Extended new command -named_pipe_loop by mode parameter

master
Thomas Schmitt 9 years ago
parent c4d11a3905
commit 5f7c0d0372
  1. 1
      xorriso/aux_objects.h
  2. 1
      xorriso/base_obj.c
  3. 6
      xorriso/opts_d_h.c
  4. 38
      xorriso/opts_i_o.c
  5. 15
      xorriso/parse_exec.c
  6. 96
      xorriso/text_io.c
  7. 29
      xorriso/xorriso.1
  8. 6
      xorriso/xorriso.h
  9. 86
      xorriso/xorriso.info
  10. 29
      xorriso/xorriso.texi
  11. 10
      xorriso/xorriso_private.h
  12. 2
      xorriso/xorriso_timestamp.h

@ -107,7 +107,6 @@ int Xorriso_lst_new(struct Xorriso_lsT **lstring, char *text,
bit0= Return new object address in *entry
bit1= do not copy data (e.g. because *data is invalid)
bit2= attach data directly by pointer rather than by copying
bit2= attach data directly by pointer rather than by copying
@return <=0 error, 1 ok
*/
int Xorriso_lst_append_binary(struct Xorriso_lsT **entry,

@ -294,6 +294,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag)
m->do_restore_sort_lba= 0;
m->do_strict_acl= 0;
m->dialog= 0;
m->buffered_dialog= NULL;
m->bsl_interpretation= 0;
m->sh_style_result= 0;
m->search_mode= 0;

@ -2098,9 +2098,13 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag)
" \"compare_sev\"|\"list_sev\" param_text",
" Enable, use, or disable message sieve. Or parse lines into",
" words. Or compare or list severity names.",
" -named_pipes_loop disk_path_stdin disk_path_stdout disk_path_stderr",
" -named_pipes_loop mode[:mode]",
" disk_path_stdin disk_path_stdout disk_path_stderr",
" Enter an EOF resistant dialog loop at a named pipe as input",
" and zero, one or two named pipes as output. \"-\" = no pipe.",
" Mode \"cleanup\" removes pipes at loop end. \"keep\" does not.",
" Mode \"buffered\" reads all lines from input pipe before it",
" opens the output pipes. \"direct\" opens after first input.",
" -launch_frontend program [args ...] --",
" Start a program, connect its stdin to xorriso stdout and",
" stderr, connect its stdout to xorriso stdin.",

