diff --git a/libisoburn/libisoburn.ver b/libisoburn/libisoburn.ver index 90039c30..d18d4da3 100644 --- a/libisoburn/libisoburn.ver +++ b/libisoburn/libisoburn.ver @@ -303,6 +303,11 @@ Xorriso_pull_outlists; Xorriso_push_outlists; Xorriso_read_rc; Xorriso_set_problem_status; +Xorriso_sieve_add_filter; +Xorriso_sieve_big; +Xorriso_sieve_clear_results; +Xorriso_sieve_dispose; +Xorriso_sieve_get_result; Xorriso_start_msg_watcher; Xorriso_startup_libraries; Xorriso_stop_msg_watcher; diff --git a/xorriso/base_obj.c b/xorriso/base_obj.c index 0392ac57..cbd84a1e 100644 --- a/xorriso/base_obj.c +++ b/xorriso/base_obj.c @@ -330,6 +330,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->msgw_stack_handle= -1; m->msgw_msg_pending= 0; m->msgw_fetch_lock_ini= 0; + m->msg_sieve= NULL; m->msglist_stackfill= 0; m->status_history_max= Xorriso_status_history_maX; m->scsi_log= 0; @@ -566,6 +567,7 @@ int Xorriso_destroy(struct XorrisO **xorriso, int flag) pthread_mutex_destroy(&(m->msg_watcher_lock)); if(m->msgw_fetch_lock_ini) pthread_mutex_destroy(&(m->msgw_fetch_lock)); + Xorriso_sieve_dispose(m, 0); free((char *) m); *xorriso= NULL; diff --git a/xorriso/opts_p_z.c b/xorriso/opts_p_z.c index 27bac802..b25c5daa 100644 --- a/xorriso/opts_p_z.c +++ b/xorriso/opts_p_z.c @@ -1781,9 +1781,10 @@ int Xorriso_option_version(struct XorrisO *xorriso, int flag) "xorriso version : %d.%d.%d%s\n", Xorriso_header_version_majoR, Xorriso_header_version_minoR, Xorriso_header_version_micrO, Xorriso_program_patch_leveL); - sprintf(xorriso->result_line+strlen(xorriso->result_line), - "Version timestamp : %s\n",Xorriso_timestamP); - sprintf(xorriso->result_line+strlen(xorriso->result_line), + Xorriso_result(xorriso, 0); + sprintf(xorriso->result_line, "Version timestamp : %s\n",Xorriso_timestamP); + Xorriso_result(xorriso, 0); + sprintf(xorriso->result_line, "Build timestamp : %s\n",Xorriso_build_timestamP); Xorriso_result(xorriso, 0); Xorriso_report_lib_versions(xorriso, 0); diff --git a/xorriso/parse_exec.c b/xorriso/parse_exec.c index f5a258b6..26e0fd42 100644 --- a/xorriso/parse_exec.c +++ b/xorriso/parse_exec.c @@ -1738,7 +1738,8 @@ next_command:; struct Xorriso_lsT *info_list, int *line_count, int flag); int pargc, pflag, max_words; - char **pargv= NULL, *pline, *prefix, *separators, *sev1, *sev2; + char **pargv= NULL, *pline, *prefix, *separators, *sev1, *sev2, *name; + int available; (*idx)++; if(strcmp(arg1, "push") == 0) { @@ -1822,6 +1823,35 @@ next_command:; "xorriso_test: Xorriso__severity_cmp(\"%s\", \"%s\")= %d\n", sev1, sev2, ret); + } else if(strcmp(arg1, "sieve_big") == 0) { + ret= Xorriso_sieve_big(xorriso, 0); + fprintf(stderr, "xorriso_test: Xorriso_sieve_big: ret= %d\n", ret); + + } else if(strcmp(arg1, "sieve_get_result") == 0) { + (*idx)++; + sev1= "Media summary:"; + if(*idx - 1 < argc) + name= argv[*idx - 1]; + ret= Xorriso_sieve_get_result(xorriso, name, &pargc, &pargv, &available, + 0); + fprintf(stderr, + "xorriso_test: _sieve_get_result: ret= %d , argc= %d , argv= 0x%lX\n", + ret, pargc, (unsigned long) pargv); + if(ret == 1) + for(i= 0; i < pargc; i++) + fprintf(stderr, "xorriso_test: argv[%d]= '%s'\n", i, pargv[i]); + Xorriso__dispose_words(&pargc, &pargv); + fprintf(stderr, "xorriso_test: available= %d\n", available); + + } else if(strcmp(arg1, "sieve_clear") == 0) { + ret= Xorriso_sieve_clear_results(xorriso, 0); + fprintf(stderr, "xorriso_test: Xorriso_sieve_clear_results: ret= %d\n", + ret); + + } else if(strcmp(arg1, "sieve_dispose") == 0) { + ret= Xorriso_sieve_dispose(xorriso, 0); + fprintf(stderr, "xorriso_test: Xorriso_sieve_dispose: ret= %d\n", ret); + } else if(strcmp(arg1, "help") == 0) { fprintf(stderr, "-test [mode] [arguments]\n"); fprintf(stderr, " push\n"); @@ -1847,6 +1877,14 @@ next_command:; fprintf(stderr, " parse by Xorriso_parse_line(NULL, ...)\n"); fprintf(stderr, " severity_cmp sev1 sev2\n"); fprintf(stderr, " perform Xorriso__severity_cmp()\n"); + fprintf(stderr, " sieve_big\n"); + fprintf(stderr, " perform Xorriso_sieve_big()\n"); + fprintf(stderr, " sieve_get_result name\n"); + fprintf(stderr, " perform Xorriso_sieve_get_result()\n"); + fprintf(stderr, " sieve_clear\n"); + fprintf(stderr, " perform Xorriso_sieve_clear_results()\n"); + fprintf(stderr, " sieve_dispose\n"); + fprintf(stderr, " perform Xorriso_sieve_dispose()\n"); } else { fprintf(stderr, "xorriso -test: unknwon mode: %s\n", arg1); } diff --git a/xorriso/text_io.c b/xorriso/text_io.c index 4e85ba7a..b5bbbe34 100644 --- a/xorriso/text_io.c +++ b/xorriso/text_io.c @@ -633,6 +633,7 @@ bit15= with bit1 to bit3: close depicted log file FILE *logfile_fp, *pktlog_fp; static int num_channels= 4; static char channel_prefixes[4][4]= {".","R","I","M"}; + int Xorriso_sieve_filter_msg(struct XorrisO *xorriso, char *msg, int flag); #ifdef Xorriso_fetch_with_msg_queueS static int complaints= 0, complaint_limit= 5; @@ -705,7 +706,7 @@ bit15= with bit1 to bit3: close depicted log file if(xorriso->stderr_fp == NULL) {ret= 0; goto ex;} } - if(flag & (2| 4 | 8)) + if(flag & (2 | 4 | 8)) {ret= 1; goto ex;} /* Eventually perform backslash encoding of non-printable characters */ @@ -716,7 +717,11 @@ bit15= with bit1 to bit3: close depicted log file {ret= -1; goto ex;} } - /* Eventually perform messag redirection */ + /* Pick interesting words for the Xorriso_sieve API */ + Xorriso_sieve_filter_msg(xorriso, text, + (channel_no > 0 ? channel_no - 1 : 0)); + + /* Eventually perform message redirection */ if(xorriso->msglist_stackfill > 0) { if(xorriso->msglist_flags[xorriso->msglist_stackfill - 1] & 1) result_redirected= 1; @@ -1374,6 +1379,572 @@ ex:; } +/* -------------------------- Xorriso_msg_sievE -------------------------- */ + +struct Xorriso_msg_filteR { + char *name; + char *prefix; + char *separators; + int channels; /* What to watch: bit0=result , bit1=info , bit2=mark */ + + int num_words; + int *word_idx; + int last_word_line_end; + + /* Oldest result gets discarded when new surpassed threshold */ + int max_results; + + struct Xorriso_lsT *results; /* Serialized tuples of num_words */ + int num_results; + int num_delivered; + struct Xorriso_lsT *next_to_deliver; + + struct Xorriso_msg_filteR *prev; + struct Xorriso_msg_filteR *next; +}; +int Xorriso_msg_filter_destroy(struct Xorriso_msg_filteR **o, int flag); + + +int Xorriso_msg_filter_new(struct Xorriso_msg_filteR **o, char *name, + struct Xorriso_msg_filteR *prev, + struct Xorriso_msg_filteR *next, + int flag) +{ + struct Xorriso_msg_filteR *m; + + m= (*o)= TSOB_FELD(struct Xorriso_msg_filteR, 1); + if((*o) == NULL) + return(-1); + m->name= NULL; + m->prefix= NULL; + m->separators= NULL; + m->channels= 7; + m->num_words= 0; + m->word_idx= NULL; + m->last_word_line_end= flag & 1; + m->max_results= 1; + m->results= NULL; + m->num_results= 0; + m->num_delivered= 0; + m->next_to_deliver= NULL; + + m->name= strdup(name); + if(m->name == NULL) + goto failure; + + m->prev= prev; + if(prev != NULL) + prev->next= m; + m->next= next; + if(next != NULL) + next->prev= m; + return(1); +failure: + Xorriso_msg_filter_destroy(o, 0); + return(-1); +} + + +int Xorriso_msg_filter_destroy(struct Xorriso_msg_filteR **o, int flag) +{ + struct Xorriso_msg_filteR *m; + + if((*o)==NULL) + return(0); + m= *o; + if(m->name != NULL) + free(m->name); + if(m->prefix != NULL) + free(m->prefix); + if(m->separators != NULL) + free(m->separators); + if(m->word_idx != NULL) + free((char *) m->word_idx); + if(m->results != NULL) + Xorriso_lst_destroy_all(&(m->results), 0); + if(m->prev != NULL) + m->prev->next= m->next; + if(m->next != NULL) + m->next->prev= m->prev; + + free(*o); + *o= NULL; + return(1); +} + + +int Xorriso_msg_filter_set_words(struct Xorriso_msg_filteR *m, + int num_words, int *word_idx, int flag) +{ + int i; + + if(m->word_idx != NULL) + free(m->word_idx); + m->num_words= 0; + if(num_words <= 0) + return(1); + m->word_idx= TSOB_FELD(int, num_words); + if(m->word_idx == NULL) + return(-1); + for(i= 0; i < num_words; i++) + m->word_idx[i]= word_idx[i]; + m->num_words= num_words; + return(1); +} + + +struct Xorriso_msg_sievE { + + int num_filters; + + struct Xorriso_msg_filteR *first_filter; + +}; + + +int Xorriso_msg_sieve_new(struct Xorriso_msg_sievE **o, int flag) +{ + struct Xorriso_msg_sievE *m; + + m= (*o)= TSOB_FELD(struct Xorriso_msg_sievE, 1); + if((*o) == NULL) + return(-1); + m->num_filters= 0; + m->first_filter= NULL; + return(1); +} + + +int Xorriso_msg_sieve_destroy(struct Xorriso_msg_sievE **o, int flag) +{ + struct Xorriso_msg_sievE *m; + struct Xorriso_msg_filteR *f, *next_f= NULL; + + if((*o) == NULL) + return(0); + m= *o; + for(f= m->first_filter; f != NULL; f= next_f) { + next_f= f->next; + Xorriso_msg_filter_destroy(&f, 0); + } + free(*o); + *o= NULL; + return(1); +} + + +/* API */ +int Xorriso_sieve_add_filter(struct XorrisO *xorriso, char *name, + int channels, char *prefix, char *separators, + int num_words, int *word_idx, int max_results, + int flag) +{ + int ret; + struct Xorriso_msg_sievE *sieve= NULL; + struct Xorriso_msg_filteR *filter; + + if(xorriso->msg_sieve == NULL) { + ret= Xorriso_msg_sieve_new(&sieve, 0); + if(ret <= 0) + goto no_mem; + xorriso->msg_sieve= sieve; + } else + sieve= xorriso->msg_sieve; + ret= Xorriso_msg_filter_new(&filter, name, NULL, sieve->first_filter, + flag & 1); + if(ret <= 0) + goto no_mem; + sieve->first_filter= filter; + ret= Xorriso_msg_filter_set_words(filter, num_words, word_idx, 0); + if(ret <= 0) + goto no_mem; + if(prefix != NULL) + filter->prefix= strdup(prefix); + if(separators != NULL) + filter->separators= strdup(separators); + filter->channels= channels; + filter->max_results= max_results; + (sieve->num_filters)++; + return(1); + +no_mem:; + Xorriso_msg_sieve_destroy(&sieve, 0); + Xorriso_no_malloc_memory(xorriso, NULL, 0); + return(-1); +} + + +/* API */ +int Xorriso_sieve_dispose(struct XorrisO *xorriso, int flag) +{ + Xorriso_msg_sieve_destroy(&(xorriso->msg_sieve), 0); + return(1); +} + + +/* API */ +int Xorriso_sieve_clear_results(struct XorrisO *xorriso, int flag) +{ + struct Xorriso_msg_filteR *f; + + for(f= xorriso->msg_sieve->first_filter; f != NULL; f= f->next) { + f->num_results= 0; + f->num_delivered= 0; + if(f->results != NULL) + Xorriso_lst_destroy_all(&(f->results), 0); + f->next_to_deliver= NULL; + } + return(1); +} + + +/* API */ +/* @param flag bit0= Reset reading to first matching result + bit1= Only inquire number of available results. + Do not allocate memory. + bit2= If *argv is not NULL, then free it before attaching + new memory. +*/ +int Xorriso_sieve_get_result(struct XorrisO *xorriso, char *name, + int *argc, char ***argv, int *available, int flag) +{ + struct Xorriso_msg_filteR *f; + struct Xorriso_lsT *lst; + int i; + + if(flag & 4) + Xorriso__dispose_words(argc, argv); + *argc= 0; + *argv= NULL; + + if(xorriso->msg_sieve == NULL) + return(0); + + for(f= xorriso->msg_sieve->first_filter; f != NULL; f= f->next) { + if(strcmp(f->name, name) != 0) + continue; + *available= f->num_results - f->num_delivered; + if(*available <= 0) + break; + if(flag & 2) + return(1); + + if(flag & 1) { + f->num_delivered= 0; + f->next_to_deliver= NULL; + } + if(f->next_to_deliver == NULL) { + f->next_to_deliver= f->results; + for(i= 0; i < f->num_words * f->num_delivered; i++) + if(f->next_to_deliver != NULL) + f->next_to_deliver= Xorriso_lst_get_next(f->next_to_deliver, 0); + } + if(f->next_to_deliver == NULL) { + /* Should not happen */ + *available= 0; + break; + } + if(f->num_words <= 0) + return(1); + + *argv= calloc(f->num_words, sizeof(char *)); + if(*argv == NULL) + goto no_mem; + *argc= f->num_words; + for(i= 0; i < *argc; i++) + (*argv)[i]= NULL; + + lst= f->next_to_deliver; + for(i= 0; i < *argc; i++) { + if(lst != NULL) { + (*argv)[i]= strdup(Xorriso_lst_get_text(lst, 0)); + if((*argv)[i] == NULL) + goto no_mem; + } else { + + /* >>> ??? should not happen */; + + } + lst= Xorriso_lst_get_next(lst, 0); + } + f->next_to_deliver= lst; + (f->num_delivered)++; + (*available)--; + return(1); + } + return(0); +no_mem: + if(*argv != NULL) + Xorriso__dispose_words(argc, argv); + Xorriso_no_malloc_memory(xorriso, NULL, 0); + return(-1); +} + + +int Xorriso_sieve_big(struct XorrisO *xorriso, int flag) +{ + struct Xorriso_sieve_big_filteR { + char *name; + int channels; + char *prefix; + char *separators; + int num_words; + int word_idx[6]; + int max_results; + int flag; + }; + static struct Xorriso_sieve_big_filteR filters[] = { + {"Drive current:", 3, "Drive current:", "", 2, { 0, 1, -1, -1, -1, -1}, + 2, 0}, + {"Drive type :", 3, "Drive type :", "", 3, { 1, 3, 5, -1, -1, -1}, + 2, 0}, + {"Media current:", 3, "Media current: ", "", 1, { 0, -1, -1, -1, -1, -1}, + 2, 1}, + {"Media status :", 3, "Media status : ", "", 1, { 0, -1, -1, -1, -1, -1}, + 2, 1}, + {"Media blocks :", 3, "Media blocks :", "", 3, { 0, 3, 6, -1, -1, -1}, + 2, 0}, + {"Media summary:", 3, "Media summary:", "", 4, { 0, 2, 5, 7, -1, -1}, + 2, 0}, + {"Media nwa :", 3, "Media nwa :", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"Volume id :", 3, "Volume id :", "", 1, { 0, -1, -1, -1, -1, -1}, + 2, 0}, + {"ISO session :", 3, "ISO session :", "", 4, { 0, 2, 4, 6, -1, -1}, + 10000, 1}, + {"Image size :", 3, "Image size :", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"Media space :", 3, "Image size :", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"After commit :", 3, "Image size :", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"PVD address :", 3, "PVD address :", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"Volume Id :", 3, "Volume Id : ", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 1}, + {"Volume Set Id:", 3, "Volume Set Id: ", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 1}, + {"Publisher Id :", 3, "Publisher Id : ", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 1}, + {"Preparer Id :", 3, "Preparer Id : ", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 1}, + {"App Id :", 3, "App Id : ", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 1}, + {"System Id :", 3, "System Id : ", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 1}, + {"CopyrightFile:", 3, "CopyrightFile: ", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 1}, + {"Abstract File:", 3, "Abstract File: ", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 1}, + {"Biblio File :", 3, "Biblio File : ", "", 1, { 0, -1, -1, -1, -1, -1}, + 1, 1}, + {"Write speed :", 3, "Write speed :", "", 2, { 0, 2, -1, -1, -1, -1}, + 100, 0}, + {"Write speed H:", 3, "Write speed H:", "", 2, { 0, 2, -1, -1, -1, -1}, + 1, 0}, + {"Write speed L:", 3, "Write speed L:", "", 2, { 0, 2, -1, -1, -1, -1}, + 1, 0}, + {"Write speed h:", 3, "Write speed h:", "", 2, { 0, 2, -1, -1, -1, -1}, + 1, 0}, + {"Write speed l:", 3, "Write speed l:", "", 2, { 0, 2, -1, -1, -1, -1}, + 1, 0}, + {"Format status:", 3, "Format status:", ", ", 2, { 0, 1, -1, -1, -1, -1}, + 1, 1}, + {"Format idx :", 3, "Format idx ", ",: ", 4, { 0, 1, 2, 3, -1, -1}, + 100, 1}, + {"Profile :", 3, "Profile :", "", 2, { 0, 1, -1, -1, -1, -1}, + 256, 1}, + {"-changes_pending", 3, "-changes_pending ", "", 1, + { 0, -1, -1, -1, -1, -1}, 1, 0}, + {"Media region :", 3, "Media region :", "", 3, { 0, 2, 4, -1, -1, -1}, + 10000, 1}, + {"MD5 tag range:", 3, "MD5 tag range:", "", 3, { 0, 2, 4, -1, -1, -1}, + 10000, 1}, + {"Local ACL :", 3, "Local ACL :", ", ", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"Local xattr :", 3, "Local xattr :", ", ", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"Jigdo files :", 3, "Jigdo files :", ", ", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"zisofs :", 3, "zisofs :", ", ", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"Ext. filters :", 3, "Ext. filters : ", ", ", 1, { 0, -1, -1, -1, -1, -1}, + 1, 1}, + {"DVD obs 64 kB:", 3, "DVD obs 64 kB:", ", ", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"Readline :", 3, "Readline :", ", ", 1, { 0, -1, -1, -1, -1, -1}, + 1, 0}, + {"xorriso version :", 3, "xorriso version :", ", ", 1, + { 0, -1, -1, -1, -1, -1}, 1, 0}, + {"Version timestamp :", 3, "Version timestamp :", ", ", 1, + { 0, -1, -1, -1, -1, -1}, 1, 0}, + {"Build timestamp :", 3, "Build timestamp : ", ", ", 1, + { 0, -1, -1, -1, -1, -1}, 1, 1}, + {"libisofs in use :", 3, "libisofs in use :", ", ", 2, + { 0, 1, -1, -1, -1, -1}, 1, 1}, + {"libjte in use :", 3, "libjte in use :", ", ", 2, + { 0, 1, -1, -1, -1, -1}, 1, 1}, + {"libburn in use :", 3, "libburn in use :", ", ", 2, + { 0, 1, -1, -1, -1, -1}, 1, 1}, + {"libburn OS adapter:", 3, "libburn OS adapter: ", ", ", 1, + { 0, -1, -1, -1, -1, -1}, 1, 1}, + {"libisoburn in use :", 3, "libisoburn in use :", ", ", 2, + { 0, 1, -1, -1, -1, -1}, 1, 1}, + {"@", 0, "@", "", 0, {-1, -1, -1, -1, -1, -1}, 0, 0} + }; + +/* Problem cases: + <<< + -devices -device_links + have no well recognizable prefix + + -pwd -pwdx + have a headline and a value line + + -ls* , -getfacl* , -getfattr* , -du* , -compare* , -show_stream* + have no well recognizable prefix + + Todo: + -find -exec + report_damage report_lba getfacl getfattr get_any_xattr list_extattr + get_md5 check_md5 get_hfs_crtp get_hfs_bless show_stream estimate_size + + +*/ + struct Xorriso_sieve_big_filteR *f; + int ret, i, num_filters= 1000; + + for(i= 0; i < num_filters; i++) { + f= &(filters[i]); + if(strcmp(f->name, "@") == 0) + break; + ret= Xorriso_sieve_add_filter(xorriso, f->name, f->channels, f->prefix, + f->separators, f->num_words, f->word_idx, + f->max_results, f->flag); + if(ret <= 0) + goto failure; + } + return(1); +failure: + Xorriso_sieve_dispose(xorriso, 0); + return(-1); +} + + +/* Check for matching filter and eventually extract words. + To be called by Xorriso_result, Xorriso_info, Xorriso_mark, + and alike. + Thus no own message output is allowed here ! + @param flag bit0-1= channel: + 0= result channel + 1= info channel + 2= mark channel +*/ +int Xorriso_sieve_filter_msg(struct XorrisO *xorriso, char *msg, int flag) +{ + int channel, ret, argc= 0, i, max_words, l, widx; + char **argv= NULL; + struct Xorriso_msg_filteR *f; + struct Xorriso_lsT *lst, *prev_lst, *next_lst; + + if(xorriso->msg_sieve == NULL) + return(1); + + channel= flag & 3; + + for(f= xorriso->msg_sieve->first_filter; f != NULL; f= f->next) { + if(!(f->channels & (1 << channel))) + continue; + if(f->prefix[0]) + if(strncmp(f->prefix, msg, strlen(f->prefix)) != 0) + continue; + max_words= 0; + if(f->last_word_line_end) + if(f->num_words > 0) /* Let last word take rest of line */ + max_words= f->word_idx[f->num_words - 1]; + if(max_words <= 0 && f->last_word_line_end) { + /* Copy rest of line as single word because Xorriso_parse_line understands + max_words == 0 as unlimited number of words. But here it is desired + to get the rest of line already in argv[0]. + */ + max_words= 0; + argv= calloc(1, sizeof(char *)); + if(argv == NULL) + goto no_mem; + argc= 1; + argv[0]= strdup(msg + strlen(f->prefix)); + if(argv[0] == NULL) + goto no_mem; + ret= 1; + } else { + ret= Xorriso_parse_line(xorriso, msg, f->prefix, f->separators, max_words, + &argc, &argv, 0); + } + if(ret < 0) + goto ex; + if(ret == 0) + continue; + + if(f->last_word_line_end) { + l= strlen(argv[max_words]); + if(l > 0) + if(argv[max_words][l - 1] == '\n') + argv[max_words][l - 1]= 0; + } + + if(f->max_results > 0 && f->num_results >= f->max_results) { + /* Dispose surplus results */ + for(i= 0; i < f->num_words; i++) { + if(f->results != NULL) { + next_lst= f->results->next; + Xorriso_lst_destroy(&(f->results), 0); + f->results= next_lst; + } + } + if(f->num_delivered > 0) + (f->num_delivered)--; + if(f->num_delivered == 0) + f->next_to_deliver= NULL; + f->num_results--; + } + + if(f->results == NULL) { + prev_lst= NULL; + } else { + for(prev_lst= f->results; prev_lst->next != NULL; + prev_lst= prev_lst->next); + } + for(i= 0; i < f->num_words; i++) { + widx= f->word_idx[i]; + if(widx >= argc || widx < 0) + ret= Xorriso_lst_new(&lst, "", prev_lst, 0); + else if(argv[widx] == NULL) + ret= Xorriso_lst_new(&lst, "", prev_lst, 0); + else + ret= Xorriso_lst_new(&lst, argv[widx], prev_lst, 0); + if(ret <= 0) + goto no_mem; + if(prev_lst == NULL) + f->results= lst; + prev_lst= lst; + } + (f->num_results)++; + Xorriso__dispose_words(&argc, &argv); + } + ret= 1; +ex: + Xorriso__dispose_words(&argc, &argv); + return(ret); +no_mem:; + Xorriso_no_malloc_memory(xorriso, NULL, 1); /* reports to stderr */ + ret= -1; + goto ex; +} + + +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^ Xorriso_msg_sievE ^^^^^^^^^^^^^^^^^^^^^^^^^^ */ + + int Xorriso_result(struct XorrisO *xorriso, int flag) /* bit0= no considerations or computations or dialog. Just put out. @@ -2839,6 +3410,8 @@ int Xorriso_reset_counters(struct XorrisO *xorriso, int flag) } +/* @param flag bit0= to stderr rather than Xorriso_msgs_submit +*/ int Xorriso_no_malloc_memory(struct XorrisO *xorriso, char **to_free, int flag) { if(to_free!=NULL) @@ -2848,7 +3421,12 @@ int Xorriso_no_malloc_memory(struct XorrisO *xorriso, char **to_free, int flag) *to_free= NULL; } sprintf(xorriso->info_text, "Out of virtual memory"); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "ABORT", 0); + if(flag & 1) { + fprintf(stderr, "%s", xorriso->info_text); + /* (No need to first check for problem status worse than ABORT) */ + Xorriso_set_problem_status(xorriso, "ABORT", 0); + } else + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "ABORT", 0); return(1); } diff --git a/xorriso/xorriso.h b/xorriso/xorriso.h index d19666a5..eb968ff4 100644 --- a/xorriso/xorriso.h +++ b/xorriso/xorriso.h @@ -429,7 +429,7 @@ int Xorriso_parse_line(struct XorrisO *xorriso, char *line, /* Dispose a list of strings as allocated by Xorriso_parse_line() or - Xorriso_program_arg_bsl(). + Xorriso_program_arg_bsl(), or Xorriso_sieve_get_result(). @since 1.2.6 @param argc A pointer to the number of allocated and filled word strings. *argc will be set to 0 by this call. @@ -583,6 +583,303 @@ int Xorriso_process_errfile(struct XorrisO *xorriso, int flag); +/* -------------------- Message output evaluation API -------------------- */ + +/* xorriso is basically a dialog software which reacts on commands by + side effects and by messages. The side effects manipulate the state of + the ISO image model and of drives. This state can be inquired by commands + which emit messages. + + There are several API approaches how a program can receive and use the + message output of xorriso. + + - The message sieve may be programmed to pick certain information snippets + out of the visible message stream. This covers all messages on the + result channel and those info channel messages which get not suppressed + by command -report_about. All important info messages have severity NOTE + or higher. + Much of the message interpretation is supposed to happen by the sieve + filter rules which describe the interesting message lines and the + positions of the interesting message parts. + The call Xorriso_sieve_big() installs a sieve that looks out for most + model state messages which xorriso can emit. After a few commands + the user will ask the sieve for certain text pieces that might have been + caught. + + - The outlist stack may be used to catch messages in linked lists rather + than putting them out on the message channels. + All interpretation of the messages has to be done by the user of the + xorriso API. Function Xorriso_parse_line() is intended to help with + splitting up messages into words. + The outlist stack is handy for catching the result channel of information + commands with large uniform output like -lsl, -getfacl, -status. + + - The message watcher is a separate program thread which uses the outlist + stack to catch the messages and to call user provided handler functions. + These functions can use Xorriso_parse_line() too, if they submit the + xorriso parameter as NULL. + The main motivation for the message watcher is to inspect and display + messages of long lasting xorriso commands like -commit, -blank, -format. + + The sieve does not interfere with outlists and message watcher. + The message watcher will only see messages which are not caught by outlists + which were enabled after the watcher thread was started. + +*/ + +/* The programmable message sieve picks words out of the program messages + of xorriso. + The sieve is a collection of filter rules. Each one is defined by a call of + Xorriso_sieve_add_filter(). The sieve watches the given output channels for + messages which begin by the given text prefixes of the filters. + Matching lines get split into words by Xorriso_parse_line() using + the given separators. The words described by the filter's word index array + get recorded by the filter and can be inquired by Xorriso_sieve_get_result() + after one or more xorriso commands have been performed. + The recorded results may be disposed by Xorriso_sieve_clear_results without + giving up the sieve. + The whole sieve may be disposed by Xorriso_sieve_dispose(). + Default at library start is an inactive sieve without any filter rules. +*/ + +/** Add a filter rule to the message sieve. + Start watching output messages, if this is not already enabled. + @since 1.2.6 + @param xorriso The environment handle + @param name The filter name by which its recorded results shall + be inquired via Xorriso_sieve_get_result() + @param channels Which of the output channels the filter shall watch + bit0= result channel + bit1= info channel + bit2= mark channel + @param prefix The line start to watch for. Will also be handed over + to Xorriso_parse_line(). Empty text matches all lines. + @param separators List of separator characters for Xorriso_parse_line() + @param num_words Number of word indice in word_idx + @param word_idx Array with the argv indice to be picked from the + the result of Xorriso_parse_line(). Must at least + contain num_words elements. + @param max_results If not 0, then the maximum number of line results that + shall be recorded by the filter. When this number is + exceeded, then results of older lines get discarded + when new results get recorded. + @param flag Bitfield for control purposes + bit0= Last result word shall contain the remainder of + the message line + @return <=0 error , >0 success +*/ +int Xorriso_sieve_add_filter(struct XorrisO *xorriso, char *name, + int channels, char *prefix, char *separators, + int num_words, int *word_idx, int max_results, + int flag); + + +/** Inquire recorded results from a particular filter rule. + @param xorriso The environment handle + @param name The filter name as given by Xorriso_sieve_add_filter() + @param argc Will return the number of allocated and filled word + strings. + @param argv Will return the array of word strings. + Do not forget to dispose the allocated memory by a + call to Xorriso__dispose_words(). + @param available Will return the number of results which are still + available for further calls of Xorriso_sieve_get_result() + with the given name. + @param flag Bitfield for control purposes: + bit0= Reset reading to first matching result. + bit1= Only inquire number of available results. + Do not allocate memory. + bit2= If *argv is not NULL, then free it before attaching + new memory. +*/ +int Xorriso_sieve_get_result(struct XorrisO *xorriso, char *name, + int *argc, char ***argv, int *available, + int flag); + + +/** Dispose all recorded results. Keep filter rules. Continue watching + and recording. + @since 1.2.6 + @param xorriso The environment handle + @param flag Unused yet. Submit 0. + @return <=0 error , >0 success +*/ +int Xorriso_sieve_clear_results(struct XorrisO *xorriso, int flag); + + +/** Dispose all filter rules. End watching and recording. + This is the default state at library startup. + @since 1.2.6 + @param xorriso The environment handle + @param flag Unused yet. Submit 0. + @return <=0 error , >0 success +*/ +int Xorriso_sieve_dispose(struct XorrisO *xorriso, int flag); + + +/** Install a large sieve with filters for about any interesting message + of xorriso. The filter rule names are mostly the same as the prefixes they + search for. If you do not find the message prefix of your desire, then + you may add a filter rule by Xorriso_sieve_add_filter(). + If you do not want all these filter any more, call Xorriso_sieve_dispose(). + + You should obtain your recorded data often and then call + Xorriso_sieve_clear_results(). It is nevertheless ok to perform several + different xorriso information commands and to then obtain results from the + sieve. + + The installed filters in particular: + Name Recorded values, returned by Xorriso_sieve_get_result() + ------------------------------------------------------------------------ + "-changes_pending" up to 1 result from -changes_pending show_status + argv[0]= "yes" or "no" + (Note: prefix is "-changes_pending ") + "Abstract File:" up to 1 result from -pvd_info + argv[0]= file name + (Note: prefix is "Abstract File: ") + "After commit :" up to 1 result from -tell_media_space + argv[0]= number of blocks with "s" appended + "App Id :" up to 1 result from -pvd_info + argv[0]= id + (Note: prefix is "App Id : ") + "Biblio File :" up to 1 result from -pvd_info + argv[0]= file name + (Note: prefix is "Biblio File : ") + "Build timestamp :" up to 1 result from -version + argv[0]= timestamp + (Note: prefix is "Build timestamp : ") + "CopyrightFile:" up to 1 result from -pvd_info + argv[0]= file name + (Note: prefix is "CopyrightFile: ") + "DVD obs 64 kB:" up to 1 result from -list_extras + argv[0]= "yes" or "no" + "Drive current:" up to 2 results from -dev, -indev, -toc, others + argv[0]= command ("-dev", "-outdev", "-indev") + argv[1]= drive address + "Drive type :" up to 2 results from -toc + argv[0]= vendor + argv[1]= product + argv[2]= revision + "Ext. filters :" up to 1 result from -list_extras + argv[0]= "yes" or "no" , possibly more info + (Note: prefix is "Ext. filters : ") + "Format idx :" up to 100 results from -list_formats + argv[0]= index + argv[1]= MMC code + argv[2]= number of blocks with "s" appended + argv[3]= roughly the size in MiB + (Note: prefix is "Format idx ") + "Format status:" up to 1 result from -list_formats + argv[0]= status + argv[1]= capacity + "Image size :" up to 1 result from -print_size + argv[0]= number of blocks with "s" appended + "ISO session :" up to 10000 results from -toc + argv[0]= Idx + argv[1]= sbsector + argv[2]= Size + argv[3]= Volume Id + "Jigdo files :" up to 1 result from -list_extras + argv[0]= "yes" or "no" + "Local ACL :" up to 1 result from -list_extras + argv[0]= "yes" or "no" + "Local xattr :" up to 1 result from -list_extras + argv[0]= "yes" or "no" + "MD5 tag range:" up to 10000 results from -check_media + argv[0]= lba + argv[1]= size in blocks + argv[2]= result text (starting with "+", "-", or "0") + "Media blocks :" up to 2 results from -toc + argv[0]= readable + argv[1]= writable + argv[2]= overall + "Media current:" up to 2 results from -dev, -indev, -toc, others + argv[0]= media type / MMC profile name + (Note: prefix is "Media current: " which eats extra blank) + "Media nwa :" up to 1 result from -toc + argv[0]= next writable address + "Media region :" up to 10000 results from -check_media + argv[0]= lba + argv[1]= size in blocks + argv[2]= quality text (starting with "+", "-", or "0") + "Media space :" up to 1 result from -tell_media_space + argv[0]= number of blocks with "s" appended + "Media status :" up to 2 results from -dev, -indev, -toc, others + argv[0]= status description + (Note: prefix is "Media status : ") + "Media summary:" up to 2 results from -dev, -indev, -toc, others + argv[0]= sessions + argv[1]= data blocks (full count) + argv[2]= data (with unit letter k,m,g) + argv[3]= free (with unit letter k,m,g) + "PVD address :" up to 1 result from -pvd_info + argv[0]= block address with "s" appended + "Preparer Id :" up to 1 result from -pvd_info + argv[0]= id + (Note: prefix is "Preparer Id : ") + "Profile :" up to 256 results from -list_profiles + argv[0]= MMC code + argv[1]= profile name in round brackets + possibly appended: " (current)" + "Publisher Id :" up to 1 result from -pvd_info + argv[0]= id + (Note: prefix is "Publisher Id : ") + "Readline :" up to 1 result from -list_extras + argv[0]= "yes" or "no" + "System Id :" up to 1 result from -pvd_info + argv[0]= id + (Note: prefix is "System Id : ") + "Version timestamp :" up to 1 result from -version + argv[0]= timestamp + "Volume Id :" up to 1 result from -pvd_info + argv[0]= id + (Note: Not output from -dev or -toc but from -pvd_info) + "Volume Set Id:" up to 1 result from -pvd_info + argv[0]= id + (Note: prefix is "Volume Set Id: ") + "Volume id :" up to 2 results from -dev, -indev, -toc, others + argv[0]= volume id + (Note: Not output from -pvd_info but from -dev or -toc) + "Write speed :" up to 100 results from -list_speeds + argv[0]= kilobytes per second + argv[1]= speed factor + "Write speed H:" up to 1 result from -list_speeds + see "Write speed :" + "Write speed L:" up to 1 result from -list_speeds + see "Write speed :" + "Write speed h:" up to 1 result from -list_speeds + see "Write speed :" + "Write speed l:" up to 1 result from -list_speeds + see "Write speed :" + "libburn in use :" up to 1 result from -version + argv[0]= version text + argv[1]= minimum version requirement + "libburn OS adapter:" up to 1 result from -version + argv[0]= adapter description + (Note: prefix is "libburn OS adapter: ") + "libisoburn in use :" up to 1 result from -version + argv[0]= version text + argv[1]= minimum version requirement + "libisofs in use :" up to 1 result from -version + argv[0]= version text + argv[1]= minimum version requirement + "libjte in use :" up to 1 result from -version + argv[0]= version text + argv[1]= minimum version requirement + "xorriso version :" up to 1 result from -version + argv[0]= version text + "zisofs :" up to 1 result from -list_extras + argv[0]= "yes" or "no" + ------------------------------------------------------------------------ + + @since 1.2.6 + @param xorriso The environment handle + @param flag Unused yet. Submit 0. + @return <=0 error , >0 success +*/ +int Xorriso_sieve_big(struct XorrisO *xorriso, int flag); + + /* The outlist stack allows to redirect the info and result messages from their normal channels into a pair of string lists which can at some later time be retrieved by the application. diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index afe00f2b..9662e402 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -591,6 +591,8 @@ struct XorrisO { /* the global context of xorriso */ int msgw_fetch_lock_ini; pthread_mutex_t msgw_fetch_lock; + struct Xorriso_msg_sievE *msg_sieve; + int status_history_max; /* for -status long_history */ /* 0= no logging of SCSI commands, 1= to stderr */ diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 54b78a12..4985d154 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2012.11.26.154951" +#define Xorriso_timestamP "2012.12.06.132118" diff --git a/xorriso/xorrisoburn.h b/xorriso/xorrisoburn.h index 67b4b828..3ed60aad 100644 --- a/xorriso/xorrisoburn.h +++ b/xorriso/xorrisoburn.h @@ -24,6 +24,7 @@ struct SpotlisT; /* List of intervals with different read qualities */ struct CheckmediajoB; /* Parameters for Xorriso_check_media() */ +struct Xorriso_msg_sievE; /* Fishes for info particles in reply messages */ int Xorriso_startup_libraries(struct XorrisO *xorriso, int flag);