diff --git a/test/xorriso.1 b/test/xorriso.1 index 5b9480ba..6d17a645 100644 --- a/test/xorriso.1 +++ b/test/xorriso.1 @@ -2,7 +2,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 "October 27, 2007" +.TH XORRISO 1 "October 29, 2007" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -543,11 +543,12 @@ Tell the current working directory on local filesystem. .TP \fB\-ls\fR pattern List files from the current working directory in the ISO -image which match a shell pattern. (I.e. wildcards '*' '?') +image which match a shell pattern (i.e. wildcards '*' '?' '[...]'). +Note that this resembles rather shell command ls -d than command ls. .TP > \fB\-lsx\fR pattern List files from the current working directory on local filesystem -which match a shell pattern. (I.e. wildcards '*' '?', but no '/') +which match a shell pattern. .TP \fB\-ls_l\fR pattern Like -ls but also list some of the file attributes. diff --git a/test/xorriso.c b/test/xorriso.c index 529ff078..f1fee54e 100644 --- a/test/xorriso.c +++ b/test/xorriso.c @@ -1785,6 +1785,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->dialog= 0; m->search_mode= 0; m->structured_search= 1; + m->temp_mem_limit= 16*1024.0*1024.0; m->use_stdin= 0; m->result_page_length= 0; m->result_page_width= 80; @@ -2335,10 +2336,12 @@ int Xorriso__bourne_to_reg(char bourne_expr[], char reg_expr[], int flag) } -int Xorriso_prepare_regex(struct XorrisO *xorriso, char *adr, int flag) -/* - bit0= do not augment relative structured search by xorriso->wd +/* @param flag bit0= do not augment relative structured search by xorriso->wdi + bit1= return 2 if bonked at root + (caller then aborts or retries without bit0) + @return <=0 error, 1= ok , 2 */ +int Xorriso_prepare_regex(struct XorrisO *xorriso, char *adr, int flag) { int l,ret,i,count,bonked= 0,is_constant; char *cpt,*npt,adr_part[2*SfileadrL],absolute_adr[2*SfileadrL],*adr_start; @@ -2477,6 +2480,8 @@ next_adr_part:; cpt++; } if(bonked) { + if(flag&2) + return(2); sprintf(xorriso->info_text, "Your '..' bonked at the root directory."); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING",0); } @@ -4022,13 +4027,30 @@ int Xorriso_option_lsi(struct XorrisO *xorriso, char *pattern, int flag) { int ret; -/* - if(strcmp(pattern,"*")!=0 && pattern[0]) - fprintf(stderr, ">>> XORRISO : TODO : filter by pattern %s\n", pattern); -*/ +#define Xorriso_lsi_structured_patterN 1 + +#ifdef Xorriso_lsi_structured_patterN + + char **filev= NULL, *eff_pattern; + int filec= 0; + + eff_pattern= pattern; + if(pattern[0]==0) + eff_pattern= "*"; + ret= Xorriso_expand_pattern(xorriso, eff_pattern, &filec, &filev, 0); + if(ret<=0) + return(0); + ret= Xorriso_ls_filev(xorriso, filec, filev, flag&1); + Sfile_destroy_argv(&filec, &filev, 0); + if(ret<=0) + return(0); + return(1); + +#else /* Xorriso_lsi_structured_patterN */ xorriso->search_mode= 4; xorriso->structured_search= 0; + ret= Xorriso_prepare_regex(xorriso, pattern, 0); if(ret<=0) { sprintf(xorriso->info_text, @@ -4036,8 +4058,12 @@ int Xorriso_option_lsi(struct XorrisO *xorriso, char *pattern, int flag) Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); return(0); } + ret= Xorriso_ls(xorriso, flag&1); return(ret); + +#endif /* ! Xorriso_lsi_structured_patterN */ + } diff --git a/test/xorriso_private.h b/test/xorriso_private.h index 7f19717b..a693b423 100644 --- a/test/xorriso_private.h +++ b/test/xorriso_private.h @@ -109,12 +109,13 @@ struct XorrisO { /* the global context of xorriso */ 4= shell parser expression for leaf name */ int structured_search; - /* ( 0= flat text search ) + /* 0= flat text search 1= '/' is a significant separator that cannot be matched by wildcards ( 2= like 1 : but report only occurence in tree, no payload, no location ) ( 3= like 2 : but report first content level of matching directories ) 4= actually not structured but unique find mode (with search_mode 4) */ + double temp_mem_limit; int use_stdin; /* use raw stdin even if readline support is compiled */ int result_page_length; @@ -192,8 +193,16 @@ double Sfile_microtime(int flag); int Sfile_add_to_path(char path[SfileadrL], char *addon, int flag); +int Sfile_scale(double value, char *result, int siz, double thresh, int flag); + +int Sfile_destroy_argv(int *argc, char ***argv, int flag); + char *Text_shellsafe(char *in_text, char *out_text, int flag); +int Sort_argv(int argc, char **argv, int flag); + + +#define Xorriso_lsi_structured_patterN 1 #endif /* Xorriso_private_includeD */ diff --git a/test/xorriso_timestamp.h b/test/xorriso_timestamp.h index bbbef1d8..7c42f647 100644 --- a/test/xorriso_timestamp.h +++ b/test/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2007.10.28.174550" +#define Xorriso_timestamP "2007.10.29.213920" diff --git a/test/xorrisoburn.c b/test/xorrisoburn.c index 985c22be..c880404e 100644 --- a/test/xorrisoburn.c +++ b/test/xorrisoburn.c @@ -1237,6 +1237,111 @@ int Xorriso_rmi(struct XorrisO *xorriso, char *path, int flag) } +#ifdef Xorriso_lsi_structured_patterN + +/* @param flag bit0= long format */ +int Xorriso_ls_filev(struct XorrisO *xorriso, int filec, char **filev, + int flag) +{ + int i, ret; + struct iso_tree_node *node; + struct iso_volume *volume; + char sfe[4*SfileadrL], path[SfileadrL], *rpt, perms[10]; + mode_t st_mode; + off_t size; + time_t mtime; + struct tm tms, *tmpt; + static char months[12][4]= { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + rpt= xorriso->result_line; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + + Sort_argv(filec, filev, 0); + + for(i= 0; iwdi); + if(Sfile_add_to_path(path, filev[i], 0)<=0) { +much_too_long:; + sprintf(xorriso->info_text, + "Path for file listing gets much too long (%d)", + strlen(path)+strlen(filev[i])+1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + continue; + } + } else + if(Sfile_str(path, filev[i], 0)<=0) + goto much_too_long; + + node= iso_tree_volume_path_to_node(volume,path); + if(node==NULL) { + sprintf(xorriso->info_text, + "Internal error: Unexpectedly missing node %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + + rpt[0]= 0; + if(flag&1) { + if(LIBISO_ISDIR(node)) + strcat(rpt, "d"); + else if(LIBISO_ISREG(node)) + strcat(rpt, "-"); + else if(LIBISO_ISLNK(node)) + strcat(rpt, "l"); + else + strcat(rpt, "?"); + + st_mode= iso_tree_node_get_permissions(node); + strcpy(perms,"---------"); + if(st_mode&S_IRUSR) perms[0]= 'r'; + if(st_mode&S_IWUSR) perms[1]= 'w'; + if(st_mode&S_IXUSR) perms[2]= 'x'; + if(st_mode&S_IRGRP) perms[3]= 'r'; + if(st_mode&S_IWGRP) perms[4]= 'w'; + if(st_mode&S_IXGRP) perms[5]= 'x'; + if(st_mode&S_IROTH) perms[6]= 'r'; + if(st_mode&S_IWOTH) perms[7]= 'w'; + if(st_mode&S_IXOTH) perms[8]= 'x'; + strcat(rpt, perms); + + /* >>> With directories this should be : number of subdirs + 2 */ + /* >>> ??? How to obtain RR hardlink number for other types ? */ + strcat(rpt," 1 "); + + sprintf(rpt+strlen(rpt), "%-8lu ", + (unsigned long) iso_tree_node_get_uid(node)); + sprintf(rpt+strlen(rpt), "%-8lu ", + (unsigned long) iso_tree_node_get_gid(node)); + size= iso_tree_node_get_size(node); + sprintf(rpt+strlen(rpt), "%8.f ",(double) size); + mtime= iso_tree_node_get_mtime(node); + tmpt= localtime_r(&mtime, &tms); + if(tmpt==0) + sprintf(rpt+strlen(rpt), "%12.f ",(double) mtime); + else if(time(0)-mtime < 180*86400) + sprintf(rpt+strlen(rpt), "%3s %2d %2.2d:%2.2d ", + months[tms.tm_mon], tms.tm_mday, tms.tm_hour, tms.tm_min); + else + sprintf(rpt+strlen(rpt), "%3s %2d %4.4d ", + months[tms.tm_mon], tms.tm_mday, 1900+tms.tm_year); + + } + sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n", + Text_shellsafe(filev[i], sfe, 0)); + Xorriso_result(xorriso, 0); + } + return(1); +} + + +#else /* Xorriso_lsi_structured_patterN */ + int Xorriso__node_name_cmp(const void *node1, const void *node2) { char *name1, *name2; @@ -1288,7 +1393,7 @@ wdi_is_not_a_dir:; iter= iso_tree_node_children(dir_node); Xorriso_process_msg_queues(xorriso,0); - for(i= 0; (node= iso_tree_iter_next(iter)) != NULL && ire_fill==0) { /* This is the empty pattern representing root */ + if(flag&1) { + *filec++; + (*mem)+= 8; + return(1); + } else { + if(*filec >= count_limit) + goto unexpected_change; + filev[*filec]= strdup("/"); + if(filev[*filec]==NULL) + goto out_of_memory; + (*filec)++; + return(1); + } + } + iter= iso_tree_node_children(dir); + if(iter==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, "Cannot obtain ISO directory iterator"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + for(i= 0; (node= iso_tree_iter_next(iter)) != NULL; ) { + name= (char *) iso_tree_node_get_name(node); + if(wd[0]!=0 || (flag&4)) { + if(strlen(wd)+1>=SfileadrL) + goto much_too_long; + strcpy(adr, wd); + if(Sfile_add_to_path(adr, name, 0)<=0) { +much_too_long:; + sprintf(xorriso->info_text, + "Path for pattern matching gets much too long (%d)", + strlen(adr)+strlen(name)+1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + } else { + if(strlen(name)+1>=SfileadrL) + goto much_too_long; + strcpy(adr, name); + } + + ret= Xorriso_regexec(xorriso, adr, &failed_at, 0); + if(ret) { /* no match */ + if(!LIBISO_ISDIR(node)) + continue; + /* dive deeper */ + ret= Xorriso_obtain_pattern_files( + xorriso, adr, (struct iso_tree_node_dir *) node, + filec, filev, count_limit, mem, flag|2); + if(ret<=0) + return(ret); + } else { + if(flag&1) { + (*filec)++; + l= strlen(adr)+1; + (*mem)+= sizeof(char *)+l; + if(l % sizeof(char *)) + (*mem)+= sizeof(char *)-(l % sizeof(char *)); + } else { + if(*filec >= count_limit) { +unexpected_change:; + sprintf(xorriso->info_text, + "Number of matching files changed unexpectedly (> %d)", + count_limit); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + filev[*filec]= strdup(adr); + if(filev[*filec]==NULL) { +out_of_memory:; + sprintf(xorriso->info_text, + "Cannot allocate enough memory (%d bytes) for pattern expansion", + strlen(adr)+1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } + (*filec)++; + } + } + } + return(1); +} + + +int Xorriso_expand_pattern(struct XorrisO *xorriso, char *pattern, + int *filec, char ***filev, int flag) +{ + int ret, count= 0, abs_adr= 0; + off_t mem= 0; + char mem_text[80], limit_text[80], sfe[4*SfileadrL]; + struct iso_volume *volume; + struct iso_tree_node_dir *dir; + + *filec= 0; + *filev= NULL; + + xorriso->search_mode= 3; + xorriso->structured_search= 1; + ret= Xorriso_prepare_regex(xorriso, pattern, 1|2); + if(ret==2) { + ret= Xorriso_prepare_regex(xorriso, pattern, 0); + abs_adr= 4; + } + if(ret<=0) { + sprintf(xorriso->info_text, + "Cannot compile pattern to regular expression: %s", pattern); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + + if(pattern[0]=='/' || abs_adr) { + dir= iso_volume_get_root(volume); + if(dir==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "While expanding pattern %s : Cannot obtain root node of ISO image", + Text_shellsafe(pattern, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + ret= -1; goto ex; + } + abs_adr= 4; + } else { + dir= (struct iso_tree_node_dir *) + iso_tree_volume_path_to_node(volume,xorriso->wdi); + if(dir==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "While expanding pattern %s : Working directory does not exist in ISO image", + Text_shellsafe(pattern, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + ret= 0; goto ex; + } + if(!LIBISO_ISDIR((struct iso_tree_node *) dir)) { + sprintf(xorriso->info_text, + "Working directory path does not lead to a directory in ISO image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + ret= 0; goto ex; + } + } + + /* count matches */ + ret= Xorriso_obtain_pattern_files(xorriso, "", dir, &count, NULL, 0, &mem, + 1 | abs_adr); + if(ret<=0) + goto ex; + if(count<=0) + {ret= 0; goto ex;} + + Sfile_scale((double) mem, mem_text,5,1e4,1); + sprintf(xorriso->info_text, + "Temporary memory needed for pattern expansion : %s", mem_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + if(count*sizeof(char *)+mem > xorriso->temp_mem_limit) { + Sfile_scale((double) xorriso->temp_mem_limit, limit_text,5,1e4,1); + sprintf(xorriso->info_text, + "List of matching file addresses exceeds -temp_mem_limit (%s > %s)", + mem_text, limit_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + ret= 0; goto ex; + } + + (*filev)= (char **) calloc(sizeof(char *), count); + if(*filev==NULL) { + Sfile_scale((double) mem, mem_text,5,1e4,1); + sprintf(xorriso->info_text, + "Cannot allocate enough memory (%s) for pattern expansion", + mem_text); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + ret= -1; goto ex; + } + + /* now store store addresses */ + ret= Xorriso_obtain_pattern_files(xorriso, "", dir, filec, *filev, count, + &mem, abs_adr); + if(ret<=0) + goto ex; + + ret= 1; +ex:; + if(ret<=0) { + if(filev!=NULL) + Sfile_destroy_argv(&count, filev, 0); + *filec= 0; + } + return(ret); +} + diff --git a/test/xorrisoburn.h b/test/xorrisoburn.h index c4942461..ddf6e02e 100644 --- a/test/xorrisoburn.h +++ b/test/xorrisoburn.h @@ -14,6 +14,8 @@ #ifndef Xorrisoburn_includeD #define Xorrisoburn_includeD yes +#define Xorriso_lsi_structured_patterN 1 + struct XorrisO; struct burn_drive; @@ -55,9 +57,21 @@ int Xorriso_format_media(struct XorrisO *xorriso, int flag); */ int Xorriso_rmi(struct XorrisO *xorriso, char *path, int flag); + +#ifdef Xorriso_lsi_structured_patterN + +/* @param flag bit0= long format */ +int Xorriso_ls_filev(struct XorrisO *xorriso, int filec, char **filev, + int flag); + +#else /* Xorriso_lsi_structured_patterN */ + /* @param flag bit0= long format , bit1= only check for directory existence */ int Xorriso_ls(struct XorrisO *xorriso, int flag); +#endif /* ! Xorriso_lsi_structured_patterN */ + + /* @param eff_path returns resulting effective path. Must provide at least SfileadrL bytes of storage. @param flag bit0= do not produce problem events (unless faulty path format) @@ -76,5 +90,8 @@ int Xorriso_rename(struct XorrisO *xorriso, char *origin, char *dest,int flag); */ int Xorriso_mkdir(struct XorrisO *xorriso, char *img_path, int flag); +int Xorriso_expand_pattern(struct XorrisO *xorriso, char *pattern, + int *filec, char ***filev, int flag); + #endif /* Xorrisoburn_includeD */