From 53f462b406f1c5ebe949034ffdedd837e7290684 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Thu, 22 May 2008 19:25:59 +0000 Subject: [PATCH] First experiments of osirrox ISO-to-disk copying --- xorriso/xorriso.c | 380 +++++++++++++++++++++-- xorriso/xorriso.h | 3 + xorriso/xorriso_private.h | 44 +++ xorriso/xorriso_timestamp.h | 2 +- xorriso/xorrisoburn.c | 596 ++++++++++++++++++++++++++++++------ xorriso/xorrisoburn.h | 15 + 6 files changed, 935 insertions(+), 105 deletions(-) diff --git a/xorriso/xorriso.c b/xorriso/xorriso.c index 886a8e10..2de2af69 100644 --- a/xorriso/xorriso.c +++ b/xorriso/xorriso.c @@ -2652,6 +2652,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) { int i, ret; struct XorrisO *m; + char leafname[SfileadrL]; *xorriso= m= TSOB_FELD(struct XorrisO,1); if(m==NULL) @@ -2715,6 +2716,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->keep_boot_image= 0; m->patch_isolinux_image= 0; m->allow_graft_points= 0; + m->allow_restore= 0; m->dialog= 0; m->search_mode= 0; m->structured_search= 1; @@ -2777,6 +2779,11 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->result_open_line_len= 0; m->info_text[0]= 0; + ret= Sfile_leafname(progname, leafname, 0); + if(ret<=0) + goto failure; + if(strcmp(leafname, "osirrox")==0) + m->allow_restore= 1; ret= Exclusions_new(&(m->disk_exclusions), 0); if(ret<=0) goto failure; @@ -3816,6 +3823,11 @@ int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag) Xorriso_status_result(xorriso,filter,fp,flag&2); } + is_default= !(xorriso->allow_restore); + sprintf(line,"-osirrox %s\n", xorriso->allow_restore ? "on" : "off"); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + is_default= (xorriso->keep_boot_image==0 && xorriso->patch_isolinux_image==0); form= "any"; treatment= "discard"; @@ -5100,7 +5112,7 @@ int Xorriso_end_idx(struct XorrisO *xorriso, bit3= do not expand last argument bit4= ignore last argument bit5= demand exactly one match - bit6= with bit allow 0 matches if pattern is a constant + bit6= with bit5 allow 0 matches if pattern is a constant bit8= free the eventually allocated sub_vector */ int Xorriso_opt_args(struct XorrisO *xorriso, char *cmd, @@ -6213,6 +6225,210 @@ int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd, } +/* + @param flag >>> bit0= remove whole sub tree: rm -r + bit1= remove empty directory: rmdir + bit2= recursion: do not reassure in mode 2 "tree" + bit3= this is for overwriting and not for plain removal + bit4= count deleted files in xorriso->pacifier_count + bit5= with bit0 only remove directory content, not the directory + @return <=0 = error + 1 = removed leaf file object + 2 = removed directory or tree + 3 = did not remove on user revocation +*/ +int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag) +{ + int ret, is_dir= 0; + struct stat victim_stbuf, *victim_node= NULL; + struct DirseQ *dirseq= NULL; + char *sfe= NULL, *sub_path= NULL; + + /* Avoiding large local memory objects in order to save stack space */ + sfe= malloc(5*SfileadrL); + sub_path= malloc(2*SfileadrL); + if(sfe==NULL || sub_path==NULL) { + Xorriso_no_malloc_memory(xorriso, &sfe, 0); + {ret= -1; goto ex;} + } + + if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0) + {ret= 0; goto ex;} + + ret= lstat(path, &victim_stbuf); + if(ret==-1) { + sprintf(xorriso->info_text, "Cannot lstat(%s)", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + {ret= 0; goto ex;} + } + if(strcmp(path, "/")==0) { + sprintf(xorriso->info_text, "May not delete root directory"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + victim_node= &victim_stbuf; + if(S_ISDIR(victim_stbuf.st_mode)) + is_dir= 1; + if(!is_dir) { + if(flag&2) { /* rmdir */ + sprintf(xorriso->info_text, "%s in disk filesystem is not a directory", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } else { + if(flag&1) { /* rm -r */ + +#ifdef Osirrox_not_yeT + /* >>> */ + + if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) || + (flag&32)) { + /* Iterate over subordinates and delete them */ + mem= boss_mem; + + ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, + &iter, &node_array, &node_count, &node_idx, + &node, 1|2); + if(ret<=0) { +cannot_create_iter:; + Xorriso_cannot_create_iter(xorriso, ret, 0); + ret= -1; goto ex; + } + pl= strlen(path); + strcpy(sub_path, path); + if(pl==0 || sub_path[pl-1]!='/') { + sub_path[pl++]= '/'; + sub_path[pl]= 0; + } + sub_name= sub_path+pl; + while(1) { + ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter, + &node_array, &node_count, &node_idx, &node, 0); + if(ret<0) + goto ex; + if(ret==0 || xorriso->request_to_abort) + break; + name= (char *) iso_node_get_name(node); + if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0) + {ret= 0; goto rm_r_problem_handler;} + strcpy(sub_name, name); + ret= Xorriso_rmi(xorriso, iter, mem, sub_path, (flag&(1|2|8|16))|4); + if(ret==3 || ret<=0 || xorriso->request_to_abort) { +rm_r_problem_handler:; + not_removed= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret<0) + goto dir_not_removed; + } + } + if(flag&32) + {ret= 2; goto ex;} + + if(not_removed) { +dir_not_removed:; + sprintf(xorriso->info_text, "Directory not removed: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + if(ret>0) + ret= 3; + goto ex; + } + } + +#else /* Osirrox_not_yeT */ + + sprintf(xorriso->info_text, "-rm_rx is not implemented yet"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + +#endif /* !Osirrox_not_yeT */ + + } else { + if(!(flag&2)) { /* not rmdir */ + sprintf(xorriso->info_text, "%s in disk filesystem is a directory", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + ret= Dirseq_new(&dirseq, path, 1); + if(ret>0) { + ret= Dirseq_next_adr(dirseq, sfe, 0); + if(ret>0) { + sprintf(xorriso->info_text, + "Directory not empty on attempt to delete: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } + } + } + if(xorriso->request_to_abort) + {ret= 3; goto ex;} + + while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4))) + && !xorriso->request_not_to_ask) { + /* ls -ld */ + Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 1|2|8); + if(is_dir) /* du -s */ + Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 2|4); + if(flag&8) + sprintf(xorriso->info_text, + "File exists. Remove ? n= keep old, y= remove, x= abort, @= stop asking\n"); + else + sprintf(xorriso->info_text, + "Remove above file ? n= keep it, y= remove it, x= abort, @= stop asking\n"); + Xorriso_info(xorriso, 4); + ret= Xorriso_request_confirmation(xorriso, 1|2|4|16); + if(ret<=0) + goto ex; + if(xorriso->request_to_abort) { + sprintf(xorriso->info_text, + "Removal operation aborted by user before file: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= 3; goto ex; + } + if(ret==3) + continue; + if(ret==6) /* yes */ + break; + if(ret==4) { /* yes, do not ask again */ + xorriso->request_not_to_ask= 1; + break; + } + if(ret==1) { /* no */ + sprintf(xorriso->info_text, "Kept in existing state: %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + ret= 3; goto ex; + } + } + if(is_dir) + ret= rmdir(path); + else + ret= unlink(path); + if(ret==-1) { + sprintf(xorriso->info_text, "Cannot delete from disk filesystem %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= -1; goto ex; + } + if(flag&16) + xorriso->pacifier_count++; + ret= 1+!!is_dir; +ex:; + if(sfe!=NULL) + free(sfe); + if(sub_path!=NULL) + free(sub_path); + Dirseq_destroy(&dirseq, 0); + return(ret); +} + + /* @param flag bit0= recursion */ int Xorriso_findx_action(struct XorrisO *xorriso, struct FindjoB *job, @@ -6486,7 +6702,8 @@ ex:; /* @param flag bit0= a non-existing target of multiple sources is a directory bit1= all paths except the last one are disk_paths - @return <=0 iis error, 1= leaf file object, 2= directory + bit2= the last path is a disk_path + @return <=0 is error, 1= leaf file object, 2= directory */ int Xorriso_cpmv_args(struct XorrisO *xorriso, char *cmd, int argc, char **argv, int *idx, @@ -6511,12 +6728,17 @@ int Xorriso_cpmv_args(struct XorrisO *xorriso, char *cmd, goto ex; /* demand one match, or 0 with a constant */ ret= Xorriso_opt_args(xorriso, cmd, argc, argv, end_idx, &end_idx, &destc, - &destv, 32|64); + &destv, ((flag&4)>>1) | 32 | 64); if(ret<=0) goto ex; /* Evaluate target address */ - ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, destv[0], eff_dest, 1); + if(flag&4) + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, destv[0], eff_dest, + 2|4|16); + else + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, destv[0], eff_dest, + 1); if(ret<0) {ret= 0; goto ex;} if(ret==2 || ((flag&1) && *optc > 1 && ret==0)) { @@ -6531,7 +6753,8 @@ int Xorriso_cpmv_args(struct XorrisO *xorriso, char *cmd, {ret= 0; goto ex;} } if(ret==0) { /* compute complete eff_dest */ - ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, destv[0],eff_dest,2); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, destv[0], eff_dest, + 2 | (flag&4)); if(ret<0) {ret= 0; goto ex;} } @@ -8334,8 +8557,8 @@ int Xorriso_option_cpri(struct XorrisO *xorriso, int argc, char **argv, strcpy(eff_dest, dest_dir); ret= Sfile_add_to_path(eff_dest, leafname, 0); if(ret<=0) { - printf(xorriso->info_text, "Effective path gets much too long (%d)", - strlen(eff_dest)+strlen(leafname)+1); + sprintf(xorriso->info_text, "Effective path gets much too long (%d)", + (int) (strlen(eff_dest)+ strlen(leafname)+1)); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); goto problem_handler; } @@ -8366,6 +8589,96 @@ ex:; } +/* Option -cpx */ +int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag) +{ + int i, ret, is_dir= 0, was_failure= 0, fret, end_idx_dummy; + char eff_origin[SfileadrL], eff_dest[SfileadrL]; + char dest_dir[SfileadrL], leafname[SfileadrL], sfe[5*SfileadrL]; + int optc= 0; + char **optv= NULL; + struct stat stbuf; + + if(!xorriso->allow_restore) { + sprintf(xorriso->info_text, + "-cpx: image-to-disk copies are not enabled by option -osirrox"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + if(xorriso->volset_change_pending) { + sprintf(xorriso->info_text, + "-cpx: 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; + } + ret= Xorriso_cpmv_args(xorriso, "-cpx", argc, argv, idx, + &optc, &optv, eff_dest, 1|4); + if(ret<=0) + goto ex; + if(ret==2) { + is_dir= 1; + strcpy(dest_dir, eff_dest); + } + + /* Perform copying */ + Xorriso_pacifier_reset(xorriso, 0); + for(i= 0; irequest_to_abort; i++) { + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, optv[i], eff_origin, + 2); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + + ret= Xorriso_iso_lstat(xorriso, eff_origin, &stbuf, 2); + if(ret==-1) + goto problem_handler; + if(S_ISDIR(stbuf.st_mode)) { + sprintf(xorriso->info_text, "-cpx: May not copy directory %s", + Text_shellsafe(eff_origin, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto problem_handler; + } + + if(is_dir) { + ret= Sfile_leafname(eff_origin, leafname, 0); + if(ret<=0) + goto problem_handler; + strcpy(eff_dest, dest_dir); + ret= Sfile_add_to_path(eff_dest, leafname, 0); + if(ret<=0) { + sprintf(xorriso->info_text, "Effective path gets much too long (%d)", + (int) (strlen(eff_dest)+strlen(leafname)+1i)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + goto problem_handler; + } + } + ret= Xorriso_restore(xorriso, eff_origin, eff_dest, 16|64); + if(ret<=0 || xorriso->request_to_abort) + goto problem_handler; + if(ret==3 || (flag&1)) + continue; + sprintf(xorriso->info_text, + "Copied from ISO image to disk: %s '%s'='%s'\n", + (ret>1 ? "directory" : "file"), eff_origin, eff_dest); + Xorriso_info(xorriso, 0); + continue; /* regular bottom of loop */ +problem_handler:; + was_failure= 1; + fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); + if(fret>=0) + continue; + goto ex; + } + Xorriso_pacifier_callback(xorriso, "files copied", xorriso->pacifier_count, + xorriso->pacifier_total, "", 1); + ret= !was_failure; +ex:; + Xorriso_opt_args(xorriso, "-cpx", + argc, argv, *idx, &end_idx_dummy, &optc, &optv, 256); + return(ret); +} + + /* SPLIT : proposed target format part_{partno}_of_{total_parts}_at_{offset}_with_{bytes}_of_{total_bytes} */ @@ -9827,8 +10140,8 @@ int Xorriso_option_mvi(struct XorrisO *xorriso, int argc, char **argv, strcpy(eff_dest, dest_dir); ret= Sfile_add_to_path(eff_dest, leafname, 0); if(ret<=0) { - printf(xorriso->info_text, "Effective path gets much too long (%d)", - strlen(eff_dest)+strlen(leafname)+1); + sprintf(xorriso->info_text, "Effective path gets much too long (%d)", + (int) (strlen(eff_dest)+strlen(leafname)+1)); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); goto problem_handler; } @@ -10147,6 +10460,26 @@ ex:; } +/* Option -osirrox "on"|"off" */ +int Xorriso_option_osirrox(struct XorrisO *xorriso, char *mode, int flag) +{ + if(strcmp(mode, "off")==0) + xorriso->allow_restore= 0; + else if(strcmp(mode, "on")==0 || mode[0]==0) + xorriso->allow_restore= 1; + else { + sprintf(xorriso->info_text, "-osirrox: unknown mode '%s'", mode); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + sprintf(xorriso->info_text, + "%s copying of file objects from ISO image to disk filesystem\n", + xorriso->allow_restore ? "Enabled" : "Disabled"); + Xorriso_info(xorriso, 0); + return(1); +} + + /* Option -overwrite "on"|"nondir"|"off" */ int Xorriso_option_overwrite(struct XorrisO *xorriso, char *mode, int flag) { @@ -11060,17 +11393,19 @@ int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv, static char arg0_commands[][40]= { "ban_stdio_write","commit","commit_eject","devices","end","help", "list_formats","no_rc","print_size","pwd","pwdi","pwdx", - "rollback","rollback_end","tell_media_space","toc","version","--","" + "rollback","rollback_end","tell_media_space","toc","version","--", + "" }; static char arg1_commands[][40]= { "abort_on","add_plainly","blank","cd","cdi","cdx","close","dev", "dummy","dialog","disk_pattern","eject","iso_rr_pattern","follow", "format","fs","gid","history","indev","joliet","mark","not_leaf", - "not_list","not_mgt","options_from_file","overwrite","outdev", + "not_list","not_mgt","options_from_file","osirrox","outdev","overwrite", "padding","path_list","pathspecs","pkt_output","print","prompt", "prog","publisher","reassure","report_about","rom_toc_scan", "session_log","speed","split_size","status","status_history_max", - "temp_mem_limit","uid","volid","use_readline","" + "temp_mem_limit","uid","volid","use_readline", + "" }; static char arg2_commands[][40]= { "alter_date","alter_date_r","boot_image","compare","compare_r", @@ -11079,12 +11414,14 @@ int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv, "" }; static char arg4_commands[][40]= { - "cut_out","" + "cut_out", + "" }; 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","du","dui","dus","dusi","dux","dusx","find","findi","findx", + "cpr","cpri","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", "not_paths","rm","rmi","rm_r","rm_ri","rmdir","rmdiri", @@ -11300,6 +11637,9 @@ 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,"cut_out")==0) { (*idx)+= 4; if((*idx)>argc) { @@ -11466,14 +11806,18 @@ next_command:; if(ret==3) goto ex; - } else if(strcmp(cmd,"overwrite")==0) { - (*idx)++; - ret= Xorriso_option_overwrite(xorriso,arg1,0); - } else if(strcmp(cmd,"outdev")==0) { (*idx)++; ret= Xorriso_option_dev(xorriso, arg1, 2); + } else if(strcmp(cmd,"osirrox")==0) { + (*idx)++; + ret= Xorriso_option_osirrox(xorriso,arg1,0); + + } else if(strcmp(cmd,"overwrite")==0) { + (*idx)++; + ret= Xorriso_option_overwrite(xorriso,arg1,0); + } else if(strcmp(cmd,"padding")==0) { (*idx)++; ret= Xorriso_option_padding(xorriso, arg1, 0); diff --git a/xorriso/xorriso.h b/xorriso/xorriso.h index cc9d6b1a..feaa5463 100644 --- a/xorriso/xorriso.h +++ b/xorriso/xorriso.h @@ -372,6 +372,9 @@ int Xorriso_option_not_paths(struct XorrisO *xorriso, int argc, char **argv, int Xorriso_option_options_from_file(struct XorrisO *xorriso, char *adr, int flag); +/* Option -osirrox "on"|"off" */ +int Xorriso_option_osirrox(struct XorrisO *xorriso, char *mode, int flag); + /* Option -overwrite "on"|"nondir"|"off" */ int Xorriso_option_overwrite(struct XorrisO *xorriso, char *mode, int flag); diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index 22cf8f7a..267c4f7e 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -158,6 +158,8 @@ struct XorrisO { /* the global context of xorriso */ /* XORRISO options */ int allow_graft_points; + int allow_restore; + int dialog; @@ -386,6 +388,28 @@ int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter, int Xorriso_path_is_excluded(struct XorrisO *xorriso, char *path, int flag); +/* @param flag bit0= long format + bit1= do not print count of nodes + bit2= du format + bit3= print directories as themselves (ls -d) +*/ +int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd, + int filec, char **filev, off_t boss_mem, int flag); + +/* + @param flag >>> bit0= remove whole sub tree: rm -r + bit1= remove empty directory: rmdir + bit2= recursion: do not reassure in mode 2 "tree" + bit3= this is for overwriting and not for plain removal + bit4= count deleted files in xorriso->pacifier_count + bit5= with bit0 only remove directory content, not the directory + @return <=0 = error + 1 = removed leaf file object + 2 = removed directory or tree + 3 = did not remove on user revocation +*/ +int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag); + int Sfile_str(char target[SfileadrL], char *source, int flag); @@ -403,6 +427,26 @@ int Sfile_destroy_argv(int *argc, char ***argv, int flag); */ int Sfile_count_components(char *path, int flag); +/* + @param flag + bit0= return -1 if file is missing + bit1= return a hardlink with siblings as type 5 + bit2= evaluate eventual link target rather than the link object itself + bit3= return a socket or a char device as types 7 or 8 rather than 0 + @return + 0=unknown + 1=regular + 2=directory + 3=symbolic link + 4=named pipe + 5=multiple hardlink (with bit1) + 6=block device + 7=socket (with bit3) + 8=character device (with bit3) +*/ +int Sfile_type(char *filename, int flag); + + char *Text_shellsafe(char *in_text, char *out_text, int flag); diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 5c13e68d..52004233 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.05.20.075142" +#define Xorriso_timestamP "2008.05.22.192618" diff --git a/xorriso/xorrisoburn.c b/xorriso/xorrisoburn.c index 059ba7b3..8e8679b1 100644 --- a/xorriso/xorrisoburn.c +++ b/xorriso/xorrisoburn.c @@ -19,6 +19,7 @@ #include #include #include +#include @@ -1330,6 +1331,9 @@ int Xorriso_node_from_path(struct XorrisO *xorriso, IsoImage *volume, bit1= work purely literally, do not use libisofs bit2= (with bit1) this is an address in the disk world bit3= return root directory as "/" and not as "" + bit4= (with bit2) determine type of disk file eff_path + and return 0 if not existing + bit5= (with bit3) this is not a parameter @return -1 = faulty path format, 0 = not found , 1 = found simple node , 2 = found directory */ @@ -1434,6 +1438,15 @@ much_too_long:; is_dir= LIBISO_ISDIR(node); } } + if(flag&16) { + ret= Sfile_type(eff_path, + 1|(4*(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&32))) + )); + if(ret<0) + return(0); + if(ret==2) + is_dir= 1; + } return(1+!!is_dir); } @@ -1461,6 +1474,99 @@ int Xorriso_get_node_by_path(struct XorrisO *xorriso, } +/* @param flag bit0= *node is already valid + bit1= add extra block for size estimation +*/ +int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf, + IsoNode **node, int flag) +{ + int ret; + IsoImage *volume; + + memset((char *) stbuf, 0, sizeof(struct stat)); + if(!(flag&1)) { + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(-1); + ret= Xorriso_node_from_path(xorriso, volume, path, node, 1); + if(ret<=0) + *node= NULL; + } + if(*node==NULL) + return(0); + + /* >>> stbuf->st_dev */ + /* >>> stbuf->st_ino */ + + stbuf->st_mode= iso_node_get_permissions(*node) & 07777; + if(LIBISO_ISDIR(*node)) + stbuf->st_mode|= S_IFDIR; + else if(LIBISO_ISREG(*node)) + stbuf->st_mode|= S_IFREG; + else if(LIBISO_ISLNK(*node)) + stbuf->st_mode|= S_IFLNK; + else if(LIBISO_ISCHR(*node)) + stbuf->st_mode|= S_IFCHR; + else if(LIBISO_ISBLK(*node)) + stbuf->st_mode|= S_IFBLK; + else if(LIBISO_ISFIFO(*node)) + stbuf->st_mode|= S_IFIFO; + else if(LIBISO_ISSOCK(*node)) + stbuf->st_mode|= S_IFSOCK; + + /* >>> NG How to represent LIBISO_BOOT ? */ + + + /* >>> With directories this should be : number of subdirs + 2 */ + /* >>> ??? How to obtain RR hardlink number for other types ? */ + stbuf->st_nlink= 1; + + stbuf->st_uid= iso_node_get_uid(*node); + stbuf->st_gid= iso_node_get_gid(*node); + + /* >>> stbuf->st_rdev */ + + if(LIBISO_ISREG(*node)) + stbuf->st_size= iso_file_get_size((IsoFile *) *node)+ (2048 * !!(flag&2)); + else + stbuf->st_size= 0; + + stbuf->st_blksize= 2048; + stbuf->st_blocks= stbuf->st_size / (off_t) 2048; + if(stbuf->st_blocks * (off_t) 2048 != stbuf->st_size) + stbuf->st_blocks++; + + stbuf->st_atime= iso_node_get_atime(*node); + stbuf->st_mtime= iso_node_get_mtime(*node); + stbuf->st_ctime= iso_node_get_ctime(*node); + return(1); +} + + +/* @param flag >>> bit0= follow links (i.e. stat() rather than lstat() + bit1= do not return -2 on sever errors +*/ +int Xorriso_iso_lstat(struct XorrisO *xorriso, char *path, struct stat *stbuf, + int flag) +{ + int ret; + IsoNode *node; + + if(flag&1) { + + /* >>> follow link in ISO image */; + + } + + ret= Xorriso_fake_stbuf(xorriso, path, stbuf, &node, 0); + if(ret>0) + return(0); + if(ret<0) + return(-2); + return(-1); +} + + /* @param flag bit0= give directory x-permission where is r-permission */ int Xorriso_transfer_properties(struct XorrisO *xorriso, struct stat *stbuf, @@ -1807,7 +1913,7 @@ cannot_lstat:; sprintf(xorriso->info_text, "Grafting failed: %s = %s", Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0)); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); - ret=0; goto was_problem; + ret= 0; goto was_problem; } xorriso->pacifier_count++; @@ -2143,7 +2249,7 @@ attach_source:; ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt, disk_path, img_path, offset, cut_size, &node, flag&8); - if(ret<0) { + 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); @@ -2232,6 +2338,408 @@ unsupported_type:; } +/* @param flag bit0= minimal transfer: access permissions only +*/ +int Xorriso_restore_properties(struct XorrisO *xorriso, char *disk_path, + IsoNode *node, int flag) +{ + int ret; + mode_t mode; + uid_t uid; + gid_t gid; + struct utimbuf utime_buffer; + char sfe[5*SfileadrL]; + + mode= iso_node_get_permissions(node); + ret= chmod(disk_path, mode); + if(ret==-1) { + sprintf(xorriso->info_text, + "Cannot change access permissions of disk file %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + if(flag&1) + return(1); + uid= iso_node_get_uid(node); + gid= iso_node_get_gid(node); + chown(disk_path, uid, gid); /* don't complain if it fails */ + utime_buffer.actime= iso_node_get_atime(node); + utime_buffer.modtime= iso_node_get_mtime(node); + ret= utime(disk_path,&utime_buffer); + if(ret==-1) { + sprintf(xorriso->info_text, + "Cannot change atime, mtime of disk file %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + return(1); +} + + +#ifdef Osirrox_not_yeT + +/* @param flag bit0= cut_out mode : base on leaf parent directory +*/ +int Xorriso_restore_implict_properties(struct XorrisO *xorriso, IsoDir *dir, + char *full_disk_path, char *disk_path, char *full_img_path, int flag) +{ + int ret, nfic, ndc, nfdc, d, i; + char nfi[SfileadrL], nd[SfileadrL], nfd[SfileadrL], *cpt; + char sfe[5*SfileadrL]; + struct stat stbuf; + + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, full_disk_path, nfd, + 1|2|4); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, nd, 1|2); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, full_img_path, nfi, + 1|2); + if(ret<=0) + return(ret); + nfdc= Sfile_count_components(nfd, 0); + ndc= Sfile_count_components(nd, 0); + nfic= Sfile_count_components(nfi, 0); + d= nfdc-(flag&1)-ndc; + if(d<0) + return(-1); + if(d>nfic) + return(0); + for(i= 0; i>> CONSTRUCTION SITE */ + + + if(stat(nfi, &stbuf)==-1) + return(0); + + Xorriso_transfer_properties(xorriso, &stbuf, (IsoNode *) dir, + ((flag&1) && d==0)); + sprintf(xorriso->info_text, + "Copied properties for %s", Text_shellsafe(ni, sfe, 0)); + sprintf(xorriso->info_text+strlen(xorriso->info_text), + " from %s", Text_shellsafe(nfd, sfe, 0)); + if(!((flag&1) && d==0)) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + return(1); +} + +#endif /* Osirrox_not_yeT */ + + +/* @param flag bit0= minimal transfer: access permissions only + @return <0 severe error , 0 failure , 1 success +*/ +int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, + char *img_path, char *disk_path, int flag) +{ + int ret, write_fd= -1, wanted, wret; + char *what= "[unknown filetype]", sfe[5*SfileadrL], buf[32*1024]; + off_t todo, size; + void *stream2= NULL; + + if(LIBISO_ISDIR(node)) { + what= "directory"; + ret= mkdir(disk_path, 0777); + + } else if(LIBISO_ISREG(node)) { + what= "regular file"; + /* >>> need to exploit node rather than img_path */ + ret= Xorriso_iso_file_open(xorriso, img_path, &stream2, 0); + if(ret<=0) + goto ex; + write_fd= open(disk_path,O_WRONLY|O_EXCL|O_CREAT); + if(write_fd==-1) + goto cannot_restore; + todo= size= iso_file_get_size((IsoFile *) node); + while(todo>0) { + wanted= sizeof(buf); + if(wanted>todo) + wanted= todo; + ret= Xorriso_iso_file_read(xorriso, stream2, buf, wanted, 0); + if(ret<=0) + break; + wret= write(write_fd, buf, ret); + if(wret>=0) + todo-= wret; + if(wret != ret) { + sprintf(xorriso->info_text, + "Cannot write all bytes to disk filesystem path %s", + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); + break; + } + } + close(write_fd); + write_fd= -1; + Xorriso_iso_file_close(xorriso, &stream2, 0); + stream2= NULL; + ret= (todo==0); + + } else if(LIBISO_ISLNK(node)) { + what= "symbolic link"; + + goto not_this_type; + /* >>> restore symbolic link */; + + } else if(LIBISO_ISCHR(node)) { + what= "character device"; + + goto not_this_type; + /* >>> restore character device */; + + } else if(LIBISO_ISBLK(node)) { + what= "block device"; + + goto not_this_type; + /* >>> restore block device */; + + } else if(LIBISO_ISFIFO(node)) { + what= "named pipe"; + + goto not_this_type; + /* >>> restore fifo */; + + } else if(LIBISO_ISSOCK(node)) { + what= ""; + /* restoring a socket file makes no sense */; + + } else { +not_this_type:; + sprintf(xorriso->info_text, "Cannot restore file type '%s'", what); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + ret= 0; goto ex; + } + if(ret==-1) { +cannot_restore:; + sprintf(xorriso->info_text, + "Cannot restore %s to disk filesystem: %s", + what, Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= 0; goto ex; + } + ret= Xorriso_restore_properties(xorriso, disk_path, node, flag&1); +ex:; + if(write_fd>0) + close(write_fd); + Xorriso_iso_file_close(xorriso, &stream2, 0); + return(ret); +} + + +/* + @param flag + >>> bit0= mkdir: graft in as empty directory, not as copy from iso + bit1= do not report copied files + bit2= -follow, -not_*: this is not a command parameter + ??? <<< bit3= use offset and cut_size for cut_out_node + bit4= return 3 on rejection by exclusion or user + bit5= if directory then do not add sub tree + bit6= this is a copy action: do not fake times and ownership + @return <=0 = error , 1 = added leaf file object , 2 = added directory , + 3 = rejected +*/ +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; + IsoNode *node= NULL; + int done= 0, is_dir= 0, ret, target_is_dir, source_is_dir, stbuf_ret; + int target_is_split; + struct stat stbuf, target_stbuf; + + ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&4)); + if(ret<0) + return(ret); + if(ret>0) + return(3*!!(flag&16)); + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + + strncpy(path, disk_path, sizeof(path)-1); + path[sizeof(path)-1]= 0; + apt= npt= path; + + if(!(flag&1)) { + ret= Xorriso_fake_stbuf(xorriso, img_path, &stbuf, &node, 0); + if(ret>0) { + if(S_ISDIR(stbuf.st_mode)) + is_dir= 1; + +#ifdef Osirrox_not_yeT + else if((stbuf.st_mode&S_IFMT)==S_IFLNK && + (xorriso->do_follow_links || + (xorriso->do_follow_param && !(flag&4)))) { + resolve_link= 1; + ret= Xorriso_iso_lstat(xorriso, img_path, &stbuf, 1|2); + if(ret!=-1) { + if(S_ISDIR(stbuf.st_mode)) + is_dir= 1; + } + } +#endif /* Osirrox_not_yeT */ + + } else { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, + "Cannot determine attributes of (ISO) source file %s", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + } + } + + for(npt= apt; !done; apt= npt+1) { + npt= strchr(apt, '/'); + if(npt==NULL) { + npt= apt+strlen(apt); + done= 1; + } else + *npt= 0; + if(*apt==0) { + *apt= '/'; + apt++; + if(done) + goto attach_source; + continue; + } + source_is_dir= (is_dir || (flag&1) || !done); + + stbuf_ret= stat(path, &target_stbuf); + if(stbuf_ret!=-1) { + target_is_dir= S_ISDIR(target_stbuf.st_mode); + target_is_split= 0; + +#ifdef Osirrox_not_yeT + /* >>> */ + if(target_is_dir) + target_is_split= Xorriso_is_split(xorriso, node, 0); +#endif + + 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_rmx(xorriso, (off_t) 0, path, 1|8); + if(ret<=0) + return(ret); + 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); + return(3*!!(flag&16)); + } + 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); + return(0); + } + } + +handle_path_node:; + if(stbuf_ret==-1 && source_is_dir) { /* make a directory */ + ret= mkdir(path, 0777); + if(ret==-1) { + Xorriso_process_msg_queues(xorriso,0); + Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); + Xorriso_report_iso_error(xorriso, disk_path, ret, + "Cannot create disk directory", 0, "FAILURE", 1); + sprintf(xorriso->info_text, + "While restoring '%s' : could not insert '%s'", disk_path, path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + +#ifdef Osirrox_not_yeT + + if(disk_path!=NULL && !done) + Xorriso_restore_implict_properties(xorriso, dir, disk__path, path, + image_path, !!(flag&8)); +#endif /* Osirrox_not_yeT */ + + } + + if(done) { +attach_source:; + + if(flag&1) { + /* directory was created above */; + + } else if(is_dir) { + Xorriso_restore_properties(xorriso, disk_path, node, !!(flag&64)); + +#ifdef Osirrox_not_yeT + if(!(flag&32)) { + ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL, + flag&2); + if(ret<=0) + return(ret); + } +#endif + + } else { + +#ifdef Osirrox_not_yeT + + 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 + +#endif /* Osirrox_not_yeT */ + + img_path_pt= img_path; + + ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, path, + !!(flag&64)); + if(ret<=0) { + 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); + return(0); + } + + xorriso->pacifier_count++; + if(xorriso->pacifier_count%100 && !(flag&2)) + Xorriso_pacifier_callback(xorriso, "files restored", + xorriso->pacifier_count, + xorriso->pacifier_total, "", 0); + } + } else + *npt= '/'; + } + Xorriso_process_msg_queues(xorriso,0); + return(1+!!is_dir); +} + + int Xorriso_process_msg_queues(struct XorrisO *xorriso, int flag) { int ret, error_code= 0, os_errno= 0, count= 0, pass, imgid, tunneled; @@ -3635,90 +4143,6 @@ ex:; } -/* @param flag bit0= *node is already valid - bit1= add extra block for size estimation -*/ -int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf, - IsoNode **node, int flag) -{ - int ret; - IsoImage *volume; - - memset((char *) stbuf, 0, sizeof(struct stat)); - if(!(flag&1)) { - ret= Xorriso_get_volume(xorriso, &volume, 0); - if(ret<=0) - return(-1); - ret= Xorriso_node_from_path(xorriso, volume, path, node, 1); - if(ret<=0) - *node= NULL; - } - if(*node==NULL) - return(0); - - /* >>> stbuf->st_dev */ - /* >>> stbuf->st_ino */ - - stbuf->st_mode= iso_node_get_permissions(*node) & 07777; - if(LIBISO_ISDIR(*node)) - stbuf->st_mode|= S_IFDIR; - else if(LIBISO_ISREG(*node)) - stbuf->st_mode|= S_IFREG; - else if(LIBISO_ISLNK(*node)) - stbuf->st_mode|= S_IFLNK; - else if(LIBISO_ISLNK(*node)) - stbuf->st_mode|= S_IFCHR; - else if(LIBISO_ISBLK(*node)) - stbuf->st_mode|= S_IFBLK; - else if(LIBISO_ISFIFO(*node)) - stbuf->st_mode|= S_IFIFO; - else if(LIBISO_ISSOCK(*node)) - stbuf->st_mode|= S_IFSOCK; - - /* >>> NG How to represent LIBISO_BOOT ? */ - - - /* >>> With directories this should be : number of subdirs + 2 */ - /* >>> ??? How to obtain RR hardlink number for other types ? */ - stbuf->st_nlink= 1; - - stbuf->st_uid= iso_node_get_uid(*node); - stbuf->st_gid= iso_node_get_gid(*node); - - /* >>> stbuf->st_rdev */ - - if(LIBISO_ISREG(*node)) - stbuf->st_size= iso_file_get_size((IsoFile *) *node)+ (2048 * !!(flag&2)); - else - stbuf->st_size= 0; - - stbuf->st_blksize= 2048; - stbuf->st_blocks= stbuf->st_size / (off_t) 2048; - if(stbuf->st_blocks * (off_t) 2048 != stbuf->st_size) - stbuf->st_blocks++; - - stbuf->st_atime= iso_node_get_atime(*node); - stbuf->st_mtime= iso_node_get_mtime(*node); - stbuf->st_ctime= iso_node_get_ctime(*node); - return(1); -} - - -int Xorriso_iso_lstat(struct XorrisO *xorriso, char *path, struct stat *stbuf, - int flag) -{ - int ret; - IsoNode *node; - - ret= Xorriso_fake_stbuf(xorriso, path, stbuf, &node, 0); - if(ret>0) - return(0); - if(ret<0) - return(-2); - return(-1); -} - - int Xorriso_sorted_dir_i(struct XorrisO *xorriso, IsoDir *dir_node, int *filec, char ***filev, off_t boss_mem, int flag) { diff --git a/xorriso/xorrisoburn.h b/xorriso/xorrisoburn.h index 12a2e193..bd84e797 100644 --- a/xorriso/xorrisoburn.h +++ b/xorriso/xorrisoburn.h @@ -225,5 +225,20 @@ int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr, struct SplitparT **parts, int *count, struct stat *total_stbuf, int flag); +/* + @param flag + >>> bit0= mkdir: graft in as empty directory, not as copy from iso + bit1= do not report copied files + bit2= -follow, -not_*: this is not a command parameter + ??? <<< bit3= use offset and cut_size for cut_out_node + bit4= return 3 on rejection by exclusion or user + bit5= if directory then do not add sub tree + bit6= this is a copy action: do not fake times and ownership + @return <=0 = error , 1 = added leaf file object , 2 = added directory , + 3 = rejected +*/ +int Xorriso_restore(struct XorrisO *xorriso, + char *img_path, char *disk_path, int flag); + #endif /* Xorrisoburn_includeD */