diff --git a/xorriso/iso_manip.c b/xorriso/iso_manip.c index b9751a14..6aed3ae1 100644 --- a/xorriso/iso_manip.c +++ b/xorriso/iso_manip.c @@ -144,7 +144,7 @@ int Xorriso_graft_split(struct XorrisO *xorriso, IsoImage *volume, offset, xorriso->split_size, &part_node, 8); if(ret<=0) - return(0); + return(ret); } sprintf(xorriso->info_text, "Split into %d parts: %s", total_parts, Text_shellsafe(nominal_target, sfe, 0)); @@ -154,7 +154,9 @@ int Xorriso_graft_split(struct XorrisO *xorriso, IsoImage *volume, /* - @param flag bit3= cut_out_node: offset and size are valid + @param flag bit0= ISO_NODE_NAME_NOT_UNIQUE exception mode: + Do not issue message. Return existing node into *node. + bit3= cut_out_node: offset and size are valid bit8= hide in iso_rr bit9= hide in joliet */ @@ -226,14 +228,18 @@ int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume, ex:; if(ret<0) { - Xorriso_process_msg_queues(xorriso,0); - if(ret == ISO_RR_NAME_TOO_LONG || ret == ISO_RR_NAME_RESERVED || - ret == ISO_RR_PATH_TOO_LONG) - namept= nominal_target; - else - namept= nominal_source; - Xorriso_report_iso_error(xorriso, namept, ret, - "Cannot add node to tree", 0, "FAILURE", 1|2); + if(ret == ISO_NODE_NAME_NOT_UNIQUE && (flag & 1)) { + iso_dir_get_node(dir, img_name, node); + } else { + Xorriso_process_msg_queues(xorriso,0); + if(ret == ISO_RR_NAME_TOO_LONG || ret == ISO_RR_NAME_RESERVED || + ret == ISO_RR_PATH_TOO_LONG) + namept= nominal_target; + else + namept= nominal_source; + Xorriso_report_iso_error(xorriso, namept, ret, + "Cannot add node to tree", 0, "FAILURE", 1|2); + } return(ret); } if(LIBISO_ISREG(*node)) @@ -242,6 +248,70 @@ ex:; } +/* + @param boss_iter Opaque handle to be forwarded to actions in ISO image + Set to NULL if calling this function without having + a boss iterator objetc. + @param node Pointer to pointer to existing node, + *node is set to NULL, if the node gets removed. + @param flag bit0= source is directory + bit4= return 3 on rejection by exclusion or user + bit6= do not delete eventually existing node from di_array + bit7= no special handling of split file directories + @return 1= no action was needed, 2= target removed, + 3= rejected with bit4, <=0 means error +*/ +int Xoriso_handle_collision(struct XorrisO *xorriso, void *boss_iter, + IsoNode **node, char *img_path, + char *full_img_path, char *disk_path, + char *show_path, int flag) +{ + int ret, target_is_dir, target_is_split, source_is_dir; + + source_is_dir= flag & 1; + target_is_dir= LIBISO_ISDIR(*node); + + target_is_split= 0; + if(target_is_dir && !(flag & 128)) + target_is_split= Xorriso_is_split(xorriso, "", (void *) *node, 1 | 2); + + if(!((target_is_dir && !target_is_split) && source_is_dir)) { + Xorriso_process_msg_queues(xorriso, 0); + + /* handle overwrite situation */; + if(xorriso->do_overwrite == 1 || + (xorriso->do_overwrite == 2 && !(target_is_dir && !target_is_split))) { + ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, img_path, + 1 | 8 | (flag & 64)); + if(ret <= 0) + return(ret); + if(ret == 3) { + sprintf(xorriso->info_text, "User revoked adding of: "); + Text_shellsafe(show_path, xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(3 * !!(flag & 16)); + } + *node= NULL; + return(2); + } + + if (disk_path[0]) + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + if(strcmp(full_img_path, img_path) == 0) + sprintf(xorriso->info_text, + "While grafting '%s' : file object exists and may not be overwritten", + img_path); + else + sprintf(xorriso->info_text, + "While grafting '%s' : '%s' exists and may not be overwritten", + full_img_path, img_path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + return(1); +} + + /* @param flag bit0= recursion is active bit1= do not report added files bit6= do not delete eventually existing node from di_array @@ -255,8 +325,8 @@ int Xorriso_add_tree(struct XorrisO *xorriso, IsoDir *dir, { IsoImage *volume; IsoNode *node; - int ret, target_is_dir, source_is_dir, source_is_link, fret, was_failure= 0; - int do_not_dive, target_is_split= 0, hide_attrs; + int ret, source_is_dir, source_is_link, fret, was_failure= 0; + int do_not_dive, hide_attrs; struct DirseQ *dirseq= NULL; char *name, *img_name, *srcpt, *stbuf_src= ""; struct stat stbuf, hstbuf; @@ -265,6 +335,15 @@ int Xorriso_add_tree(struct XorrisO *xorriso, IsoDir *dir, char *sfe= NULL, *sfe2= NULL; char *disk_path= NULL, *img_path= NULL, *link_target= NULL; +#define Xorriso_add_handle_collisioN 1 +#define Xorriso_optimistic_add_treE 1 + +#ifndef Xorriso_optimistic_add_treE +#ifndef Xorriso_add_handle_collisioN + int target_is_split= 0, target_is_dir; +#endif +#endif + /* Avoiding large local memory objects in order to save stack space */ sfe= malloc(5*SfileadrL); sfe2= malloc(5*SfileadrL); @@ -404,6 +483,28 @@ cannot_lstat:; do_not_dive= 1; } +#ifdef Xorriso_optimistic_add_treE + + ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name, + "", img_path, (off_t) 0, (off_t) 0, + &node, 1 | (hide_attrs << 8)); + if(ret == ISO_NODE_NAME_NOT_UNIQUE) { + ret= Xoriso_handle_collision(xorriso, NULL, &node, img_path, img_path, + srcpt, img_path, + (!!source_is_dir) | (flag & (64 | 128))); + if(ret <= 0) + goto was_problem; + if(node == NULL) { + ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name, + "", img_path, (off_t) 0, (off_t) 0, + &node, (hide_attrs << 8)); + if(ret <= 0) + node= NULL; + } + } + +#else /* Xorriso_optimistic_add_treE */ + /* does a node exist with this name ? */ node= NULL; if(dir != NULL) { @@ -450,6 +551,9 @@ cannot_lstat:; "", img_path, (off_t) 0, (off_t) 0, &node, (hide_attrs << 8)); } + +#endif /* Xorriso_optimistic_add_treE */ + if(node==NULL) { Xorriso_process_msg_queues(xorriso,0); Xorriso_msgs_submit(xorriso, 0, stbuf_src, 0, "ERRFILE", 0); @@ -624,12 +728,21 @@ int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter, IsoImage *volume; char path[SfileadrL], *apt, *npt, *cpt, sfe[5*SfileadrL], sfe2[5*SfileadrL]; char *disk_path_pt, resolved_disk_path[SfileadrL]; - IsoDir *dir, *hdir; + IsoDir *dir= NULL, *hdir; IsoNode *node; - int done= 0, is_dir= 0, l, ret, target_is_dir, source_is_dir, resolve_link= 0; - int target_is_split, hide_attrs; + int done= 0, is_dir= 0, l, ret, source_is_dir, resolve_link= 0; + int hide_attrs; struct stat stbuf; +#define Xorriso_graft_handle_collisioN 1 +#define Xorriso_optimistic_graft_iN 1 + +#ifndef Xorriso_optimistic_graft_iN +#ifndef Xorriso_graft_handle_collisioN + int target_is_split, target_is_dir; +#endif +#endif + hide_attrs= (flag >> 8) & 3; if (disk_path == NULL && !(flag & 1)) { Xorriso_msgs_submit(xorriso, 0, @@ -753,8 +866,136 @@ int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter, continue; } source_is_dir= (is_dir || (flag&1) || !done); - ret= Xorriso_node_from_path(xorriso, volume, path, &node, 1); + +#ifdef Xorriso_optimistic_graft_iN + + /* Directories of the source path are likely to exist already as directory + in the image. + That will cause two lookups with optimistic, and only one with + pessimistic. + So optimism will pay off only with the leaf. I.e. if(done). + */ + if(source_is_dir) { /* eventually create directory */ + ret= iso_dir_get_node(dir, apt, &node); + if(ret > 0) { + ret= Xoriso_handle_collision(xorriso, boss_iter, &node, path, + img_path, disk_path, + disk_path[0] ? disk_path : img_path, + (!!source_is_dir) | (flag & (16 | 64 | 128))); + if(ret <= 0 || ret == 3) + return(ret); + if(ret == 1 && node != NULL) + dir= (IsoDir *) node; + } else + node= NULL; + if(node == NULL) { + ret= iso_tree_add_new_dir(dir, apt, &hdir); + if(ret < 0) { + Xorriso_process_msg_queues(xorriso,0); + if(disk_path[0]) + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + Xorriso_report_iso_error(xorriso, img_path, ret, + "Cannot create directory", 0, "FAILURE", 1); + sprintf(xorriso->info_text, + "While grafting '%s' : could not insert '%s'", img_path, path); + 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)); + iso_node_set_uid((IsoNode *) dir, geteuid()); + iso_node_set_gid((IsoNode *) dir, getegid()); + + if(disk_path[0] && !done) { + /* This not only copies disk directory properties + but also sets eventual hide_attrs */ + Xorriso_copy_implicit_properties(xorriso, dir, img_path, path, + disk_path, !!(flag&8)); + } + } + } + + if(done) { +attach_source:; + if(flag&1) { + /* directory node was created above */; + + } else if(is_dir) { + Xorriso_transfer_properties(xorriso, &stbuf, disk_path, + (IsoNode *) dir, 4 | 32); + if(!(flag&32)) { + ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL, + flag & (2 | 64 | 128)); + if(ret<=0) + return(ret); + } + } else { + if(resolve_link) { + ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0); + if(ret<=0) + return(ret); + disk_path_pt= resolved_disk_path; + } else + disk_path_pt= disk_path; + + ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt, + disk_path, img_path, offset, cut_size, + &node, 1 | (flag & 8) | (hide_attrs << 8)); + if(ret == ISO_NODE_NAME_NOT_UNIQUE) { + ret= Xoriso_handle_collision(xorriso, boss_iter, &node, img_path, + img_path, disk_path, + disk_path[0] ? disk_path : img_path, + (flag & (16 | 64 | 128))); + if(ret <= 0 || ret == 3) + return(ret); + ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt, + disk_path, img_path, offset, cut_size, + &node, (flag & 8) | (hide_attrs << 8)); + } + if(ret<=0) { + sprintf(xorriso->info_text, "Grafting failed: %s = %s", + Text_shellsafe(img_path,sfe,0), Text_shellsafe(disk_path,sfe2,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + Xorriso_set_change_pending(xorriso, 0); + iso_node_set_name(node, apt); + + xorriso->pacifier_count++; + if(xorriso->pacifier_count%100 && !(flag&2)) + Xorriso_pacifier_callback(xorriso, "files added", + xorriso->pacifier_count, + xorriso->pacifier_total, "", 0); + } + } else + *npt= '/'; + +#else /* Xorriso_optimistic_graft_iN */ + + node= NULL; + ret= iso_dir_get_node(dir, apt, &node); if(ret>0) { + +#ifdef Xorriso_graft_handle_collisioN + + ret= Xoriso_handle_collision(xorriso, boss_iter, &node, path, img_path, + disk_path, + disk_path[0] ? disk_path : img_path, + (!!source_is_dir) | (flag & (16 | 64 | 128))); + if(ret <= 0 || ret == 3) + return(ret); + if(ret == 2) + goto handle_path_node; + +#else /* Xorriso_graft_handle_collisioN */ + target_is_dir= LIBISO_ISDIR(node); target_is_split= 0; @@ -790,6 +1031,9 @@ int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter, Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } + +#endif /* ! Xorriso_graft_handle_collisioN */ + dir= (IsoDir *) node; } @@ -868,7 +1112,11 @@ attach_source:; } } else *npt= '/'; + +#endif /* ! Xorriso_optimistic_graft_iN */ + } + Xorriso_process_msg_queues(xorriso,0); return(1+!!is_dir); } diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index e966a10b..6255173f 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2011.04.27.150829" +#define Xorriso_timestamP "2011.04.30.121138"