@ -1091,17 +1091,43 @@ ex:;
/* Option -named_pipe_loop */
int Xorriso_option_named_pipe_loop(struct XorrisO *xorriso, char *stdin_pipe,
char *stdout_pipe, char *stderr_pipe,
int flag)
int Xorriso_option_named_pipe_loop(struct XorrisO *xorriso, char *mode,
char *stdin_pipe, char *stdout_pipe,
char *stderr_pipe, int flag)
{
char *pipe_paths[3];
int ret;
char *pipe_paths[3], *cpt, *npt;
int ret, hflag= 0, l;
npt= mode;
for(cpt= mode; npt != NULL; cpt= npt + 1) {
npt= strchr(cpt, ':');
if(npt==NULL)
l= strlen(cpt);
else
l= npt-cpt;
if(l==0) {
;
} else if(strncmp(cpt, "-", l) == 0) {
;
} else if(strncmp(cpt, "cleanup", l) == 0) {
hflag|= 1;
} else if(strncmp(cpt, "keep", l) == 0) {
hflag&= ~1;
} else if(strncmp(cpt, "buffered", l) == 0) {
hflag|= 2;
} else if(strncmp(cpt, "direct", l) == 0) {
hflag&= ~2;
} else {
sprintf(xorriso->info_text, "-named_pipe_loop: unknown mode in '%s'",
mode);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
}
pipe_paths[0]= stdin_pipe;
pipe_paths[1]= stdout_pipe;
pipe_paths[2]= stderr_pipe;
ret= Xorriso_named_pipe_loop(xorriso, pipe_paths, 0);
ret= Xorriso_named_pipe_loop(xorriso, pipe_paths, hflag);
return(ret);
}

@ -534,11 +534,12 @@ int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv,
""
};
static char arg3_commands[][40]= {
"append_partition","named_pipe_loop",
"append_partition",
""
};
static char arg4_commands[][40]= {
"cut_out","extract_cut","mount","mount_cmd","paste_in","session_string",
"cut_out","extract_cut","mount","mount_cmd","named_pipe_loop",
"paste_in","session_string",
""
};
static char argn_commands[][40]= {
@ -903,7 +904,7 @@ return:
{
int ret, was_dashed, end_ret, num1, num2, cmd_data_size= 2 * SfileadrL;
int mem_idx, arg_count, i;
char *cmd, *original_cmd, *cmd_data= NULL, *arg1, *arg2, *arg3;
char *cmd, *original_cmd, *cmd_data= NULL, *arg1, *arg2, *arg3, *arg4;
Xorriso_alloc_meM(cmd_data, char, cmd_data_size);
@ -1462,8 +1463,12 @@ next_command:;
ret= Xorriso_option_mkdiri(xorriso, argc, argv, idx, 0);
} else if(strcmp(cmd,"named_pipe_loop")==0) {
(*idx)+= 3;
ret= Xorriso_option_named_pipe_loop(xorriso, arg1, arg2, arg3, 0);
if((*idx) + 3 < argc)
arg4= argv[(*idx) + 3];
else
arg4= "";
(*idx)+= 4;
ret= Xorriso_option_named_pipe_loop(xorriso, arg1, arg2, arg3, arg4, 0);
if(ret == 3)
goto ex;

@ -67,6 +67,7 @@ int Xorriso_dialog_input(struct XorrisO *xorriso, char line[], int linesize,
bit1= do not read input (but eventually write to history)
bit2= do not write to history line which begin with "-history:" or "-history "
bit3= enforce single line dialog mode
bit4= do not read from xorriso->buffered_dialog
*/
{
char *cpt= NULL, **argv= NULL, *linept, *why_append= "";
@ -77,6 +78,7 @@ int Xorriso_dialog_input(struct XorrisO *xorriso, char line[], int linesize,
double tdiff;
struct timeval tv;
struct timezone tz;
struct Xorriso_lsT *next_lst;
gettimeofday(&tv,&tz);
tdiff= tv.tv_sec+(1.e-6*(double) tv.tv_usec);
@ -85,6 +87,16 @@ int Xorriso_dialog_input(struct XorrisO *xorriso, char line[], int linesize,
linept= line;
get_single:;
if(xorriso->buffered_dialog != NULL && !(flag & 16)) {
/* Consume next buffered line */
next_lst= Xorriso_lst_get_next(xorriso->buffered_dialog, 0);
strcpy(line, Xorriso_lst_get_text(xorriso->buffered_dialog, 0));
Xorriso_lst_destroy(&(xorriso->buffered_dialog), 0);
xorriso->buffered_dialog= next_lst;
goto process_single;
}
#ifdef Xorriso_with_readlinE
if(xorriso->use_stdin || xorriso->dev_fd_1>=0 ||
@ -121,8 +133,6 @@ get_single:;
strcpy(linept, cpt);
}
process_single:;
#else /* Xorriso_with_readlinE */
if(flag&2)
@ -138,6 +148,8 @@ process_single:;
#endif /* ! Xorriso_with_readlinE */
process_single:;
if(xorriso->dialog == 2 && !(flag & 8)) {
append_line= 0;
if(linept != line && strcmp(linept, "@@@") == 0) {
@ -3987,7 +3999,14 @@ int Xorriso_open_named_pipe(struct XorrisO *xorriso, char fd_names[3][20],
/* Usage example via bash:
in=/u/test/xorriso_stdin
out=/u/test/xorriso_stdout
mknod "$in" p
mknod "$out" p
xorriso -abort_on NEVER \
-named_pipe_loop cleanup:buffered "$in" "$out" - &
# Send command and receive result
xorriso_cmd() {
echo "$@" >/u/test/xorriso_stdin
cat </u/test/xorriso_stdout
@ -4002,14 +4021,21 @@ int Xorriso_open_named_pipe(struct XorrisO *xorriso, char fd_names[3][20],
iso_path=...arbitrary.characters...
xorriso_cmd map $(xorriso_esc "$disk_path") $(xorriso_esc "$iso_path")
*/
/* @param flag bit0= unlink pipes when the loop ends
bit1= read all lines from pipe until EOF before executing them
*/
int Xorriso_named_pipe_loop(struct XorrisO *xorriso,
char *pipe_paths[3], int flag)
{
char *line= NULL;
int i, ret, mem_fds[3], pipe_fds[3], first_line, hret;
int i, ret, mem_fds[3], pipe_fds[3], first_line, hret, pipes_are_valid= 0;
int lst_ret, filling_buffer= 0;
off_t mem_used= 0, mem_needed;
struct stat stbuf;
struct Xorriso_lsT *prev_lst= NULL;
static char fd_names[3][20] = {
"standard input", "standard output", "standard error" };
char mem_text[80], limit_text[80];
if(xorriso->tolerate_stdin_eof) {
sprintf(xorriso->info_text,
@ -4048,6 +4074,7 @@ int Xorriso_named_pipe_loop(struct XorrisO *xorriso,
ret= 0; goto ex;
}
}
pipes_are_valid= 1;
while(1) {
/* Open input pipe */
@ -4059,10 +4086,52 @@ int Xorriso_named_pipe_loop(struct XorrisO *xorriso,
/* As long as the input connection exists */
xorriso->tolerate_stdin_eof= 1;
first_line= 1;
if(flag & 2) {
filling_buffer= 8 | 16; /* single line, no reading from buffered_dialog */
prev_lst= NULL;
mem_used= 0;
}
while(1) {
/* Fetch input line */
ret= Xorriso_dialog_input(xorriso, line, SfileadrL, 1);
if((flag & 2) && xorriso->buffered_dialog == NULL && !filling_buffer) {
ret= -2; /* EOF */
} else {
ret= Xorriso_dialog_input(xorriso, line, SfileadrL, 1 | filling_buffer);
}
if((flag & 2) && filling_buffer) {
/* Fetch and buffer lines before opening output pipes */
if(ret > 0) {
/* Check for excessive memory consumption */;
mem_needed= strlen(line) + 8 + sizeof(struct Xorriso_lsT);
if(mem_used + mem_needed > xorriso->temp_mem_limit) {
Sfile_scale((double) (mem_used + mem_needed), mem_text, 5, 1e4, 0);
Sfile_scale((double) xorriso->temp_mem_limit,
limit_text, 5, 1e4, 0);
sprintf(xorriso->info_text,
"-named_pipe_loop: List of buffered input lines exceeds -temp_mem_limit (%s > %s)",
mem_text, limit_text);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
"FAILURE", 0);
ret= -1; goto ex;
}
mem_used+= mem_needed;
lst_ret= Xorriso_lst_new(&prev_lst, line, prev_lst, 0);
if(lst_ret <= 0) {
Xorriso_msgs_submit(xorriso, 0,
"-named_pipe_loop: Cannot buffer all input lines", 0, "FATAL", 0);
ret= -1;
} else {
if(xorriso->buffered_dialog == NULL)
xorriso->buffered_dialog= prev_lst;
continue;
}
}
filling_buffer= 0; /* start consuming buffer */
continue;
}
/* Open output pipes late to allow the sender to open them after
the first (and usually only) input line was transmitted:
@ -4114,10 +4183,23 @@ int Xorriso_named_pipe_loop(struct XorrisO *xorriso,
ret= 1;
ex:;
xorriso->tolerate_stdin_eof= 0;
if(flag & 2)
Xorriso_lst_destroy_all(&(xorriso->buffered_dialog), 0);
/* Close any open pipes. Restore stdin, stdout and stderr. */
for(i= 0; i < 3; i++) {
if(pipe_fds[i] != -1)
if(pipe_fds[i] != -1) {
if((flag & 1) && pipes_are_valid) {
if(stat(pipe_paths[i], &stbuf) != -1) {
if(S_ISFIFO(stbuf.st_mode)) {
sprintf(xorriso->info_text, "Removing named pipe ");
Text_shellsafe(pipe_paths[i], xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
unlink(pipe_paths[i]);
}
}
}
close(pipe_fds[i]);
}
if(mem_fds[i] != -1) {
close(i);
dup2(mem_fds[i], i);

@ -9,7 +9,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH XORRISO 1 "Version 1.3.1, Jul 02, 2013"
.TH XORRISO 1 "Version 1.3.1, Jul 03, 2013"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -4700,19 +4700,30 @@ Above example "SORRY,UPDATE" will yield 1.
Print to the result channel a blank separated list of all severity names.
Sorted from low to high severity.
.TP
\fB\-named_pipe_loop\fR disk_path_stdin disk_path_stdout disk_path_stderr
\fB\-named_pipe_loop\fR mode[:mode] disk_path_stdin disk_path_stdout disk_path_stderr
Temporarily replace standard input, standard output and standard error by
named pipes. Enter dialog mode without readline.
The three parameters must either be disk paths to existing named pipes,
.br
Defined modes are:
.br
"cleanup" removes the submitted pipe files when the loop ends.
.br
"keep" does not delete them. This is the default.
.br
"buffered" reads all lines from the input pipe until EOF before it opens
the output pipes and processes the input lines.
.br
"direct" opens the output pipes after the first input line was read.
Each line is executed directly after it is read. This is the default.
.br
The other three parameters must either be disk paths to existing named pipes,
or be "\-" to leave the according standard i/o channel unreplaced.
.br
xorriso will open the stdin pipe, read and execute dialog lines from it
until the sender closes the pipe. Then xorriso will close its side of
the pipes and enter a new cycle of opening, reading and executing.
.br
The output pipes will get opened after the first input line was
read from a freshly opened pipe. This allows the sender to first send
a very long line and to only then open an output pipe for reading the reply.
until the sender closes the pipe. The output pipes get opened depending on
mode "buffered" resp. "direct". After all lines are executed, xorriso will
close its side of the pipes and enter a new cycle of opening, reading and
executing.
.br
If an input line consists only of the word "end_named_pipe_loop"
then \-named_pipe_loop will end and further xorriso commands may be

@ -1665,9 +1665,9 @@ int Xorriso_option_mvi(struct XorrisO *xorriso, int argc, char **argv,
/* Option -named_pipe_loop */
/* @since 1.3.2 */
int Xorriso_option_named_pipe_loop(struct XorrisO *xorriso, char *stdin_pipe,
char *stdout_pipe, char *stderr_pipe,
int flag);
int Xorriso_option_named_pipe_loop(struct XorrisO *xorriso, char *mode,
char *stdin_pipe, char *stdout_pipe,
char *stderr_pipe, int flag);
/* Command -no_rc */
int Xorriso_option_no_rc(struct XorrisO *xorriso, int flag);

@ -4110,19 +4110,25 @@ File: xorriso.info, Node: Frontend, Next: ExDevices, Prev: Scripting, Up: Co
Print to the result channel a blank separated list of all severity
names. Sorted from low to high severity.
-named_pipe_loop disk_path_stdin disk_path_stdout disk_path_stderr
-named_pipe_loop mode[:mode] disk_path_stdin disk_path_stdout disk_path_stderr
Temporarily replace standard input, standard output and standard
error by named pipes. Enter dialog mode without readline. The
three parameters must either be disk paths to existing named pipes,
or be "-" to leave the according standard i/o channel unreplaced.
error by named pipes. Enter dialog mode without readline.
Defined modes are:
"cleanup" removes the submitted pipe files when the loop ends.
"keep" does not delete them. This is the default.
"buffered" reads all lines from the input pipe until EOF before it
opens the output pipes and processes the input lines.
"direct" opens the output pipes after the first input line was
read. Each line is executed directly after it is read. This is
the default.
The other three parameters must either be disk paths to existing
named pipes, or be "-" to leave the according standard i/o channel
unreplaced.
xorriso will open the stdin pipe, read and execute dialog lines
from it until the sender closes the pipe. Then xorriso will close
its side of the pipes and enter a new cycle of opening, reading
and executing.
The output pipes will get opened after the first input line was
read from a freshly opened pipe. This allows the sender to first
send a very long line and to only then open an output pipe for
reading the reply.
from it until the sender closes the pipe. The output pipes get
opened depending on mode "buffered" resp. "direct". After all
lines are executed, xorriso will close its side of the pipes and
enter a new cycle of opening, reading and executing.
If an input line consists only of the word "end_named_pipe_loop"
then -named_pipe_loop will end and further xorriso commands may be
executed from other sources.
@ -4872,7 +4878,7 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top
* -jigdo clears JTE or or adds parameter to JTE: Jigdo. (line 33)
* -joliet enables production of Joliet tree: SetWrite. (line 10)
* -launch_frontend starts frontend program at pipes: Frontend.
(line 140)
(line 146)
* -list_arg_sorting prints sorting order of -x: ArgSort. (line 27)
* -list_delimiter replaces '--': Scripting. (line 60)
* -list_extras lists compile time extra features: Scripting.
@ -4927,8 +4933,8 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top
* -print_info prints message text line: Scripting. (line 113)
* -print_mark prints synchronizing text line: Scripting. (line 116)
* -print_size predicts image size: Inquiry. (line 91)
* -prog sets program name: Frontend. (line 175)
* -prog_help prints help text: Frontend. (line 178)
* -prog sets program name: Frontend. (line 181)
* -prog_help prints help text: Frontend. (line 184)
* -prompt prompts for enter key: Scripting. (line 121)
* -publisher sets publisher id: SetWrite. (line 186)
* -pvd_info shows image id strings: Inquiry. (line 115)
@ -5089,7 +5095,7 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top
* Filter, unregister, -unregister_filter: Filter. (line 48)
* Filter, zisofs parameters, -zisofs: SetWrite. (line 272)
* Frontend program, start at pipes, -launch_frontend: Frontend.
(line 140)
(line 146)
* GPT, _definition: Extras. (line 38)
* Group, global in ISO image, -gid: SetWrite. (line 268)
* Group, in ISO image, -chgrp: Manip. (line 57)
@ -5203,7 +5209,7 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top
* Program, end without writing, -rollback_end: Scripting. (line 170)
* Program, list extra features, -list_extras: Scripting. (line 26)
* Program, print help text, -help: Scripting. (line 20)
* Program, print help text, -prog_help: Frontend. (line 178)
* Program, print help text, -prog_help: Frontend. (line 184)
* Program, print message text line, -print_info: Scripting. (line 113)
* Program, print result text line, -print: Scripting. (line 110)
* Program, print synchronizing text line, -print_mark: Scripting.
@ -5211,7 +5217,7 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top
* Program, print version, -version: Scripting. (line 23)
* Program, prompt for enter key, -prompt: Scripting. (line 121)
* Program, replace --, -list_delimiter: Scripting. (line 60)
* Program, set name, -prog: Frontend. (line 175)
* Program, set name, -prog: Frontend. (line 181)
* Program, show current settings, -status: Scripting. (line 47)
* Program, status history, -status_history_max: Scripting. (line 56)
* Program, wait a time span, -sleep: Scripting. (line 125)
@ -5320,28 +5326,28 @@ Node: Restore178554
Node: Emulation185641
Node: Scripting195943
Node: Frontend203714
Node: Examples212994
Node: ExDevices214172
Node: ExCreate214831
Node: ExDialog216116
Node: ExGrowing217381
Node: ExModifying218186
Node: ExBootable218690
Node: ExCharset219242
Node: ExPseudo220063
Node: ExCdrecord220961
Node: ExMkisofs221278
Node: ExGrowisofs222618
Node: ExException223753
Node: ExTime224207
Node: ExIncBackup224666
Node: ExRestore228646
Node: ExRecovery229579
Node: Files230149
Node: Seealso231448
Node: Bugreport232171
Node: Legal232752
Node: CommandIdx233763
Node: ConceptIdx250279
Node: Examples213321
Node: ExDevices214499
Node: ExCreate215158
Node: ExDialog216443
Node: ExGrowing217708
Node: ExModifying218513
Node: ExBootable219017
Node: ExCharset219569
Node: ExPseudo220390
Node: ExCdrecord221288
Node: ExMkisofs221605
Node: ExGrowisofs222945
Node: ExException224080
Node: ExTime224534
Node: ExIncBackup224993
Node: ExRestore228973
Node: ExRecovery229906
Node: Files230476
Node: Seealso231775
Node: Bugreport232498
Node: Legal233079
Node: CommandIdx234090
Node: ConceptIdx250606

End Tag Table

@ -50,7 +50,7 @@
@c man .\" First parameter, NAME, should be all caps
@c man .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
@c man .\" other parameters are allowed: see man(7), man(1)
@c man .TH XORRISO 1 "Version 1.3.1, Jul 02, 2013"
@c man .TH XORRISO 1 "Version 1.3.1, Jul 03, 2013"
@c man .\" Please adjust this date whenever revising the manpage.
@c man .\"
@c man .\" Some roff macros, for reference:
@ -5491,21 +5491,32 @@ Above example "SORRY,UPDATE" will yield 1.
Print to the result channel a blank separated list of all severity names.
Sorted from low to high severity.
@c man .TP
@item -named_pipe_loop disk_path_stdin disk_path_stdout disk_path_stderr
@item -named_pipe_loop mode[:mode] disk_path_stdin disk_path_stdout disk_path_stderr
@kindex -named_pipe_loop enters EOF resistant dialog
@cindex Dialog, EOF resistant, -named_pipe_loop
Temporarily replace standard input, standard output and standard error by
named pipes. Enter dialog mode without readline.
The three parameters must either be disk paths to existing named pipes,
@*
Defined modes are:
@*
"cleanup" removes the submitted pipe files when the loop ends.
@*
"keep" does not delete them. This is the default.
@*
"buffered" reads all lines from the input pipe until EOF before it opens
the output pipes and processes the input lines.
@*
"direct" opens the output pipes after the first input line was read.
Each line is executed directly after it is read. This is the default.
@*
The other three parameters must either be disk paths to existing named pipes,
or be "-" to leave the according standard i/o channel unreplaced.
@*
xorriso will open the stdin pipe, read and execute dialog lines from it
until the sender closes the pipe. Then xorriso will close its side of
the pipes and enter a new cycle of opening, reading and executing.
@*
The output pipes will get opened after the first input line was
read from a freshly opened pipe. This allows the sender to first send
a very long line and to only then open an output pipe for reading the reply.
until the sender closes the pipe. The output pipes get opened depending on
mode "buffered" resp. "direct". After all lines are executed, xorriso will
close its side of the pipes and enter a new cycle of opening, reading and
executing.
@*
If an input line consists only of the word "end_named_pipe_loop"
then -named_pipe_loop will end and further xorriso commands may be

@ -520,6 +520,8 @@ struct XorrisO { /* the global context of xorriso */
int dialog; /* 0=off , 1=single-line , 2=multi-line */
struct Xorriso_lsT *buffered_dialog; /* If not NULL : read by dialog */
int bsl_interpretation;
/* whether to run input through Sfile_bsl_interpreter():
bit0-1= dialog and quoted file reading
@ -533,6 +535,14 @@ struct XorrisO { /* the global context of xorriso */
bit6= perform backslash encoding with info texts
*/
int sh_style_result; /* Whether not to wrap into quotation marks the file
addresses reported by:
pwd pwdx ls lsd lsl lsdl lsx lsdx lslx lsdlx
du dus dux dusx findx find
and to make du* numbers left adjusted,
and not to append "/" to pwd*
*/
/* Pattern matching facility. It still carries legacy from scdbackup/askme.c
but is fully functional for xorriso.
*/

@ -1 +1 @@
#define Xorriso_timestamP "2013.07.02.123642"
#define Xorriso_timestamP "2013.07.04.094640"

Loading…
Cancel
Save