diff --git a/xorriso/base_obj.c b/xorriso/base_obj.c index fab807f1..2ad83e50 100644 --- a/xorriso/base_obj.c +++ b/xorriso/base_obj.c @@ -363,6 +363,8 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->perm_stack= NULL; + m->update_flags= 0; + m->result_line[0]= 0; m->result_line_counter= 0; m->result_page_counter= 0; diff --git a/xorriso/cmp_update.c b/xorriso/cmp_update.c index 8148117a..e50a5a88 100644 --- a/xorriso/cmp_update.c +++ b/xorriso/cmp_update.c @@ -284,6 +284,7 @@ ex:; bit1= compare ctime bit2= check only existence of both file objects count one or both missing as "difference" + bit26= do not issue message about missing disk file bit27= for Xorriso_path_is_excluded(): bit0 bit28= examine eventual disk_path link target rather than link bit29= do not issue pacifier messages @@ -320,7 +321,7 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr, sprintf(respt , "? %s (DISK) : exluded by %s\n", Text_shellsafe(disk_adr, sfe, 0), (ret==1 ? "-not_paths" : "-not_leaf")); - if(!(flag&(1<<31))) + if(! (flag & ((1 << 31) | (1 << 26)))) Xorriso_result(xorriso,0); missing= 1; (*result)|= 1; @@ -334,7 +335,7 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr, if(ret==-1) { sprintf(respt , "? %s (DISK) : cannot lstat() : %s\n", Text_shellsafe(disk_adr, sfe, 0), strerror(errno)); - if(!(flag&(1<<31))) + if(! (flag & ((1 << 31) | (1 << 26)))) Xorriso_result(xorriso,0); missing= 1; (*result)|= 1; @@ -681,10 +682,11 @@ int Xorriso_pfx_disk_path(struct XorrisO *xorriso, char *iso_path, Set to NULL if calling this function from outside ISO world @param flag bit0= update rather than compare bit1= find[ix] is in recursion + bit2= update_merge : do not delete but mark visited and found @return <=0 error, 1= ok , 2= iso_path was deleted 3=ok, do not dive into directory (e.g. because it is a split file) */ -int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter, +int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter, void *node, char *iso_path, char *iso_prefix, char *disk_prefix, int flag) { @@ -709,22 +711,24 @@ int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter, follow_links= (xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&2))) <<28; ret= Xorriso_compare_2_files(xorriso, disk_path, iso_path, "", &result, - 2 | follow_links | ((!(flag&2))<<27) | ((flag&1)<<31)); + 2 | follow_links | ((!!(flag & 4)) << 26) + | ((!(flag&2))<<27) | ((flag&1)<<31)); /* was once: | ((!(flag&1))<<29) */ if(retfind_compare_result) xorriso->find_compare_result= ret; if(flag&1) { - if(ret<=0) { - if(ret<0) - if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0) - return(ret); - uret= Xorriso_update_interpreter(xorriso, boss_iter, result, - disk_path, iso_path, (flag&2)<<1); - if(uret<=0) - ret= 0; - if(uret==2) - deleted= 1; - } + if(ret<0) + if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0) + return(ret); + if(ret > 0) + result= 0; + uret= Xorriso_update_interpreter(xorriso, boss_iter, node, result, + disk_path, iso_path, + ((flag & 2) << 1) | ((flag & 4) >> 1)); + if(uret<=0) + ret= 0; + if(uret==2) + deleted= 1; } if(ret<0) return(ret); @@ -742,11 +746,15 @@ int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter, Do not call Xorriso_hardlink_update() Overwrite exactly if normal mode would not, else do nothing + bit1= do not delete files which are not found under + disk_path, but rather mark visited files and mark + files which were found. bit2= -follow: this is not a command parameter @return <=0 error, 1= ok , 2= iso_rr_path node object has been deleted , 3= no action taken */ -int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter, +int Xorriso_update_interpreter(struct XorrisO *xorriso, + void *boss_iter, void *node, int compare_result, char *disk_path, char *iso_rr_path, int flag) { @@ -767,6 +775,15 @@ int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter, ret= 3; goto ex; } + if((flag & 2) && !(compare_result & 2)) { + ret= Xorriso_mark_update_merge(xorriso, iso_rr_path, node, + !(compare_result & 1)); + if(ret <= 0) + goto ex; + } + if(compare_result == 0) + {ret= 1; goto ex;} + if(compare_result&((1<<11)|(1<<13))) { if(flag & 1) {ret= 3; goto ex;} @@ -806,15 +823,24 @@ int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter, deleted= 1; ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, iso_rr_path, (off_t) 0, (off_t) 0, 2|(flag&4)); + if(ret <= 0) + goto ex; + if(flag & 2) { + ret= Xorriso_mark_update_merge(xorriso, iso_rr_path, NULL, 1); + if(ret <= 0) + goto ex; + } } sprintf(xorriso->info_text, "Deleted and re-added "); } else if(compare_result&(1)) { delete:; /* disk_adr not existing */ - ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1); - deleted= 1; - sprintf(xorriso->info_text, "Deleted "); + if(!(flag & 2)) { + ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1); + deleted= 1; + sprintf(xorriso->info_text, "Deleted "); + } } else if(compare_result&(2|128|(1<<12)|(1<<14)|(1<<15))) { /* iso_adr not existing, size, cannot open iso file, early eof of iso file @@ -895,6 +921,11 @@ overwrite:; if(ret < 0) goto ex; } + if(flag & 2) { + ret= Xorriso_mark_update_merge(xorriso, iso_rr_path, NULL, 1); + if(ret <= 0) + goto ex; + } if(flag & 1) sprintf(xorriso->info_text, "Widened hard link "); else diff --git a/xorriso/cmp_update.h b/xorriso/cmp_update.h index 1e35fb94..33631b71 100644 --- a/xorriso/cmp_update.h +++ b/xorriso/cmp_update.h @@ -23,16 +23,21 @@ int Xorriso_pfx_disk_path(struct XorrisO *xorriso, char *iso_path, /* @param boss_iter Opaque handle to be forwarded to actions in ISO image Set to NULL if calling this function from outside ISO world + @param node Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function from outside ISO world @param flag bit0= update rather than compare */ -int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter, +int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter, void *node, char *iso_path, char *iso_prefix, char *disk_prefix, int flag); /* @param boss_iter Opaque handle to be forwarded to actions in ISO image Set to NULL if calling this function from outside ISO world + @param @node Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function from outside ISO world */ -int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter, +int Xorriso_update_interpreter(struct XorrisO *xorriso, + void *boss_iter, void *node, int compare_result, char *disk_path, char *iso_rr_path, int flag); diff --git a/xorriso/disk_ops.c b/xorriso/disk_ops.c index ea8ccebe..60324be5 100644 --- a/xorriso/disk_ops.c +++ b/xorriso/disk_ops.c @@ -1132,8 +1132,8 @@ int Xorriso_findx_action(struct XorrisO *xorriso, struct FindjoB *job, if(retfind_compare_result) xorriso->find_compare_result= ret; if(ret==0) { - uret= Xorriso_update_interpreter(xorriso, NULL, compare_result, - abs_path, iso_path, (flag&1)<<2); + uret= Xorriso_update_interpreter(xorriso, NULL, NULL, compare_result, + abs_path, iso_path, ((flag&1)<<2) | 2); if(uret<=0) ret= 0; } diff --git a/xorriso/emulators.c b/xorriso/emulators.c index 20e1b392..6984c01f 100644 --- a/xorriso/emulators.c +++ b/xorriso/emulators.c @@ -900,6 +900,7 @@ int Xorriso_genisofs(struct XorrisO *xorriso, char *whom, char *ept, *add_pt, eff_path[SfileadrL], indev[SfileadrL+8], msc[80], *cpt; char old_root[SfileadrL]; char *boot_path, partno_text[8], *iso_rr_pt, *disk_pt; + char *rm_merge_args[3]; /* >>> This should not be static. Why is it ? */ static char *sort_weight_args[4]= {"", "-exec", "sort_weight", ""}; @@ -1595,8 +1596,8 @@ is_pathspec_2:; goto problem_handler_2; } } - /* update_r */ - ret= Xorriso_option_update(xorriso, disk_pt, iso_rr_pt, 1 | 8); + /* update_merge */ + ret= Xorriso_option_update(xorriso, disk_pt, iso_rr_pt, 1 | 8 | 32); } else { mem_graft_points= xorriso->allow_graft_points; xorriso->allow_graft_points= 1; @@ -1634,6 +1635,21 @@ problem_handler_2:; continue; goto ex; } + + if(old_root[0]) { + /* Delete all visited nodes which were not found on disk */ + if(root_seen) + rm_merge_args[0]= xorriso->wdi; + else + rm_merge_args[0]= "/"; + rm_merge_args[1]= "-exec"; + rm_merge_args[2]= "rm_merge"; + zero= 0; + ret= Xorriso_option_find(xorriso, 3, rm_merge_args, &zero, 2); + if(ret<=0) + goto ex; + } + if(lower_r) { static char *lower_r_args[3]= {"/", "-exec", "mkisofs_r"}; zero= 0; diff --git a/xorriso/findjob.h b/xorriso/findjob.h index e5d0e272..05225e73 100644 --- a/xorriso/findjob.h +++ b/xorriso/findjob.h @@ -155,6 +155,9 @@ struct FindjoB { 38= sort_weight number 39= hide on|iso_rr|joliet|off 40= estimate_size + 41= update_merge disk_equiv + 42= rm_merge + 43= clear_merge */ int action; int prune; diff --git a/xorriso/iso_manip.c b/xorriso/iso_manip.c index 0fb7fd6c..d6a3c571 100644 --- a/xorriso/iso_manip.c +++ b/xorriso/iso_manip.c @@ -126,6 +126,11 @@ int Xorriso_graft_split(struct XorrisO *xorriso, IsoImage *volume, if(ret<0) return(ret); *node= (IsoNode *) new_dir; + if(xorriso->update_flags & 1) { + ret= Xorriso_mark_update_merge(xorriso, img_name, node, 1); + if(ret <= 0) + return(0); + } total_parts= size / xorriso->split_size; if(size % xorriso->split_size) total_parts++; @@ -213,6 +218,11 @@ int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume, if(ret <= 0) goto ex; } + if(xorriso->update_flags & 1) { + ret= Xorriso_mark_update_merge(xorriso, img_name, *node, 1); + if(ret <= 0) + goto ex; + } ex:; if(ret<0) { @@ -788,6 +798,12 @@ handle_path_node:; Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } + if(xorriso->update_flags & 1) { + ret= Xorriso_mark_update_merge(xorriso, path, (IsoNode *) hdir, 1); + if(ret <= 0) + return(0); + } + dir= hdir; Xorriso_set_change_pending(xorriso, 0); iso_node_set_ctime((IsoNode *) dir, time(NULL)); @@ -1391,7 +1407,8 @@ int Xorriso_cannot_clone(struct XorrisO *xorriso, char *eff_origin, return(0); } - +/* @param flag bit0= for iso_tree_clone() : merge directories +*/ int Xorriso_clone_tree(struct XorrisO *xorriso, void *boss_iter, char *origin, char *dest, int flag) { @@ -1464,7 +1481,7 @@ int Xorriso_clone_tree(struct XorrisO *xorriso, void *boss_iter, return(ret); new_parent= (IsoDir *) dir_node; - ret = iso_tree_clone(origin_node, new_parent, leafname, &new_node, 0); + ret = iso_tree_clone(origin_node, new_parent, leafname, &new_node, flag & 1); Xorriso_process_msg_queues(xorriso,0); if(ret < 0) { Xorriso_cannot_clone(xorriso, eff_origin, eff_dest, ret, 0); @@ -1518,7 +1535,7 @@ int Xorriso_clone_under(struct XorrisO *xorriso, char *origin, char *dest, ret= 0; goto ex; } } else { - ret = iso_tree_clone(origin_node, dest_dir, namept, &new_node, 0); + ret = iso_tree_clone(origin_node, dest_dir, namept, &new_node, 1); Xorriso_process_msg_queues(xorriso,0); if(ret < 0) { Xorriso_cannot_clone(xorriso, eff_origin, eff_dest, ret, 0); @@ -1850,8 +1867,8 @@ int Xorriso_widen_hardlink(struct XorrisO *xorriso, void * boss_iter, /* >>> compare_result bit17 = is_split */; - ret= Xorriso_update_interpreter(xorriso, boss_iter, compare_result, disk_path, - abs_path, 1); + ret= Xorriso_update_interpreter(xorriso, boss_iter, NULL, + compare_result, disk_path, abs_path, 1); if(ret <= 0) return(ret); return(ret); @@ -2080,10 +2097,13 @@ int Xorriso_findi_action(struct XorrisO *xorriso, struct FindjoB *job, Findjob_set_start_path(subjob, abs_path, 0); ret= Xorriso_findi(xorriso, subjob, boss_iter, boss_mem, NULL, abs_path, &dir_stbuf, depth, 1); - } else if(action==14 || action==17) { /* compare , update */ + } else if(action==14 || action==17 || action == 41) { + /* compare , update , update_merge */ Findjob_get_start_path(job, &iso_prefix, 0); - ret= Xorriso_find_compare(xorriso, (void *) boss_iter, abs_path, - iso_prefix, target, (action==17)|((flag&1)<<1)); + ret= Xorriso_find_compare(xorriso, (void *) boss_iter, (void *) node, + abs_path, iso_prefix, target, + (action == 17 || action == 41) + | ((flag&1)<<1) | ((action == 41) << 2)); if(ret==2) deleted= 1; if(ret==3) @@ -2164,6 +2184,17 @@ int Xorriso_findi_action(struct XorrisO *xorriso, struct FindjoB *job, if(ret > 0) ret= Xorriso_estimate_file_size(xorriso, job, basename, stbuf.st_mode, stbuf.st_size, 0); + } else if(action == 42) { /* rm_merge */ + ret= Xorriso_mark_update_merge(xorriso, show_path, node, 2 | 4); + if(ret == 2) { + ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, 1|hflag); + sprintf(xorriso->info_text, "Deleted "); + Text_shellsafe(show_path, xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); + deleted= 1; + } + } else if(action == 43) { /* clear_merge */ + ret= Xorriso_mark_update_merge(xorriso, show_path, node, 2 | 4); } else { /* includes : 15 in_iso */ sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0)); Xorriso_result(xorriso, 0); @@ -2566,9 +2597,10 @@ int Xorriso_findi(struct XorrisO *xorriso, struct FindjoB *job, mem= boss_mem; hflag= 1; if(action==1 || action==2 || action==3 || action==17 || action == 28 || - action == 32) + action == 32 || action == 41 || action == 42) hflag|= 2; /* need freedom to manipulate image */ - if(action==14 || action==17 || action == 28 || action == 35 || action == 36) + if(action==14 || action==17 || action == 28 || action == 35 || action == 36 || + action == 41) hflag|= 4; /* need LBA sorted iteration for good data reading performance */ ret= Xorriso_findi_iter(xorriso, dir_node, &mem, &iter, &node_array, &node_count, &node_idx, @@ -2980,3 +3012,92 @@ ex:; return(ret); } + +int Xorriso__mark_update_xinfo(void *data, int flag) +{ + /* data is an int disguised as pointer. It does not point to memory. */ + return(1); +} + + +int Xorriso__mark_update_cloner(void *old_data, void **new_data, int flag) +{ + *new_data= NULL; + if(flag) + return(ISO_XINFO_NO_CLONE); + if(old_data == NULL) + return(0); + /* data is an int disguised as pointer. It does not point to memory. */ + *new_data= old_data; + return(0); +} + + +/* @param flag bit0= found on disk + bit1= inquire visit-found status: + 1=not visited, 2=not found, 3=found + bit2= with bit1: delete xinfo before returning status +*/ +int Xorriso_mark_update_merge(struct XorrisO *xorriso, char *path, + void *in_node, int flag) +{ + int ret; + void *xipt= NULL; + IsoNode *node; + + if(in_node == NULL) { + ret= Xorriso_node_from_path(xorriso, NULL, path, &node, 0); + if(ret <= 0) + return(ret); + } else + node= (IsoNode *) in_node; + ret= iso_node_get_xinfo(node, Xorriso__mark_update_xinfo, &xipt); + if(ret < 0) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_report_iso_error(xorriso, "", ret, + "Error when looking for update_merge xinfo", + 0, "FAILURE", 1); + return(0); + } + if(flag & 2) { /* Inquire status and optionally delete xinfo */ + if(ret == 0) + return(1); + if(flag & 4) { + ret= iso_node_remove_xinfo(node, Xorriso__mark_update_xinfo); + if(ret < 0) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_report_iso_error(xorriso, "", ret, + "Error when removing update_merge xinfo", + 0, "FAILURE", 1); + return(0); + } + } + if(((char *) &xipt)[0]) + return(3); + return(2); + } + /* xipt is a byte value disguised as void pointer */ + if(ret == 1) { + if(((char *) &xipt)[0]) + return(1); + if(!(flag & 1)) + return(1); + } else + ((char *) &xipt)[0]= 0; + if(flag & 1) + ((char *) &xipt)[0]= 1; + ret= iso_node_remove_xinfo(node, Xorriso__mark_update_xinfo); + if(ret < 0) + goto set_error; + ret= iso_node_add_xinfo(node, Xorriso__mark_update_xinfo, xipt); + if(ret <= 0) { +set_error:; + Xorriso_process_msg_queues(xorriso,0); + Xorriso_report_iso_error(xorriso, "", ret, + "Error when trying to set update_merge xinfo", + 0, "FAILURE", 1); + return(0); + } + return(1); +} + diff --git a/xorriso/iso_manip.h b/xorriso/iso_manip.h index 7c1a2a5c..30780f3b 100644 --- a/xorriso/iso_manip.h +++ b/xorriso/iso_manip.h @@ -67,6 +67,8 @@ int Xorriso_all_node_array(struct XorrisO *xorriso, int addon_nodes, int flag); int Xorriso__file_start_lba(IsoNode *node, int *lba, int flag); +int Xorriso__mark_update_xinfo(void *data, int flag); +int Xorriso__mark_update_cloner(void *old_data, void **new_data, int flag); #endif /* ! Xorriso_pvt_iso_manip_includeD */ diff --git a/xorriso/lib_mgt.c b/xorriso/lib_mgt.c index ce49f8bf..40d8b0de 100644 --- a/xorriso/lib_mgt.c +++ b/xorriso/lib_mgt.c @@ -55,6 +55,7 @@ #include "xorrisoburn.h" #include "lib_mgt.h" +#include "iso_manip.h" int Xorriso_abort(struct XorrisO *xorriso, int flag) @@ -203,6 +204,9 @@ LIBISOBURN_MISCONFIGURATION_ = 0; zisofs_ctrl.compression_level; } + iso_node_xinfo_make_clonable(Xorriso__mark_update_xinfo, + Xorriso__mark_update_cloner, 0); + /* Second initialization. This time with libs. */ Xorriso_preparer_string(xorriso, xorriso->preparer_id, 0); diff --git a/xorriso/opts_a_c.c b/xorriso/opts_a_c.c index 881d42bf..bda59ca1 100644 --- a/xorriso/opts_a_c.c +++ b/xorriso/opts_a_c.c @@ -1953,14 +1953,20 @@ nondir_exists:; } ret= Xorriso_iso_lstat(xorriso, eff_dest, &stbuf, 0); if(pass == 0) { + /* It is ok if both are directories */; + if(ret >= 0 && S_ISDIR(stbuf.st_mode)) { + ret= Xorriso_iso_lstat(xorriso, eff_origin, &stbuf, 0); + if (ret >= 0 && S_ISDIR(stbuf.st_mode)) + ret= -1; + } if(ret >= 0) { - sprintf(xorriso->info_text, "Cloning: Copy address already exists: "); + sprintf(xorriso->info_text, "Cloning: May not overwrite: "); Text_shellsafe(eff_dest, xorriso->info_text, 1); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); goto problem_handler; } - } else if(ret == -1) { - ret= Xorriso_clone_tree(xorriso, NULL, eff_origin, eff_dest, 0); + } else { + ret= Xorriso_clone_tree(xorriso, NULL, eff_origin, eff_dest, 1); if(ret <= 0) goto problem_handler; sprintf(xorriso->info_text, "Cloned in ISO image: "); diff --git a/xorriso/opts_d_h.c b/xorriso/opts_d_h.c index 4dced9b9..f863b110 100644 --- a/xorriso/opts_d_h.c +++ b/xorriso/opts_d_h.c @@ -875,15 +875,22 @@ not_enough_exec_arguments:; job= new_job; } else if(strcmp(cpt, "compare")==0 || strcmp(cpt, "update")==0 || - strcmp(cpt, "widen_hardlinks")==0) { + strcmp(cpt, "widen_hardlinks")==0 || + strcmp(cpt, "update_merge")==0) { if(i+1>=end_idx) goto not_enough_exec_arguments; i++; action= 14; if(strcmp(cpt, "update")==0) action= 17; - if(strcmp(cpt, "widen_hardlinks")==0) + else if(strcmp(cpt, "widen_hardlinks")==0) action= 32; + else if(strcmp(cpt, "update_merge") == 0) { + action= 41; + /* Enter update_merge mode for node adding */ + xorriso->update_flags|= 1; + } + ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, argv[i], other_path_start, 1|2|4|8); if(ret<=0) @@ -1009,6 +1016,12 @@ not_enough_exec_arguments:; Findjob_set_action_type(job, 39, type, 0); } else if(strcmp(cpt, "estimate_size")==0) { Findjob_set_action_target(job, 40, NULL, 0); + } else if(strcmp(cpt, "rm_merge")==0) { + Findjob_set_action_target(job, 42, NULL, 0); + xorriso->update_flags&= ~1; /* End update_merge mode for node adding */ + } else if(strcmp(cpt, "clear_merge")==0) { + Findjob_set_action_target(job, 43, NULL, 0); + xorriso->update_flags&= ~1; /* End update_merge mode for node adding */ } else { sprintf(xorriso->info_text, "-find -exec: unknown action %s", Text_shellsafe(argv[i], sfe, 0)); diff --git a/xorriso/opts_p_z.c b/xorriso/opts_p_z.c index 674d457f..0f92dd41 100644 --- a/xorriso/opts_p_z.c +++ b/xorriso/opts_p_z.c @@ -1361,6 +1361,9 @@ int Xorriso_option_uid(struct XorrisO *xorriso, char *uid, int flag) bit2= do not issue pacifier messages at all bit3= recursive: -update_r bit4= do not establish and dispose xorriso->di_array + bit5= do not delete files which are not found under + disk_path, but rather mark visited files and mark + files which were found. */ int Xorriso_option_update(struct XorrisO *xorriso, char *disk_path, char *iso_path, int flag) @@ -1447,7 +1450,10 @@ int Xorriso_option_update(struct XorrisO *xorriso, char *disk_path, if(ret >= 0) { argv[0]= eff_dest; argv[1]= "-exec"; - argv[2]= "update"; + if(flag & 32) + argv[2]= "update_merge"; + else + argv[2]= "update"; argv[3]= eff_origin; zero= 0; ret= Xorriso_option_find(xorriso, 4, argv, &zero, @@ -1468,7 +1474,18 @@ int Xorriso_option_update(struct XorrisO *xorriso, char *disk_path, argv[3]= eff_dest; zero= 0; ret= Xorriso_option_find(xorriso, 4, argv, &zero, 1|2); /* -findx */ - if(ret>0 && !xorriso->do_follow_mount) { + if(ret>0 && (!xorriso->do_follow_mount) && !(flag & 32)) { + + /* >>> ??? what about mount points with (flag & 32) ? + empty_iso_dir shall delete those which already existed + and are freshly excluded. (E.g. by mounting at a non-empty + directory, or by new follow rules.) + This deletion does not match the idea of merging. + For determining the foreign files in a directory which is + target of a mount point, one would have to enter that mount + point directory. Somewhat contrary to do-not-follow. + */ + argv[0]= eff_origin; argv[1]= "-type"; argv[2]= "m"; @@ -1495,13 +1512,17 @@ int Xorriso_option_update(struct XorrisO *xorriso, char *disk_path, ret= -1; } } else { + if(flag & 32) + xorriso->update_flags|= 1; /* Enter update_merge mode for node adding */ /* compare ctime too, no filename reporting, eventually silent */ follow_links= (xorriso->do_follow_links || xorriso->do_follow_param) <<28; ret= Xorriso_compare_2_files(xorriso, eff_origin, eff_dest, "", &result, 2 | follow_links | ((flag&4)<<27) | (3<<30)); - if(ret==0) { - uret= Xorriso_update_interpreter(xorriso, NULL, result, eff_origin, - eff_dest, 0); + if(ret == 0 || (ret > 0 && (flag & 32))) { + if(ret > 0) + result= 0; + uret= Xorriso_update_interpreter(xorriso, NULL, NULL, result, eff_origin, + eff_dest, (!!(flag & 32)) << 1); if(uret<=0) ret= -1; if(uret==3) diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index e4c4b89e..24751699 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -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 "Feb 07, 2011" +.TH XORRISO 1 "Feb 12, 2011" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -1065,7 +1065,8 @@ already exists in the ISO tree. .TP \fB\-cp_clone\fR iso_rr_path_original [***] iso_rr_path_dest Create copies of one or more ISO file objects as with command -clone. -Do not not overwrite existing ISO file objects. +Eventually merge directories with existing ones, but do not overwrite +existing ISO file objects. .br The rules for generating the copy addresses are the same as with command -cpr (see above) resp. shell command cp -r. Other than with -cpr, @@ -1649,6 +1650,16 @@ performs command -update with the found file address as iso_rr_path. The corresponding file address is determined like with above action "compare". .br +\fBupdate_merge\fR +is like update but does not delete the found file if it is missing on disk. +It may be run several times and records with all visited files whether their +counterpart on disk has already been seen by one of the update_merge runs. +Finally, a -find run with action "rm_merge" may remove all files that +saw no counterpart on disk. +.br +Up to the next "rm_merge" or "clear_merge" all newly inserted files will +get marked as having a disk counterpart. +.br \fBrm\fR removes the found iso_rr_path from the image if it is not a directory with files in it. I.e. this "rm" includes "rmdir". @@ -1657,6 +1668,14 @@ with files in it. I.e. this "rm" includes "rmdir". removes the found iso_rr_path from the image, including whole directory trees. .br +\fBrm_merge\fR +removes the found iso_rr_path if it was visited by one or more previous actions +"update_merge" and saw no counterpart on disk in any of them. The marking from +the update actions is removed in any case. +.br +\fBclear_merge\fR +removes an eventual marking from action "update_merge". +.br \fBreport_damage\fR classifies files whether they hit a data block that is marked as damaged. The result is printed together with the eventual address @@ -3118,7 +3137,7 @@ not exist in the ISO image. The report format is the same as with command .br \fBadd_missing\fR iso_rr_path_start adds the counterpart if it does not yet -exist in the ISO image. +exist in the ISO image and marks it for "rm_merge" as non-removable. .br E.g.: -findx /home/thomas -exec add_missing /thomas_on_cd -- .br @@ -3550,9 +3569,10 @@ allowed to violate the standard by -compliance option allow_dir_id_ext. This may be avoided by option -disallow_dir_id_ext. .br Option -root is supported. Option -old-root is implemented by xorriso -commands -mkdir, -cp_clone, and -update_r. It sets command -disk_dev_ino -to "ino_only" and -md5 to "on", by default. -disk_dev_ino can be set -to "off" by --old-root-no-ino +commands -mkdir, -cp_clone, -find update_merge, and -find rm_merge. +-root and -old-root set command -disk_dev_ino to "ino_only" and -md5 to "on", +by default. +-disk_dev_ino can be set to "off" by --old-root-no-ino resp. to "on" by --old-root-devno . -md5 can be set to "off" by --old-root-no-md5 . .br @@ -4275,7 +4295,7 @@ $ xorriso \\ .br -not_leaf '*.o' -not_leaf '*.swp' \\ .br - -update_r /home/thomas/open_source_projects /open_source_projects \\ + -update_r /home/thomas/projects /projects \\ .br -update_r /home/thomas/personal_mail /personal_mail \\ .br @@ -4318,20 +4338,33 @@ older sessions in the table-of-content. E.g. as superuser: .br # osirrox -mount /dev/sr0 "volid" '*2008_12_05*' /mnt .br +.sp 1 +This example produces a result similar to -root / -old-root / with mkisofs. +For getting the session trees accumulated in the new sessions, let all -update +commands use a common parent directory and clone it after updating is done: +.br + -update_r /home/thomas/projects /current/projects \\ +.br + -update_r /home/thomas/personal_mail /current/personal_mail \\ +.br + -clone /current /"$(date '+%Y_%m_%d_%H%M%S')" \\ +.br +The cloned tree will have a name like /2011_02_12_155700. +.br +.sp 1 Sessions on multi-session media are separated by several MB of unused blocks. So with small sessions the payload capacity can become substantially lower than the overall media capacity. If the remaining space on media does not suffice for the next gap, the drive is supposed to close the media automatically. .br +.sp 1 \fBBetter do not use your youngest backup for -update_r\fR. Have at least two media which you use alternatingly. So only older backups get endangered by the new write operation, while the newest backup is stored safely on a different media. Always have a blank media ready to perform a full backup in case the update attempt fails due to insufficient remaining capacity. -.br -This example produces a result similar to -root / -old-root / with mkisofs. .SS .B Restore directory trees from a particular ISO session to disk This is an alternative to mounting the media and using normal file operations. diff --git a/xorriso/xorriso.info b/xorriso/xorriso.info index 1e0e54b4..06115582 100644 --- a/xorriso/xorriso.info +++ b/xorriso/xorriso.info @@ -1000,7 +1000,8 @@ filesystem. -cp_clone iso_rr_path_original [***] iso_rr_path_dest Create copies of one or more ISO file objects as with command - -clone. Do not not overwrite existing ISO file objects. + -clone. Eventually merge directories with existing ones, but do + not overwrite existing ISO file objects. The rules for generating the copy addresses are the same as with command -cpr (see above) resp. shell command cp -r. Other than with -cpr, relative iso_rr_path_original will get prepended the @@ -1499,12 +1500,28 @@ File: xorriso.info, Node: CmdFind, Next: Filter, Prev: Manip, Up: Options performs command -update with the found file address as iso_rr_path. The corresponding file address is determined like with above action "compare". + update_merge + is like update but does not delete the found file if it is + missing on disk. It may be run several times and records + with all visited files whether their counterpart on disk has + already been seen by one of the update_merge runs. Finally, + a -find run with action "rm_merge" may remove all files that + saw no counterpart on disk. + Up to the next "rm_merge" or "clear_merge" all newly inserted + files will get marked as having a disk counterpart. rm removes the found iso_rr_path from the image if it is not a directory with files in it. I.e. this "rm" includes "rmdir". rm_r removes the found iso_rr_path from the image, including whole directory trees. + rm_merge + removes the found iso_rr_path if it was visited by one or + more previous actions "update_merge" and saw no counterpart + on disk in any of them. The marking from the update actions + is removed in any case. + clear_merge + removes an eventual marking from action "update_merge". report_damage classifies files whether they hit a data block that is marked as damaged. The result is printed together with the eventual @@ -2763,7 +2780,7 @@ File: xorriso.info, Node: Navigate, Next: Verify, Prev: Inquiry, Up: Options image. The report format is the same as with command -compare. add_missing iso_rr_path_start adds the counterpart if it does not yet exist in the ISO - image. + image and marks it for "rm_merge" as non-removable. E.g.: -findx /home/thomas -exec add_missing /thomas_on_cd -- is_full_in_iso reports if the counterpart in the ISO image contains files. @@ -3166,11 +3183,11 @@ programs trigger comparable actions. option allow_dir_id_ext. This may be avoided by option -disallow_dir_id_ext. Option -root is supported. Option -old-root is implemented by - xorriso commands -mkdir, -cp_clone, and -update_r. It sets command - -disk_dev_ino to "ino_only" and -md5 to "on", by default. - -disk_dev_ino can be set to "off" by --old-root-no-ino resp. to - "on" by --old-root-devno . -md5 can be set to "off" by - --old-root-no-md5 . + xorriso commands -mkdir, -cp_clone, -find update_merge, and -find + rm_merge. -root and -old-root set command -disk_dev_ino to + "ino_only" and -md5 to "on", by default. -disk_dev_ino can be set + to "off" by --old-root-no-ino resp. to "on" by --old-root-devno . + -md5 can be set to "off" by --old-root-no-md5 . Not original mkisofs options are --quoted_path_list , --hardlinks , --acl , --xattr , --md5 , --stdio_sync . They work like the xorriso options with the same name and hardcoded argument "on", @@ -3805,7 +3822,7 @@ $ xorriso \ -dev /dev/sr0 \ -volid PROJECTS_MAIL_"$(date '+%Y_%m_%d_%H%M%S')" \ -not_leaf '*.o' -not_leaf '*.swp' \ --update_r /home/thomas/open_source_projects /open_source_projects \ +-update_r /home/thomas/projects /projects \ -update_r /home/thomas/personal_mail /personal_mail \ -commit -toc -check_md5 FAILURE -- -eject all @@ -3843,6 +3860,15 @@ commands for older sessions in the table-of-content. E.g. as superuser: # osirrox -mount /dev/sr0 "volid" '*2008_12_05*' /mnt +This example produces a result similar to -root / -old-root / with +mkisofs. For getting the session trees accumulated in the new +sessions, let all -update commands use a common parent directory and +clone it after updating is done: +-update_r /home/thomas/projects /current/projects \ +-update_r /home/thomas/personal_mail /current/personal_mail \ +-clone /current /"$(date '+%Y_%m_%d_%H%M%S')" \ +The cloned tree will have a name like /2011_02_12_155700. + Sessions on multi-session media are separated by several MB of unused blocks. So with small sessions the payload capacity can become substantially lower than the overall media capacity. If the remaining @@ -3856,9 +3882,6 @@ stored safely on a different media. Always have a blank media ready to perform a full backup in case the update attempt fails due to insufficient remaining capacity. -This example produces a result similar to -root / -old-root / with -mkisofs. -  File: xorriso.info, Node: ExRestore, Next: ExRecovery, Prev: ExIncBackup, Up: Examples @@ -4468,45 +4491,45 @@ Node: Options23227 Node: AqDrive24835 Node: Loading27741 Node: Insert40885 -Node: SetInsert50450 -Node: Manip59017 -Node: CmdFind67698 -Node: Filter78122 -Node: Writing82471 -Node: SetWrite88760 -Node: Bootable102370 -Node: Jigdo114677 -Node: Charset118935 -Node: Exception121686 -Node: DialogCtl126201 -Node: Inquiry128788 -Node: Navigate133121 -Node: Verify141016 -Node: Restore149605 -Node: Emulation156261 -Node: Scripting165493 -Node: Frontend171055 -Node: Examples172350 -Node: ExDevices173519 -Node: ExCreate174153 -Node: ExDialog175427 -Node: ExGrowing176689 -Node: ExModifying177491 -Node: ExBootable177992 -Node: ExCharset178539 -Node: ExPseudo179367 -Node: ExCdrecord180261 -Node: ExMkisofs180576 -Node: ExGrowisofs181579 -Node: ExException182703 -Node: ExTime183157 -Node: ExIncBackup183616 -Node: ExRestore187184 -Node: ExRecovery188153 -Node: Files188719 -Node: Seealso189947 -Node: Legal190471 -Node: CommandIdx191393 -Node: ConceptIdx205765 +Node: SetInsert50504 +Node: Manip59071 +Node: CmdFind67752 +Node: Filter79052 +Node: Writing83401 +Node: SetWrite89690 +Node: Bootable103300 +Node: Jigdo115607 +Node: Charset119865 +Node: Exception122616 +Node: DialogCtl127131 +Node: Inquiry129718 +Node: Navigate134051 +Node: Verify141991 +Node: Restore150580 +Node: Emulation157236 +Node: Scripting166510 +Node: Frontend172072 +Node: Examples173367 +Node: ExDevices174536 +Node: ExCreate175170 +Node: ExDialog176444 +Node: ExGrowing177706 +Node: ExModifying178508 +Node: ExBootable179009 +Node: ExCharset179556 +Node: ExPseudo180384 +Node: ExCdrecord181278 +Node: ExMkisofs181593 +Node: ExGrowisofs182596 +Node: ExException183720 +Node: ExTime184174 +Node: ExIncBackup184633 +Node: ExRestore188553 +Node: ExRecovery189522 +Node: Files190088 +Node: Seealso191316 +Node: Legal191840 +Node: CommandIdx192762 +Node: ConceptIdx207134  End Tag Table diff --git a/xorriso/xorriso.texi b/xorriso/xorriso.texi index 64e86a93..04915b4a 100644 --- a/xorriso/xorriso.texi +++ b/xorriso/xorriso.texi @@ -44,7 +44,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 "Feb 07, 2011" +@c man .TH XORRISO 1 "Feb 12, 2011" @c man .\" Please adjust this date whenever revising the manpage. @c man .\" @c man .\" Some roff macros, for reference: @@ -1331,7 +1331,8 @@ already exists in the ISO tree. @kindex -cp_clone copies ISO directory tree @cindex Directories, copy, -cp_clone Create copies of one or more ISO file objects as with command -clone. -Do not not overwrite existing ISO file objects. +Eventually merge directories with existing ones, but do not overwrite +existing ISO file objects. @* The rules for generating the copy addresses are the same as with command -cpr (see above) resp. shell command cp -r. Other than with -cpr, @@ -2013,6 +2014,16 @@ performs command -update with the found file address as iso_rr_path. The corresponding file address is determined like with above action "compare". @* +@item update_merge +is like update but does not delete the found file if it is missing on disk. +It may be run several times and records with all visited files whether their +counterpart on disk has already been seen by one of the update_merge runs. +Finally, a -find run with action "rm_merge" may remove all files that +saw no counterpart on disk. +@* +Up to the next "rm_merge" or "clear_merge" all newly inserted files will +get marked as having a disk counterpart. +@* @item rm removes the found iso_rr_path from the image if it is not a directory with files in it. I.e. this "rm" includes "rmdir". @@ -2021,6 +2032,14 @@ with files in it. I.e. this "rm" includes "rmdir". removes the found iso_rr_path from the image, including whole directory trees. @* +@item rm_merge +removes the found iso_rr_path if it was visited by one or more previous actions +"update_merge" and saw no counterpart on disk in any of them. The marking from +the update actions is removed in any case. +@* +@item clear_merge +removes an eventual marking from action "update_merge". +@* @item report_damage classifies files whether they hit a data block that is marked as damaged. The result is printed together with the eventual address @@ -3708,7 +3727,7 @@ not exist in the ISO image. The report format is the same as with command @* @item add_missing iso_rr_path_start adds the counterpart if it does not yet -exist in the ISO image. +exist in the ISO image and marks it for "rm_merge" as non-removable. @* E.g.: -findx /home/thomas -exec add_missing /thomas_on_cd @minus{}@minus{} @* @@ -4205,9 +4224,10 @@ allowed to violate the standard by -compliance option allow_dir_id_ext. This may be avoided by option -disallow_dir_id_ext. @* Option -root is supported. Option -old-root is implemented by xorriso -commands -mkdir, -cp_clone, and -update_r. It sets command -disk_dev_ino -to "ino_only" and -md5 to "on", by default. -disk_dev_ino can be set -to "off" by @minus{}@minus{}old-root-no-ino +commands -mkdir, -cp_clone, -find update_merge, and -find rm_merge. +-root and -old-root set command -disk_dev_ino to "ino_only" and -md5 to "on", +by default. +@minus{}disk_dev_ino can be set to "off" by @minus{}@minus{}old-root-no-ino resp. to "on" by @minus{}@minus{}old-root-devno . @minus{}md5 can be set to "off" by @minus{}@minus{}old-root-no-md5 . @* @@ -5129,7 +5149,7 @@ $ xorriso \ @* -not_leaf '*.o' -not_leaf '*.swp' \ @* - -update_r /home/thomas/open_source_projects /open_source_projects \ + -update_r /home/thomas/projects /projects \ @* -update_r /home/thomas/personal_mail /personal_mail \ @* @@ -5179,6 +5199,21 @@ older sessions in the table-of-content. E.g. as superuser: # osirrox -mount /dev/sr0 "volid" '*2008_12_05*' /mnt @* @sp 1 +@c man .sp 1 +Above example produces a result similar to -root / -old-root / with mkisofs. +For getting the session trees accumulated in the new sessions, let all -update +commands use a common parent directory and clone it after updating is done: +@* + -update_r /home/thomas/projects /current/projects \ +@* + -update_r /home/thomas/personal_mail /current/personal_mail \ +@* + -clone /current /"$(date '+%Y_%m_%d_%H%M%S')" \ +@* +The cloned tree will have a name like /2011_02_12_155700. +@* +@sp 1 +@c man .sp 1 Sessions on multi-session media are separated by several MB of unused blocks. So with small sessions the payload capacity can become substantially lower than the overall media capacity. If the remaining space on media does not @@ -5186,15 +5221,13 @@ suffice for the next gap, the drive is supposed to close the media automatically. @* @sp 1 +@c man .sp 1 @strong{Better do not use your youngest backup for -update_r}. Have at least two media which you use alternatingly. So only older backups get endangered by the new write operation, while the newest backup is stored safely on a different media. Always have a blank media ready to perform a full backup in case the update attempt fails due to insufficient remaining capacity. -@* -@sp 1 -This example produces a result similar to -root / -old-root / with mkisofs. @c man .SS @c man .B Restore directory trees from a particular ISO session to disk @node ExRestore, ExRecovery, ExIncBackup, Examples diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index 812dc745..0336fe31 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -582,6 +582,10 @@ struct XorrisO { /* the global context of xorriso */ struct PermiteM *perm_stack; /* Temporarily altered dir access permissions */ + /* bit0= update_merge active: mark all newly added nodes as visited+found + */ + int update_flags; + /* result (stdout, R: ) */ char result_line[10*SfileadrL]; int result_line_counter; diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 4ddbcb74..d90101bf 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2011.02.08.133624" +#define Xorriso_timestamP "2011.02.12.171423" diff --git a/xorriso/xorrisoburn.h b/xorriso/xorrisoburn.h index f5b2e4bb..50edad5d 100644 --- a/xorriso/xorrisoburn.h +++ b/xorriso/xorrisoburn.h @@ -567,6 +567,8 @@ int Xorriso_clone_tree(struct XorrisO *xorriso, void *boss_iter, int Xorriso_clone_under(struct XorrisO *xorriso, char *origin, char *dest, int flag); +int Xorriso_mark_update_merge(struct XorrisO *xorriso, char *path, + void *node, int flag); #endif /* Xorrisoburn_includeD */