From dd4ebdbe17efde7c2b63ec1fe4ce401a43272323 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 6 Nov 2007 16:32:39 +0000 Subject: [PATCH] Implemented -overwrite control --- test/xorriso.1 | 23 ++-- test/xorriso.c | 28 +++-- test/xorriso.h | 4 +- test/xorriso_private.h | 12 +- test/xorriso_timestamp.h | 2 +- test/xorrisoburn.c | 233 ++++++++++++++++++++++++++++++++------- 6 files changed, 244 insertions(+), 58 deletions(-) diff --git a/test/xorriso.1 b/test/xorriso.1 index f9478b15..fd5296f7 100644 --- a/test/xorriso.1 +++ b/test/xorriso.1 @@ -264,10 +264,10 @@ operations. They are intended to be in effect with the read-only mounted image. .PP If the iso_rr_path of a newly inserted or renamed file leads to an existing file object in the ISO image, then the following collision handling happens: +.br If both objects are directories then they get merged by recursively inserting the subobjects from filesystem into ISO image. - > If other file types collide then the setting of command -overwrite decides. - > Directories may only be deleted by commands -rmdir or -rm_r. +If other file types collide then the setting of command -overwrite decides. .PP The commands in this section alter the ISO image and not the local filesystem. .TP @@ -487,13 +487,20 @@ Set the threshhold for events to be reported. Events are the same as with -abort_on. Regardless what is set by -report_about, messages get always reported if they reach the severity threshhold of -abort_on . -.TP -> \fB\-overwrite\fR "on"|"off" -Allow or disallow to overwrite existing files in the -ISO image by files with the same user defined name. This is -the RockRidge name and not the plain ISO name. .br -With setting "off", RR name collisions cause SORRY-events. +Event messages are sent to the info channel "I" which is usually stderr +but may be influenced by command -pkt_output. +Info messages which belong to no event get attributed severity "NOTE". +.TP +\fB\-overwrite\fR "on"|"nondir"|"off" +Allow or disallow to overwrite existing files in the +ISO image by files with the same user defined name. +.br +With setting "off", name collisions cause SORRY-events. +With setting "nondir", only directories are protected by such events, other +existing file types get treated with -rm before the new file gets added. +Setting "on" allows automatic -rm_r. I.e. a non-directory can replace an +existing directory and all its subordinates. .TP .B Dialog mode control: .TP diff --git a/test/xorriso.c b/test/xorriso.c index f7b083ad..e83408fd 100644 --- a/test/xorriso.c +++ b/test/xorriso.c @@ -1669,7 +1669,7 @@ return: /* >>> how to distinguish error from EOF , do i need a (FILE *) ? */ return(0); } - if(strlen(entry->d_name)>4095) { + if(strlen(entry->d_name)>=SfileadrL) { fprintf(stderr,"--- oversized directory entry (number %d) :\n %s", o->count+1,entry->d_name); return(-1); @@ -1769,7 +1769,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->global_uid= 0; m->volid[0]= 0; m->do_global_gid= 0; - m->do_overwrite= 1; + m->do_overwrite= 2; m->do_reassure= 0; m->global_gid= 0; m->indev[0]= 0; @@ -2818,8 +2818,9 @@ int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag) Xorriso_status_result(xorriso,filter,fp,flag&2); } - is_default= !!xorriso->do_overwrite; - sprintf(line,"-overwrite %s\n",(xorriso->do_overwrite ? "on" : "off")); + is_default= (xorriso->do_overwrite==2); + sprintf(line,"-overwrite %s\n",(xorriso->do_overwrite == 1 ? "on" : + (xorriso->do_overwrite == 2 ? "nondir" : "off"))); if(!(is_default && no_defaults)) Xorriso_status_result(xorriso,filter,fp,flag&2); @@ -3095,7 +3096,7 @@ int Xorriso_eval_problem_status(struct XorrisO *xorriso, int ret, int flag) if(xorriso->problem_status < xorriso->abort_on_severity && xorriso->problem_status > 0) { - if(xorriso->problem_status >= sev) { + if(xorriso->problem_status >= sev && !(flag&1)) { sprintf(xorriso->info_text, "xorriso : NOTE : Tolerated problem event of severity '%s'\n", xorriso->problem_status_text); @@ -3106,7 +3107,8 @@ int Xorriso_eval_problem_status(struct XorrisO *xorriso, int ret, int flag) sprintf(xorriso->info_text, "xorriso : ABORT : -abort_on '%s' encountered '%s'", xorriso->abort_on_text, xorriso->problem_status_text); - Xorriso_info(xorriso, 0);/* submit not as problem event */ + if(!(flag&1)) + Xorriso_info(xorriso, 0);/* submit not as problem event */ ret= -1; } else if(ret>0) ret= 1; @@ -4359,10 +4361,20 @@ ex:; } -/* Option -overwrite "on"|"off" */ +/* Option -overwrite "on"|"nondir"|"off" */ int Xorriso_option_overwrite(struct XorrisO *xorriso, char *mode, int flag) { - xorriso->do_overwrite= !!strcmp(mode, "off"); + if(strcmp(mode, "off")==0) + xorriso->do_overwrite= 0; + else if(strcmp(mode, "on")==0) + xorriso->do_overwrite= 0; + else if(strcmp(mode, "nondir")==0) + xorriso->do_overwrite= 2; + else { + sprintf(xorriso->info_text, "-overwrite: unknown mode '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } return(1); } diff --git a/test/xorriso.h b/test/xorriso.h index 675c4ec8..6ff775d1 100644 --- a/test/xorriso.h +++ b/test/xorriso.h @@ -57,7 +57,7 @@ int Xorriso_msgs_submit(struct XorrisO *xorriso, option function to evaluate the situation. @param xorriso The environment handle @param ret The return value of the prviously called option function - @param flag Unused yet. Submit 0. + @param flag bit0= do not issue own event messages @return Gives the advice: 2= pardon was given, go on 1= no problem, go on @@ -249,7 +249,7 @@ int Xorriso_option_no_rc(struct XorrisO *xorriso, int flag); int Xorriso_option_options_from_file(struct XorrisO *xorriso, char *adr, int flag); -/* Option -overwrite "on"|"off" */ +/* Option -overwrite "on"|"nondir"|"off" */ int Xorriso_option_overwrite(struct XorrisO *xorriso, char *mode, int flag); /* Option -page */ diff --git a/test/xorriso_private.h b/test/xorriso_private.h index f5d0fd0b..04a2a087 100644 --- a/test/xorriso_private.h +++ b/test/xorriso_private.h @@ -72,8 +72,7 @@ struct XorrisO { /* the global context of xorriso */ int do_global_gid; gid_t global_gid; - /* >>> put overwrite_mode here */ - int do_overwrite; + int do_overwrite; /* 0=off, 1=on, 2=nondir */ int do_reassure; char volid[SfileadrL]; @@ -202,6 +201,15 @@ char *Text_shellsafe(char *in_text, char *out_text, int flag); int Sort_argv(int argc, char **argv, int flag); +struct DirseQ; + +int Dirseq_new(struct DirseQ **o, char *dir, int flag); + +int Dirseq_destroy(struct DirseQ **o, int flag); + +int Dirseq_next_adr(struct DirseQ *o, char reply[SfileadrL], int flag); + + #endif /* Xorriso_private_includeD */ diff --git a/test/xorriso_timestamp.h b/test/xorriso_timestamp.h index 801b77d0..a5a99ead 100644 --- a/test/xorriso_timestamp.h +++ b/test/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2007.11.02.184705" +#define Xorriso_timestamP "2007.11.06.163305" diff --git a/test/xorrisoburn.c b/test/xorrisoburn.c index 97121dba..03b10434 100644 --- a/test/xorrisoburn.c +++ b/test/xorrisoburn.c @@ -97,6 +97,20 @@ int Xorriso_startup_libraries(struct XorrisO *xorriso, int flag) } +/* @param flag bit0=path is in source filesystem , bit1= unconditionally */ +int Xorriso_much_too_long(struct XorrisO *xorriso, int len, int flag) +{ + if(len>=SfileadrL || (flag&2)) { + sprintf(xorriso->info_text, + "Path given for %s is much too long (%d)", + ((flag&1) ? "local filesystem" : "ISO image"), len); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + return(0); + } + return(1); +} + + /* @param flag bit1= obtain outdrive, else indrive */ int Xorriso_get_drive_handles(struct XorrisO *xorriso, struct burn_drive_info **dinfo, @@ -562,17 +576,149 @@ much_too_long:; } +/* @param flag bit0= recursion is active */ +int Xorriso_add_tree(struct XorrisO *xorriso, struct iso_tree_node_dir *dir, + char *img_dir_path, char *disk_dir_path, int flag) +{ + struct iso_volume *volume; + struct iso_tree_node *node; + int ret, target_is_dir, source_is_dir; + struct DirseQ *dirseq= NULL; + char sfe[4*SfileadrL], sfe2[4*SfileadrL]; + char disk_path[2*SfileadrL], img_path[2*SfileadrL]; + char *name, *img_name; + struct stat stbuf; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + + ret= Dirseq_new(&dirseq, disk_dir_path, 1); + if(ret<0) { + sprintf(xorriso->info_text,"Failed to create source filesystem iterator"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + if(ret==0) { + sprintf(xorriso->info_text,"Cannot open as source directory: %s", + Text_shellsafe(disk_dir_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + {ret= 0; goto ex;} + } + + if(Sfile_str(disk_path, disk_dir_path,0)<=0) + {ret= -1; goto ex;} + if(disk_path[strlen(disk_path)-1]!='/') + strcat(disk_path,"/"); + name= disk_path+strlen(disk_path); + if(Sfile_str(img_path, img_dir_path, 0)<=0) + {ret= -1; goto ex;} + if(img_path[strlen(img_path)-1]!='/') + strcat(img_path,"/"); + img_name= img_path+strlen(img_path); + + while(1) { /* loop over directory content */ + Xorriso_process_msg_queues(xorriso,0); + ret= Dirseq_next_adr(dirseq,name,0); + if(ret==0) + break; + if(ret<0) { + sprintf(xorriso->info_text,"Failed to obtain next directory entry"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + {ret= -1; goto ex;} + } + strcpy(img_name, name); + if(Xorriso_much_too_long(xorriso, strlen(img_path), 0)<=0) + goto was_problem; + if(Xorriso_much_too_long(xorriso, strlen(disk_path), 0)<=0) + goto was_problem; + if(lstat(disk_path, &stbuf)==-1) { + sprintf(xorriso->info_text, + "Cannot determine attributes of source file %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0); + goto was_problem; + } + source_is_dir= 0; + if(S_ISDIR(stbuf.st_mode)) { + source_is_dir= 1; + } else if(!(S_ISREG(stbuf.st_mode) || S_ISLNK(stbuf.st_mode))) { + sprintf(xorriso->info_text,"Source file %s is of non-supported file type", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + goto was_problem; + } + + /* does a node exist with this name ? */ + node= iso_tree_volume_path_to_node(volume,img_path); + if(node!=NULL) { + target_is_dir= (iso_tree_node_get_type(node)==LIBISO_NODE_DIR); + if(!(target_is_dir && source_is_dir)) { + Xorriso_process_msg_queues(xorriso,0); + + /* handle overwrite situation */; + if(xorriso->do_overwrite==1 || + (xorriso->do_overwrite==2 && !target_is_dir)) { + ret= Xorriso_rmi(xorriso, img_path, 1); + if(ret<=0) + goto was_problem; + node= NULL; + } else { + sprintf(xorriso->info_text, + "While grafting %s : file object exists and may not be overwritten", + Text_shellsafe(img_path,sfe,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + goto was_problem; + } + } + } + + if(node==NULL) + node= iso_tree_add_node(dir, disk_path); + if(node == NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "While grafting %s=%s : libisofs_errno = %d", + Text_shellsafe(img_path,sfe,0), Text_shellsafe(disk_path,sfe2,0), + libisofs_errno); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + goto was_problem; + } + /* name always equal to disk. Obsolete: iso_tree_node_set_name(node,name);*/ + if(source_is_dir) { + ret= Xorriso_add_tree(xorriso, (struct iso_tree_node_dir *) node, + img_path, disk_path, 1); + if(ret<0) + {ret= -1; goto ex;} + if(ret==0) + goto was_problem; + } + + continue; +was_problem:; + ret= Xorriso_eval_problem_status(xorriso, 0, 1); + if(ret<0) + {ret= 0; goto ex;} + } + + ret= 1; +ex: + Xorriso_process_msg_queues(xorriso,0); + Dirseq_destroy(&dirseq, 0); + return(ret); +} + + /** @param flag bit0= mkdir: graft in as empty directory, not as copy from disk @return <=0 = error , 1 = added simple node , 2 = added directory */ int Xorriso_graft_in(struct XorrisO *xorriso, char *disk_path, char *img_path, int flag) { struct iso_volume *volume; - struct iso_tree_radd_dir_behavior behav= {NULL, 0, 0}; char path[SfileadrL], *apt, *npt, *cpt; struct iso_tree_node_dir *dir; struct iso_tree_node *node; - int done= 0, is_dir= 0, l, ret; + int done= 0, is_dir= 0, l, ret, target_is_dir, source_is_dir; struct stat stbuf; for(cpt= img_path; 1; cpt++) { @@ -654,24 +800,34 @@ int Xorriso_graft_in(struct XorrisO *xorriso, char *disk_path, char *img_path, goto attach_source; continue; } + source_is_dir= (is_dir || (flag&1) || !done); node= iso_tree_volume_path_to_node(volume,path); if(node!=NULL) { - if(iso_tree_node_get_type(node)!=LIBISO_NODE_DIR) { + target_is_dir= (iso_tree_node_get_type(node)==LIBISO_NODE_DIR); + if(!(target_is_dir && source_is_dir)) { Xorriso_process_msg_queues(xorriso,0); - if(done) { - - /* >>> handle overwrite situation */; - + /* handle overwrite situation */; + if(xorriso->do_overwrite==1 || + (xorriso->do_overwrite==2 && !target_is_dir)) { + ret= Xorriso_rmi(xorriso, path, 1); + if(ret<=0) + return(ret); + node= NULL; + goto handle_path_node; } + sprintf(xorriso->info_text, - "While grafting '%s' : '%s' exists and is not a directory", + "While grafting '%s' : '%s' exists and may not be overwritten", img_path, path); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); return(0); } dir= (struct iso_tree_node_dir *) node; - } else if(is_dir || (flag&1) || !done) { + } + +handle_path_node:; + if(node==NULL && source_is_dir) { /* make a directory */ dir= iso_tree_add_dir(dir, apt); if(dir==NULL) { Xorriso_process_msg_queues(xorriso,0); @@ -692,11 +848,19 @@ attach_source:; } else if(is_dir) { - /* >>> do this by own recursive operation in order to gain - full control with overwriting */; +#ifdef Xorriso_on_its_way_ouT + /* <<< */ + { struct iso_tree_radd_dir_behavior behav= {NULL, 0, 0}; - iso_tree_radd_dir(dir, disk_path, &behav); + iso_tree_radd_dir(dir, disk_path, &behav); + } +#else + ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, 0); + if(ret<=0) + return(ret); + +#endif /* ! Xorriso_on_its_way_ouT */ } else { node= iso_tree_add_node(dir, disk_path); @@ -820,6 +984,9 @@ int Xorriso_toc(struct XorrisO *xorriso, int flag) if(s != BURN_DISC_FULL && s != BURN_DISC_APPENDABLE) return(1); + if(xorriso->request_to_abort) + return(1); + disc= burn_drive_get_disc(drive); if (disc==NULL) { Xorriso_process_msg_queues(xorriso,0); @@ -856,11 +1023,13 @@ int Xorriso_toc(struct XorrisO *xorriso, int flag) num_sessions= 1; } else { sessions= burn_disc_get_sessions(disc, &num_sessions); - for (session_no= 0; session_norequest_to_abort); + session_no++) { tracks = burn_session_get_tracks(sessions[session_no], &num_tracks); if (tracks==NULL) continue; - for(track_no= 0; track_norequest_to_abort); + track_no++) { track_count++; is_data= 0; burn_track_get_entry(tracks[track_no], &toc_entry); @@ -896,6 +1065,8 @@ int Xorriso_toc(struct XorrisO *xorriso, int flag) num_data+= last_track_size; } } + if(xorriso->request_to_abort) + return(1); sprintf(respt, "Media summary: %d session%s, %d data blocks\n", num_sessions, (num_sessions==1 ? "" : "s"), num_data); Xorriso_result(xorriso,0); @@ -947,7 +1118,7 @@ int Xorriso_show_devices(struct XorrisO *xorriso, int flag) Xorriso_info(xorriso,0); respt= xorriso->result_line; - for(i= 0; i < drive_count; i++) { + for(i= 0; i < drive_count && !(xorriso->request_to_abort); i++) { if(burn_drive_get_adr(&(drive_list[i]), adr)<=0) strcpy(adr, "-get_adr_failed-"); Xorriso_process_msg_queues(xorriso,0); @@ -1196,7 +1367,7 @@ int Xorriso_node_from_path(struct XorrisO *xorriso, struct iso_volume *volume, /* @param flag bit0= remove whole sub tree: rm -r - bit1=remove empty directory: rmdir + bit1= remove empty directory: rmdir @return <=0 = error 1 = removed simple node 2 = removed directory or tree @@ -1213,12 +1384,8 @@ int Xorriso_rmi(struct XorrisO *xorriso, char *path, int flag) if(ret<=0) return(ret); - if(strlen(path)>=SfileadrL) { - sprintf(xorriso->info_text, - "Path given for ISO image is much too long (%d)", strlen(path)); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0) return(0); - } ret= Xorriso_node_from_path(xorriso, volume, path, &victim_node, 0); if(ret<=0) return(ret); @@ -1253,16 +1420,11 @@ int Xorriso_rmi(struct XorrisO *xorriso, char *path, int flag) return(0); } -#ifdef Not_yeT - char boss_adr[SfiladrL], *spt; - struct *check_node; - int l; + if(xorriso->do_reassure) { - /* >>> derive boss_path as dirname from victim_path ... */ - check_node= iso_tree_volume_path_to_node(volume, boss_path); - /* >>> compare boss_node and check_node */ + /* >>> ask user */; -#endif /* Not_yeT */ + } ret= iso_tree_node_remove(boss_node, victim_node); Xorriso_process_msg_queues(xorriso,0); @@ -1379,10 +1541,7 @@ int Xorriso_show_du_subs(struct XorrisO *xorriso, strcpy(path, abs_path); if(Sfile_add_to_path(path, name, 0)<=0) { much_too_long:; - sprintf(xorriso->info_text, - "Path for subdirectory gets much too long (%d)", - strlen(path)+strlen(name)+1); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + Xorriso_much_too_long(xorriso, strlen(path)+strlen(name)+1, 2); {ret= -1; goto ex;} } filec++; @@ -1419,7 +1578,7 @@ much_too_long:; iter= iso_tree_node_children(dir_node); } - for(i= 0; irequest_to_abort); i++) { if(no_sort) { node= iso_tree_iter_next(iter); if(node==NULL) @@ -1495,7 +1654,7 @@ much_too_long:; "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); - was_error++; + was_error++; continue; } } else @@ -1519,7 +1678,7 @@ much_too_long:; return(!was_error); } - for(i= 0; irequest_to_abort); i++) { if(filev[i][0]!='/') { strcpy(path, xorriso->wdi); if(Sfile_add_to_path(path, filev[i], 0)<=0) @@ -1667,7 +1826,7 @@ wdi_is_not_a_dir:; iter= iso_tree_node_children(dir_node); } - for(i= 0; irequest_to_abort); i++) { if(no_sort) { node= iso_tree_iter_next(iter); if(node==NULL)