From b595c7f836951a2ac695135ace0475a298a45a36 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Thu, 5 Jun 2008 16:51:04 +0000 Subject: [PATCH] New options -cpax, -cp_rx, cp_rax to restore files and trees from ISO to disk --- xorriso/xorriso.1 | 37 ++- xorriso/xorriso.c | 51 +++- xorriso/xorriso_timestamp.h | 2 +- xorriso/xorrisoburn.c | 549 ++++++++++++++++++++++++++++-------- 4 files changed, 502 insertions(+), 137 deletions(-) diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index 90ee9f41..e9192353 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, 02, 2008" +.TH XORRISO 1 "Jun, 5, 2008" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -146,7 +146,7 @@ There are two families of media in the MMC standard: unformatted DVD-RW. These media provide a table of content which describes their existing sessions. See option \fB-toc\fR. .br -\fBOverwriteable\fR media are DVD-RAM, DVD+RW, and formatted DVD-RW. +\fBOverwriteable\fR media are DVD-RAM, DVD+RW, BD-RE, and formatted DVD-RW. They allow random write access but do not provide information about their session history. If they contain one or more ISO 9660 sessions and if the first session was written by xorriso, then a table of content can @@ -181,7 +181,7 @@ Appendable is the state after writing a session with option -close off. for xorriso. .br Closed is the state of DVD-ROM media and of multi-session media which were -written with option -close on. If the drive is incapable of writing it will +written with option -close on. If the drive is read-only hardware then it will probably show any media as closed CD-ROM resp. DVD-ROM. .br Overwriteable media assume this state in such read-only drives or if they @@ -1140,6 +1140,9 @@ 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. +.br +If restoring of files is enabled, then the overwrite rule applies to the +target file objects on disk as well. .TP \fB\-split_size\fR number["k"|"m"] Set the threshold for automatic splitting of regular files. Such splitting @@ -1385,6 +1388,8 @@ If "on" then ask the user for "y" or "n": .br before deleting or overwriting any file in the ISO image, .br +before overwriting any disk file during restore operations, +.br before rolling back pending image changes, .br before committing image changes to media, @@ -1602,12 +1607,19 @@ Normally xorriso only writes to disk files which were given as stdio: pseudo-drives or as log files. But its alter ego, osirrox, is able to extract file objects 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. .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 @@ -1624,7 +1636,7 @@ directories as data files if the directory contains a complete collection of -cut_out part files. .br With option "concat_split_off" such directories are -handled as any other ISO image directory. +handled like any other ISO image directory. .TP \fB\-cpx\fR iso_rr_path [***] disk_path Extract single leaf file objects from the ISO image and store them under @@ -1633,13 +1645,26 @@ 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. .br Missing directory components in disk_path will get created, if possible. -Disk file exclusions are in effect. If this is undesired then perform --not_mgt "off" first. .br Directories are allowed as iso_rr_path only with -osirrox "concat_split_on" and only if they actually represent a complete collection of -cut_out split file parts. .TP +\fB\-cpax\fR iso_rr_path [***] disk_path +Like -cpx but restoring mtime, atime as in ISO image and trying to set +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. +If directories do already exist under disk_path then their content +eventually gets merged with the content of restored directories +of the same name. Disk files get removed only if they are to be replaced +by file objects from the ISO image. +.TP +\fB\-cp_rax\fR iso_rr_path [***] disk_path +Like -cp_rx but restoring mtime, atime as in ISO image and trying to set +ownership and group as in ISO image. +.TP .B Command compatibility emulations: .PP Writing of ISO 9660 on CD is traditionally done by program mkisofs diff --git a/xorriso/xorriso.c b/xorriso/xorriso.c index 9fa83670..09bfedb3 100644 --- a/xorriso/xorriso.c +++ b/xorriso/xorriso.c @@ -2692,12 +2692,14 @@ failed:; /* @param flag bit0= minimal transfer: access permissions only + bit1= do not set timestamps */ int Permstack_pop(struct PermiteM **o, struct PermiteM *stopper, struct XorrisO *xorriso, int flag) { int ret; char sfe[5*SfileadrL]; + struct utimbuf utime_buffer; struct PermiteM *m, *m_next; if((*o)==stopper) @@ -2723,9 +2725,22 @@ int Permstack_pop(struct PermiteM **o, struct PermiteM *stopper, 0); } } - if(!(flag&1)) + if(!(flag&1)) { chown(m->disk_path, m->stbuf.st_uid, m->stbuf.st_gid); /* don't complain if it fails */ + if(!(flag&2)) { + utime_buffer.actime= m->stbuf.st_atime; + utime_buffer.modtime= m->stbuf.st_mtime;; + ret= utime(m->disk_path,&utime_buffer); + if(ret==-1 && xorriso!=NULL) { + sprintf(xorriso->info_text, + "Cannot change timestamps of disk directory: %s", + Text_shellsafe(m->disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", + 0); + } + } + } m_next= m->next; free(m->disk_path); free((char *) m); @@ -8711,7 +8726,10 @@ ex:; } -/* Option -cpx */ +/* Options -cpx , -cpax, -cp_rx , -cp_rax */ +/* @param flag bit0= recursive (-cp_rx, -cp_rax) + bit1= full property restore (-cpax, -cp_rax) +*/ int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv, int *idx, int flag) { @@ -8722,7 +8740,7 @@ int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv, char **optv= NULL; struct stat stbuf; - ret= Xorriso_cpmv_args(xorriso, "-cpx", argc, argv, idx, + ret= Xorriso_cpmv_args(xorriso, "-cp*x", argc, argv, idx, &optc, &optv, eff_dest, 1|4); if(ret<=0) goto ex; @@ -8738,7 +8756,7 @@ int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv, } if(xorriso->volset_change_pending) { sprintf(xorriso->info_text, - "-cpx: Image changes pending. May not copy from image to disk.\n"); + "-cp*x: Image changes pending. May not copy from image to disk.\n"); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } @@ -8754,7 +8772,7 @@ int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv, ret= Xorriso_iso_lstat(xorriso, eff_origin, &stbuf, 2|4); if(ret==-1) goto problem_handler; - if(S_ISDIR(stbuf.st_mode)) { + if(S_ISDIR(stbuf.st_mode) && !(flag&1)) { /* only allow directories if they actually represent split data files */ ret= 0; if(xorriso->do_concat_split) @@ -8782,7 +8800,7 @@ int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv, goto problem_handler; } } - ret= Xorriso_restore(xorriso, eff_origin, eff_dest, 16|64); + ret= Xorriso_restore(xorriso, eff_origin, eff_dest, 16 | (!(flag&2)<<6)); if(ret<=0 || xorriso->request_to_abort) goto problem_handler; if(ret==3 || (flag&1)) @@ -8804,7 +8822,7 @@ problem_handler:; xorriso->pacifier_total, "", 1); ret= !was_failure; ex:; - Xorriso_opt_args(xorriso, "-cpx", + Xorriso_opt_args(xorriso, "-cp*x", argc, argv, *idx, &end_idx_dummy, &optc, &optv, 256); return(ret); } @@ -9728,9 +9746,15 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag) " to create, overwrite, delete files in the disk filesystem.", " -cpx iso_rr_path [***] disk_path", " Copy leaf file objects from ISO image to disk filesystem.", +" -cpax iso_rr_path [***] disk_path", +" Like -cpx but trying to restore timestamps and ownership.", +" -cp_rx iso_rr_path [***] disk_path", +" Copy directory trees from ISO image to disk filesystem.", +" -cp_rax iso_rr_path [***] disk_path", +" Like -cp_rx but trying to restore timestamps and ownership.", "", "Compatibility emulation (argument list may be ended by --):", -" -as mkisofs [-help|-o|-R|-J|-V|-P|-f|-graft-points|-path-list|pathspecs]", +" -as mkisofs [-help|-o|-R|-J|-V|-P|-f|-m|-graft-points|-path-list|pathspecs]", " Perform some mkisofs gestures, understand pathspecs as mkisofs", " does. Commit happens outside emulation at usual occasions.", " -as cdrecord [-help|-v|dev=|speed=|blank=|fs=|-eject|-atip|padsize=|path|-]", @@ -11593,7 +11617,7 @@ int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv, static char argn_commands[][40]= { "add","as","chgrp","chgrpi","chgrp_r","chgrp_ri","chmod","chmodi", "chmod_r","chmod_ri","chown","chowni","chown_r","chown_ri", - "cpr","cpri","cpx", + "cpr","cpri","cp_rax","cp_rx","cpax","cpx", "du","dui","dus","dusi","dux","dusx","find","findi","findx", "ls","lsi","lsl","lsli","lsd","lsdi","lsdl","lsdli", "lsx","lslx","lsdx","lsdlx","mv","mvi","mkdir","mkdiri", @@ -11810,8 +11834,13 @@ next_command:; } else if(strcmp(cmd,"cpr")==0 || strcmp(cmd,"cpri")==0) { ret= Xorriso_option_cpri(xorriso, argc, argv, idx, 0); - } else if(strcmp(cmd,"cpx")==0) { - ret= Xorriso_option_cpx(xorriso, argc, argv, idx, 0); + } else if(strcmp(cmd,"cp_rx")==0 || strcmp(cmd,"cp_rax")==0) { + ret= Xorriso_option_cpx(xorriso, argc, argv, idx, + 1|((strcmp(cmd,"cp_rax")==0)<<1)); + + } else if(strcmp(cmd,"cpx")==0 || strcmp(cmd,"cpax")==0) { + ret= Xorriso_option_cpx(xorriso, argc, argv, idx, + (strcmp(cmd,"cpax")==0)<<1); } else if(strcmp(cmd,"cut_out")==0) { (*idx)+= 4; diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 84fd5c07..539b9f2c 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.06.02.141334" +#define Xorriso_timestamP "2008.06.05.165023" diff --git a/xorriso/xorrisoburn.c b/xorriso/xorrisoburn.c index 39e09fca..81bdf8b8 100644 --- a/xorriso/xorrisoburn.c +++ b/xorriso/xorrisoburn.c @@ -69,6 +69,11 @@ int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume, off_t offset, off_t cut_size, IsoNode **node, int flag); +int Xorriso_findi_iter(struct XorrisO *xorriso, IsoDir *dir_node, off_t *mem, + IsoDirIter **iter, + IsoNode ***node_array, int *node_count, int *node_idx, + IsoNode **iterated_node, int flag); + #define LIBISO_ISDIR(node) (iso_node_get_type(node) == LIBISO_DIR) #define LIBISO_ISREG(node) (iso_node_get_type(node) == LIBISO_FILE) @@ -2433,11 +2438,12 @@ unsupported_type:; /* @param flag bit0= minimal transfer: access permissions only bit1= keep directory open: keep owner, allow rwx for owner + and push directory onto xorriso->perm_stack */ int Xorriso_restore_properties(struct XorrisO *xorriso, char *disk_path, IsoNode *node, int flag) { - int ret; + int ret, is_dir= 0; mode_t mode; uid_t uid; gid_t gid; @@ -2455,9 +2461,22 @@ int Xorriso_restore_properties(struct XorrisO *xorriso, char *disk_path, } uid= stbuf.st_uid; + is_dir= S_ISDIR(stbuf.st_mode); mode= iso_node_get_permissions(node); - if(S_ISDIR(stbuf.st_mode) && (flag&2)) + if(is_dir && (flag&2)) { + ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1); + if(ret<=0) + return(0); + ret= Permstack_push(&(xorriso->perm_stack), disk_path, &stbuf, 0); + if(ret<=0) { + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + strcpy(xorriso->info_text, + "Cannot memorize permissions for disk directory"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); + return(-1); + } mode|= S_IRUSR|S_IWUSR|S_IXUSR; + } ret= chmod(disk_path, mode); if(ret==-1) { sprintf(xorriso->info_text, @@ -2531,17 +2550,7 @@ int Xorriso_restore_implicit_properties(struct XorrisO *xorriso, ret= Xorriso_fake_stbuf(xorriso, nfi, &stbuf, &node, 0); if(ret<=0) return(0); - if(flag&4) { - ret= Permstack_push(&(xorriso->perm_stack), nd, &stbuf, 0); - if(ret<=0) { - Xorriso_msgs_submit(xorriso, 0, nfd, 0, "ERRFILE", 0); - strcpy(xorriso->info_text, - "Cannot memorize permissions for disk directory"); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); - return(-1); - } - } - ret= Xorriso_restore_properties(xorriso, nd, node, !!(flag&2)); + ret= Xorriso_restore_properties(xorriso, nd, node, ((flag>>1)&3)); if(ret<=0) return(ret); sprintf(xorriso->info_text, @@ -2731,6 +2740,394 @@ ex:; } +/* Handle overwrite situation in disk filesystem. + @param flag + bit4= return 3 on rejection by exclusion or user +*/ +int Xorriso_restore_overwrite(struct XorrisO *xorriso, char *img_path, + char *path, char *nominal_path, + struct stat *stbuf, int flag) +{ + int ret; + char sfe[5*SfileadrL], sfe2[5*SfileadrL]; + + Xorriso_process_msg_queues(xorriso,0); + if(xorriso->do_overwrite==1 || + (xorriso->do_overwrite==2 && !S_ISDIR(stbuf->st_mode))) { + ret= Xorriso_rmx(xorriso, (off_t) 0, path, 1|8); + if(ret<=0) + return(ret); + if(ret==3) { + sprintf(xorriso->info_text, "User revoked restoring of (ISO) file: %s", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(3*!!(flag&16)); + } + return(1); + } + Xorriso_msgs_submit(xorriso, 0, nominal_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "While restoring %s : %s exists and may not be overwritten", + Text_shellsafe(nominal_path, sfe, 0), strcmp(nominal_path, path)==0 ? + "file object" : Text_shellsafe(path, sfe2, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); +} + + +/* + @param flag + bit1= do not report copied files + bit2= -follow, -not_*: this is not a command parameter + bit3= keep directory open: keep owner, allow rwx for owner + bit6= this is a copy action: do not fake times and ownership + @return <=0 = error , 1 = added leaf file object , 2 = added directory , +*/ +int Xorriso_restore_disk_object(struct XorrisO *xorriso, + char *img_path, IsoNode *node, + char *disk_path, + int flag) +{ + int ret, i, split_count= 0, partno, total_parts, leaf_is_split= 0; + off_t offset, bytes, total_bytes; + char *part_name, part_path[SfileadrL], *img_path_pt; + char sfe[5*SfileadrL], sfe2[5*SfileadrL]; + IsoImage *volume; + IsoNode *part_node, *first_part_node= NULL; + struct SplitparT *split_parts= NULL; + struct stat stbuf; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + goto ex; + + if(LIBISO_ISDIR(node) && xorriso->do_concat_split) + leaf_is_split= Xorriso_identify_split(xorriso, img_path, node, + &split_parts, &split_count, &stbuf, 1|2); + if(leaf_is_split) { + /* map all files in directory img_path into regular file disk_path */ + + for(i=0 ; itotal_bytes) + bytes= total_bytes-offset; + ret= Xorriso_tree_restore_node(xorriso, part_node, part_path, disk_path, + offset, bytes, + (!!(flag&64)) | 2 | (flag&4) | 8); + if(ret<=0) + goto restoring_failed; + } + if(first_part_node!=NULL) + Xorriso_restore_properties(xorriso, disk_path, first_part_node, + !!(flag&64)); + goto went_well; + } + +#ifdef Osirrox_not_yeT + + if(resolve_link) { + ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0); + if(ret<=0) + goto ex; + disk_path_pt= resolved_disk_path; + } else + +#endif /* Osirrox_not_yeT */ + + img_path_pt= img_path; + + ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, disk_path, + (off_t) 0, (off_t) 0, + (flag&(4|8)) | !!(flag&64)); + if(ret>0 && (flag&8)) + ret= Xorriso_restore_properties(xorriso, disk_path, node, 2 | !!(flag&64)); + if(ret<=0) { +restoring_failed:; + sprintf(xorriso->info_text, "Restoring 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); + {ret= 0; goto ex;} + } + if(ret==2) + {ret= 3; goto ex;} +went_well:; + xorriso->pacifier_count++; + if(xorriso->pacifier_count%100 && !(flag&2)) + Xorriso_pacifier_callback(xorriso, "files restored", + xorriso->pacifier_count, + xorriso->pacifier_total, "", 0); + ret= 1; +ex:; + if(split_parts!=NULL) + Splitparts_destroy(&split_parts, split_count, 0); + return(ret); +} + + +/* @param flag bit0= recursion is active + bit1= do not report restored files + bit6= this is a copy action: do not fake times and ownership +*/ +int Xorriso_restore_tree(struct XorrisO *xorriso, IsoDir *dir, + char *img_dir_path, char *disk_dir_path, + off_t boss_mem, + struct LinkiteM *link_stack, int flag) +{ + IsoImage *volume; + IsoNode *node; + 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 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; + + perm_stack_mem= xorriso->perm_stack; + + /* Avoiding large local memory objects in order to save stack space */ + sfe= malloc(5*SfileadrL); + sfe2= malloc(5*SfileadrL); + disk_path= malloc(2*SfileadrL); + img_path= malloc(2*SfileadrL); + link_target= malloc(SfileadrL); + if(sfe==NULL || sfe2==NULL || disk_path==NULL || img_path==NULL || + link_target==NULL) { + Xorriso_no_malloc_memory(xorriso, &sfe, 0); + {ret= -1; goto ex;} + } + + own_link_stack= link_stack; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + goto ex; + + stbuf_src= img_dir_path; + node= (IsoNode *) dir; + ret= Xorriso_fake_stbuf(xorriso, stbuf_src, &stbuf, &node, 1); + if(ret<=0) { + Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text,"Cannot open as (ISO) source directory: %s", + Text_shellsafe(img_dir_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + +#ifdef Osirrox_not_yeT + + dev_t dir_dev; + dir_dev= stbuf.st_dev; + + if(S_ISLNK(stbuf.st_mode)) { + if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1)))) + {ret= 2; goto ex;} + stbuf_src= disk_dir_path; + if(stat(disk_dir_path, &stbuf)==-1) + goto cannot_open_dir; + if(dir_dev != stbuf.st_dev && + !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1)))) + {ret= 2; goto ex;} + } + +#endif /* Osirrox_not_yeT */ + + if(!S_ISDIR(stbuf.st_mode)) { + Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text,"Is not a directory in ISO image: %s", + Text_shellsafe(img_dir_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + + mem= boss_mem; + ret= Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count, + &node_idx, &node, 1|4); + if(ret<=0) + goto ex; + + if(Sfile_str(img_path, img_dir_path,0)<=0) { +much_too_long:; + Xorriso_much_too_long(xorriso, SfileadrL, 2); + {ret= 0; goto ex;} + } + if(img_path[0]==0 || img_path[strlen(img_path)-1]!='/') + strcat(img_path,"/"); + name= img_path+strlen(img_path); + if(Sfile_str(disk_path, disk_dir_path, 0)<=0) + goto much_too_long; + if(disk_path[0] || disk_path[strlen(disk_path)-1]!='/') + strcat(disk_path,"/"); + disk_name= disk_path+strlen(disk_path); + + len_dp= strlen(disk_path); + len_ip= strlen(img_path); + + while(1) { /* loop over ISO directory content */ + stbuf_src= ""; + +#ifdef Osirrox_not_yeT + + Linkitem_reset_stack(&own_link_stack, link_stack, 0); + +#endif + + srcpt= img_path; + Xorriso_process_msg_queues(xorriso,0); + ret= Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count, + &node_idx, &node, 0); + if(ret<0) + goto ex; + if(ret==0 || xorriso->request_to_abort) + break; + leaf_name= (char *) iso_node_get_name(node); + if(Xorriso_much_too_long(xorriso, len_dp + strlen(leaf_name)+1, 0)<=0) + {ret= 0; goto was_problem;} + if(Xorriso_much_too_long(xorriso, len_ip + strlen(leaf_name)+1, 0)<=0) + {ret= 0; goto was_problem;} + /* name is a pointer into img_path */ + strcpy(name, leaf_name); + strcpy(disk_name, leaf_name); + + stbuf_src= srcpt; + ret= Xorriso_fake_stbuf(xorriso, img_path, &stbuf, &node, 1); + if(ret<=0) + goto was_problem; + source_is_dir= 0; + source_is_link= S_ISLNK(stbuf.st_mode); + +#ifdef Osirrox_not_yeT + + if(xorriso->do_follow_links && source_is_link) { + /* Xorriso_hop_link checks for wide link loops */ + ret= Xorriso_hop_link(xorriso, srcpt, &own_link_stack, &hstbuf, 0); + if(ret<0) + goto was_problem; + if(ret==1) { + ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 0); + if(ret<=0) + goto was_problem; + srcpt= link_target; + stbuf_src= srcpt; + if(lstat(srcpt, &stbuf)==-1) + goto cannot_lstat; + } else { + if(Xorriso_eval_problem_status(xorriso, 0, 1|2)<0) + {ret= 0; goto was_problem;} + } + } else if (S_ISLNK(stbuf.st_mode)) { + ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1); + if(ret<=0) + goto was_problem; + } + +#endif /* Osirrox_not_yeT */ + + do_not_dive= 0; + if(S_ISDIR(stbuf.st_mode)) + source_is_dir= 1; + source_is_split= 0; + if(source_is_dir) + source_is_split= Xorriso_is_split(xorriso, img_path, node, 1|2); + if(source_is_split) + do_not_dive= 1; + + /* does a disk file exist with this name ? */ + stbuf_ret= lstat(disk_path, &target_stbuf); + if(stbuf_ret!=-1) { + target_is_dir= S_ISDIR(target_stbuf.st_mode); + if(!(target_is_dir && (source_is_dir && !source_is_split))) { + Xorriso_process_msg_queues(xorriso,0); + ret= Xorriso_restore_overwrite(xorriso, img_path, disk_path, disk_path, + &target_stbuf, 0); + if(ret<=0) + goto was_problem; + stbuf_ret= -1; + } + } + + if(stbuf_ret!=-1) { /* (Can only happen with directory) */ + + /* ??? >>> eventually open access to existing directory ? */; + + } else { + hflag= 4 | (flag & (2|64)); + if(source_is_dir && !do_not_dive) + hflag|= 8; /* keep directory open for user */ + ret= Xorriso_restore_disk_object(xorriso, img_path, node, disk_path, + hflag); + if(ret<=0) + goto was_problem; + } + if(source_is_dir && !do_not_dive) { + ret= Xorriso_restore_tree(xorriso, (IsoDir *) node, + img_path, disk_path, mem, + own_link_stack, 1|(flag&2)); + /* eventually restore exact access permissions of directory */ + hret= Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, + !!(flag&64)); + if(hret<=0 && hretperm_stack), perm_stack_mem, xorriso, !!(flag&64)); + } + + ret= 1; +ex: + Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, !!(flag&64)); + if(sfe!=NULL) + free(sfe); + if(sfe2!=NULL) + free(sfe2); + if(disk_path!=NULL) + free(disk_path); + if(img_path!=NULL) + free(img_path); + if(link_target!=NULL) + free(link_target); + Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count, + &node_idx, &node, (1<<31)); + + Xorriso_process_msg_queues(xorriso,0); + +#ifdef Osirrox_not_yeT + + Linkitem_reset_stack(&own_link_stack, link_stack, 0); + +#endif + + if(ret<=0) + return(ret); + return(!was_failure); +} + + /* @param flag >>> bit0= mkdir: graft in as empty directory, not as copy from iso @@ -2747,15 +3144,12 @@ int Xorriso_restore(struct XorrisO *xorriso, char *img_path, char *disk_path, int flag) { IsoImage *volume; - char path[SfileadrL], *apt, *npt, sfe[5*SfileadrL], sfe2[5*SfileadrL]; - char *img_path_pt, *part_name; - IsoNode *node= NULL, *part_node, *first_part_node= NULL; + 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 leaf_is_split= 0, source_is_split= 0, split_count, partno, total_parts, i; - off_t offset, bytes, total_bytes; + int leaf_is_split= 0, source_is_split= 0; struct stat stbuf, target_stbuf; struct PermiteM *perm_stack_mem; - struct SplitparT *split_parts= NULL; perm_stack_mem= xorriso->perm_stack; @@ -2802,8 +3196,7 @@ int Xorriso_restore(struct XorrisO *xorriso, ret= 0; goto ex; } if(is_dir && xorriso->do_concat_split) - leaf_is_split= Xorriso_identify_split(xorriso, img_path, node, - &split_parts, &split_count, &stbuf, 1|2); + leaf_is_split= Xorriso_is_split(xorriso, img_path, node, 1|2); } for(npt= apt; !done; apt= npt+1) { npt= strchr(apt, '/'); @@ -2825,32 +3218,13 @@ int Xorriso_restore(struct XorrisO *xorriso, if(stbuf_ret!=-1) { target_is_dir= S_ISDIR(target_stbuf.st_mode); if(!(target_is_dir && (source_is_dir && !source_is_split))) { - Xorriso_process_msg_queues(xorriso,0); - /* handle overwrite situation */ - if(xorriso->do_overwrite==1 || - (xorriso->do_overwrite==2 && !target_is_dir)) { - ret= Xorriso_rmx(xorriso, (off_t) 0, path, 1|8); - if(ret<=0) - goto ex; - if(ret==3) { - sprintf(xorriso->info_text, "User revoked restoring of: %s", - Text_shellsafe(disk_path, sfe, 0)); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); - {ret= 3*!!(flag&16); goto ex;} - } - stbuf_ret= -1; - goto handle_path_node; - } - Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); - sprintf(xorriso->info_text, - "While restoring '%s' : '%s' exists and may not be overwritten", - disk_path, path); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); - {ret= 0; goto ex;} + ret= Xorriso_restore_overwrite(xorriso, img_path, path, disk_path, + &target_stbuf, flag&16); + if(ret<=0 || ret==3) + goto ex; + stbuf_ret= -1; /* now it is removed */ } } - -handle_path_node:; if(stbuf_ret==-1 && (source_is_dir && !source_is_split)) { /* make a directory */ ret= mkdir(path, 0777); @@ -2881,81 +3255,20 @@ attach_source:; /* directory was created above */; } else if(is_dir && !source_is_split) { - Xorriso_restore_properties(xorriso, disk_path, node, !!(flag&64)); - -#ifdef Osirrox_not_yeT - - /* >>> */ - + Xorriso_restore_properties(xorriso, disk_path, node, 2 | !!(flag&64)); if(!(flag&32)) { - ret= Xorriso_add_tree(xorriso, dir, img_path, path, NULL, - flag&2); + ret= Xorriso_restore_tree(xorriso, (IsoDir *) node, img_path, path, + (off_t) 0, NULL, flag&(2|64)); if(ret<=0) goto ex; + if(!(flag&64)) /* set timestamps which Permstack_pop() will not set */ + Xorriso_restore_properties(xorriso, disk_path, node, 2); } -#endif - } else { - if(source_is_split) { - /* map all files in directory img_path into regular file disk_path */ - - for(i=0 ; itotal_bytes) - bytes= total_bytes-offset; - ret= Xorriso_tree_restore_node(xorriso, part_node, sfe2, path, - offset, bytes, - (!!(flag&64)) | 2 | (flag&4) | 8); - if(ret<=0) - goto restoring_failed; - } - if(first_part_node!=NULL) - Xorriso_restore_properties(xorriso, path, first_part_node, - !!(flag&64)); - break; - -#ifdef Osirrox_not_yeT - - } else if(resolve_link) { - ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0); - if(ret<=0) - goto ex; - disk_path_pt= resolved_disk_path; - -#endif /* Osirrox_not_yeT */ - - } else - img_path_pt= img_path; - - ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, path, - (off_t) 0, (off_t) 0, - (flag&4) | !!(flag&64)); - if(ret<=0) { -restoring_failed:; - sprintf(xorriso->info_text, "Restoring 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); - {ret= 0; goto ex;} - } - if(ret==2) - {ret= 3; goto ex;} - xorriso->pacifier_count++; - if(xorriso->pacifier_count%100 && !(flag&2)) - Xorriso_pacifier_callback(xorriso, "files restored", - xorriso->pacifier_count, - xorriso->pacifier_total, "", 0); + ret= Xorriso_restore_disk_object(xorriso, img_path, node, path, + flag & (2|4|64)); + if(ret<=0) + goto ex; } } else *npt= '/'; @@ -2965,11 +3278,9 @@ restoring_failed:; ex:; /* restore exact access permissions of stacked paths */ hret= Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, - !!(flag&64)); + 2 | !!(flag&64)); if(hret<=0 && hret0);