From 24ad7e5abe511eeae1cbdc1ef20db874887396d3 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Wed, 11 Jun 2008 13:15:43 +0000 Subject: [PATCH] Proper handling of restore overwrite situations with directories and softlinks --- xorriso/xorriso.1 | 19 +++++--- xorriso/xorriso_timestamp.h | 2 +- xorriso/xorrisoburn.c | 89 +++++++++++++++++++++++++++++++++++-- 3 files changed, 98 insertions(+), 12 deletions(-) diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index bb382efd..342e2f3a 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -2,7 +2,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH XORRISO 1 "Jun, 6, 2008" +.TH XORRISO 1 "Jun, 11, 2008" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -15,6 +15,7 @@ .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) +.nh .SH NAME xorriso - creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions. @@ -1144,7 +1145,7 @@ Setting "on" allows automatic -rm_r. I.e. a non-directory can replace an existing directory and all its subordinates. .br If restoring of files is enabled, then the overwrite rule applies to the -target file objects on disk as well. +target file objects on disk as well, but "on" is downgraded to "nondir". .TP \fB\-split_size\fR number["k"|"m"] Set the threshold for automatic splitting of regular files. Such splitting @@ -1612,16 +1613,17 @@ from ISO images and to create, overwrite, or delete file objects on disk. .br Disk file exclusions by -not_mgt, -not_leaf, -not_paths apply. If disk file objects already exist then the settings of -overwrite and --reassure apply. +-reassure apply. But -overwrite "on" only triggers the behavior +of -overwrite "nondir". I.e. directories cannot be deleted. +.br +Access permissions of files in the ISO image do not restrict restoring. +The permissions on disk have to allow writing, of course. .TP \fB\-osirrox\fR "on"|"device_files"|"off"[:option:...] Setting "off" disables disk filesystem manipulations. This is the default unless the program was started with leafname "osirrox". Elsewise the capability to restore files can be enabled explicitly by -osirrox "on". .br -Access permissions of files in the ISO image do not restrict restoring. -The permissions on disk have to allow writing, of course. -.br To enable restoring of special files by "device_files" is potentially dangerous. The meaning of the number st_rdev (see man 2 stat) depends much on the @@ -1644,7 +1646,7 @@ handled like any other ISO image directory. Extract single leaf file objects from the ISO image and store them under the address given by disk_path. If more then one iso_rr_path is given then disk_path must be a directory or non-existent. In the latter case it gets -created. The extracted files get installed in it with the same leafnames. +created and the extracted files get installed in it with the same leafnames. .br Missing directory components in disk_path will get created, if possible. .br @@ -1658,6 +1660,9 @@ ownership and group as in ISO image. .TP \fB\-cp_rx\fR iso_rr_path [***] disk_path Like -cpx but also extracting whole directory trees from the ISO image. +.br +If disk_path is an existing directory then the trees will be inserted +underneath this directory and will keep their leaf names. If directories do already exist under disk_path then their content eventually gets merged with the content of restored directories of the same name. Directory attributes get extracted only if the disk diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 5cb714d0..66e3c1ff 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.06.10.100231" +#define Xorriso_timestamP "2008.06.11.131607" diff --git a/xorriso/xorrisoburn.c b/xorriso/xorrisoburn.c index 2eea5c88..b28df93e 100644 --- a/xorriso/xorrisoburn.c +++ b/xorriso/xorrisoburn.c @@ -2811,6 +2811,55 @@ ex:; } +/* @param flag bit0= source is a directory and not to be restored as split file + @return <=0 error , 1=collision handled , 2=no collision , 3=revoked by user +*/ +int Xorriso_handle_collision(struct XorrisO *xorriso, + IsoNode *node, char *img_path, + char *disk_path, char *nominal_disk_path, + int *stbuf_ret, int flag) +{ + int ret, target_is_dir= 0, target_is_link= 0, stat_ret; + struct stat target_stbuf, lt_stbuf; + + /* does a disk file exist with this name ? */ + *stbuf_ret= lstat(disk_path, &target_stbuf); + + if(*stbuf_ret==-1) + return(2); + + target_is_link= S_ISLNK(target_stbuf.st_mode); + if(target_is_link) { + stat_ret= stat(disk_path, <_stbuf); + if(stat_ret!=-1) + target_is_dir= S_ISDIR(lt_stbuf.st_mode); + } else { + target_is_dir= S_ISDIR(target_stbuf.st_mode); + } + if(target_is_dir && (!target_is_link) && !(flag&2)) { + strcpy(xorriso->info_text, "Attempt to replace DISK directory "); + Text_shellsafe(nominal_disk_path, + xorriso->info_text+strlen(xorriso->info_text), 0); + strcat(xorriso->info_text, " by ISO file "); + Text_shellsafe(img_path, xorriso->info_text+strlen(xorriso->info_text), 0); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + + if(!(target_is_dir && (flag&1))) { + Xorriso_process_msg_queues(xorriso,0); + ret= Xorriso_restore_overwrite(xorriso, node, img_path, disk_path, + nominal_disk_path, &target_stbuf, 16); + if(ret==3) + return(3); + if(ret<=0) + return(ret); + *stbuf_ret= -1; /* It might still exist but will be handled properly */ + } + return(1); +} + + /* @param flag bit0= recursion is active bit1= do not report restored files bit6= this is a copy action: do not fake times and ownership @@ -2825,15 +2874,20 @@ int Xorriso_restore_tree(struct XorrisO *xorriso, IsoDir *dir, IsoDirIter *iter= NULL; IsoNode **node_array= NULL; int node_count, node_idx; - int ret, target_is_dir, source_is_dir, source_is_link, fret, was_failure= 0; + int ret, source_is_dir, source_is_link, fret, was_failure= 0; int do_not_dive, source_is_split= 0, len_dp, len_ip, stbuf_ret, hflag, hret; char *name, *disk_name, *leaf_name, *srcpt, *stbuf_src= ""; - struct stat stbuf, target_stbuf; struct LinkiteM *own_link_stack; char *sfe= NULL, *sfe2= NULL; char *disk_path= NULL, *img_path= NULL, *link_target= NULL; off_t mem; struct PermiteM *perm_stack_mem; + struct stat stbuf; + +#ifdef NIX + struct stat target_stbuf; + target_is_dir; +#endif perm_stack_mem= xorriso->perm_stack; @@ -2984,6 +3038,7 @@ much_too_long:; if(source_is_split) do_not_dive= 1; +#ifdef NIX /* >>> handle softlinks */; @@ -3002,6 +3057,15 @@ much_too_long:; } } +#else /* NIX */ + + ret= Xorriso_handle_collision(xorriso, node, img_path, disk_path, disk_path, + &stbuf_ret, (source_is_dir && !source_is_split)); + if(ret<=0 || ret==3) + goto was_problem; + +#endif /* ! NIX */ + if(stbuf_ret!=-1) { /* (Can only happen with directory) */ /* ??? >>> eventually open access to existing directory ? */; @@ -3085,11 +3149,16 @@ int Xorriso_restore(struct XorrisO *xorriso, IsoImage *volume; char path[SfileadrL], *apt, *npt, sfe[5*SfileadrL]; IsoNode *node= NULL; - int done= 0, is_dir= 0, ret, target_is_dir, source_is_dir, stbuf_ret, hret; + int done= 0, is_dir= 0, ret, source_is_dir, stbuf_ret, hret; int leaf_is_split= 0, source_is_split= 0, new_dir_made= 0; - struct stat stbuf, target_stbuf; + struct stat stbuf; struct PermiteM *perm_stack_mem; +#ifdef NIX + struct stat target_stbuf; + int target_is_dir; +#endif + perm_stack_mem= xorriso->perm_stack; ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&4)); @@ -3154,6 +3223,8 @@ int Xorriso_restore(struct XorrisO *xorriso, source_is_dir= (is_dir || (flag&1) || !done); source_is_split= done && leaf_is_split; +#ifdef NIX + /* >>> handle softlinks */; stbuf_ret= stat(path, &target_stbuf); @@ -3168,6 +3239,16 @@ int Xorriso_restore(struct XorrisO *xorriso, stbuf_ret= -1; /* now it is removed (or can be handled properly) */ } } + +#else /* NIX */ + + ret= Xorriso_handle_collision(xorriso, node, img_path, path, disk_path, + &stbuf_ret, (source_is_dir && !source_is_split)); + if(ret<=0 || ret==3) + goto ex; + +#endif /* ! NIX */ + new_dir_made= 0; if(stbuf_ret==-1 && (source_is_dir && !source_is_split)) { /* make a directory */