From 691955d387e3a45a6df90965494bf45e27966dca Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sat, 29 Mar 2008 16:44:39 +0000 Subject: [PATCH] New option -split_size, automated splitting of oversized files --- xorriso/xorriso.1 | 16 +++- xorriso/xorriso.c | 47 ++++++++++-- xorriso/xorriso.h | 3 + xorriso/xorriso_private.h | 5 ++ xorriso/xorriso_timestamp.h | 2 +- xorriso/xorrisoburn.c | 146 ++++++++++++++++++++++++++++++++---- xorriso/xorrisoburn.h | 3 + 7 files changed, 194 insertions(+), 28 deletions(-) diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index 0a65ac26..056e7297 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -590,8 +590,8 @@ inherited from cp -r behavior. Its syntax resembles cp, though. Map a byte interval of a regular disk file into a regular file in the ISO image. This may be necessary if the disk file is larger than a single media, or if -it exceeds the traditional limit of 2 GiB - 2 kiB for old operating systems, -or the limit of 4 GiB - 2 kiB for newer ones. +it exceeds the traditional limit of 2 GiB - 1 for old operating systems, +or the limit of 4 GiB - 1 for newer ones. .br A clumsy remedy for this limit is to backup file pieces and to concatenate them at restore time. A well tested chopping size is 2047m. @@ -621,7 +621,7 @@ A disk file gets mapped to an ISO directory containing its split parts as regular files. The parts have names which describe the splitting by 5 numbers which are separated by some non-numerical text: .br -part_number, total_parts, byte_offset, byte_count, disk_path_size +part_number, total_parts, byte_offset, byte_count, disk_file_size .br Scaling characters like "m" or "k" are taken into respect and may serve as separators as well. All digits are interpreted as decimal, @@ -988,6 +988,16 @@ 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. .TP +\fB\-split_size\fR number["k"|"m"] +Set the threshold for automatic splitting of regular files. Such splitting +maps a large disk file onto a ISO directory with several part files in it. +This is necessary if the size of the disk file exceeds 4 GiB - 1. +Older operating systems can handle files only if they are 2 GiB - 1. +See also option -cut_out for more information about file parts. +.br +Default is 0 which will exclude files >= 4 GiB by a FAILURE event. +A well tested -split_size is 2047m. Sizes of 4 GiB or more are not permissible. +.TP .B Settings for result writing: .TP Rock Ridge info will be generated by the program unconditionally. diff --git a/xorriso/xorriso.c b/xorriso/xorriso.c index 7b245666..a954b35d 100644 --- a/xorriso/xorriso.c +++ b/xorriso/xorriso.c @@ -2960,6 +2960,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) strcpy(m->wdx, m->initial_wdx); m->did_something_useful= 0; m->add_plainly= 0; + m->split_size= 0; m->do_joliet= 0; m->do_follow_pattern= 1; m->do_follow_param= 0; @@ -4152,6 +4153,18 @@ int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag) (xorriso->wdx[0] ? Text_shellsafe(xorriso->wdx,sfe,0) : "'/'")); Xorriso_status_result(xorriso,filter,fp,flag&2); + is_default= (xorriso->split_size==0); + strcpy(line,"-split_size "); + if(xorriso->split_size % (1024*1024) || xorriso->split_size==0) { + Sfile_off_t_text(line+strlen(line), xorriso->split_size, 0); + } else { + Sfile_off_t_text(line+strlen(line), xorriso->split_size / (1024*1024), 0); + strcat(line, "m"); + } + strcat(line, "\n"); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + is_default= (xorriso->add_plainly==0); sprintf(line,"-add_plainly %s\n", (xorriso->add_plainly == 1 ? "unknown" : @@ -4679,7 +4692,7 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr, /* Splitfile parts */ if((S_ISREG(s1.st_mode) || S_ISBLK(s1.st_mode)) && S_ISDIR(s2.st_mode)) { - is_split= Xorriso_identify_split(xorriso, iso_adr, &split_parts, + is_split= Xorriso_identify_split(xorriso, iso_adr, NULL, &split_parts, &split_count, &s2, 0); if(is_split>0) (*result)|= (1<<17); @@ -7620,9 +7633,6 @@ int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter, if(compare_result&(8|64)) { /* file type, minor+major with device file */ - - /* <<< ??? SPLIT : cannot happen here ??? really ? */ - ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1); /* rm_r */ if(ret>0) { deleted= 1; @@ -7643,8 +7653,7 @@ delete:; content bytes differ */ if(is_split) { - /* >>> SPLIT : differing content or size */; - ret= Xorriso_identify_split(xorriso, iso_rr_path, + ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL, &split_parts, &split_count, &stbuf, 0); if(ret<=0) {ret= -1; goto ex;} /* (should not happen) */ @@ -7709,7 +7718,7 @@ delete:; /* access permissions, user id, group id, mtime, atime, ctime */ if(is_split) { - ret= Xorriso_identify_split(xorriso, iso_rr_path, + ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL, &split_parts, &split_count, &stbuf, 0); if(ret<=0) {ret= -1; goto ex;} /* (should not happen) */ @@ -8637,7 +8646,6 @@ ex:; /* SPLIT : proposed target format - part_{partno}_of_{total_parts}_at_{offset}_with_{bytes}_of_{total_bytes} */ @@ -10554,6 +10562,25 @@ dvd_speed:; } +/* Option -split_size */ +int Xorriso_option_split_size(struct XorrisO *xorriso, char *size, int flag) +{ + double num; + static off_t limit= ((off_t) 4) * ((off_t) 1024*1024*1024) - (off_t) 1; + + num= Scanf_io_size(size, 0); + if(num > limit) { + sprintf(xorriso->info_text, "-split_size: too large %.f (allowed: %.f)", + num, (double) limit); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } else if(num < 0) + num= 0.0; + xorriso->split_size= num; + return(1); +} + + /* Option -status */ int Xorriso_option_status(struct XorrisO *xorriso, char *mode, int flag) { @@ -11220,6 +11247,10 @@ next_command:; (*idx)++; ret= Xorriso_option_speed(xorriso, arg1, 0); + } else if(strcmp(cmd,"split_size")==0) { + (*idx)++; + ret= Xorriso_option_split_size(xorriso, arg1, 0); + } else if(strcmp(cmd,"status")==0) { (*idx)++; ret= Xorriso_option_status(xorriso, arg1, 0); diff --git a/xorriso/xorriso.h b/xorriso/xorriso.h index 44cf9aae..ddc0c29c 100644 --- a/xorriso/xorriso.h +++ b/xorriso/xorriso.h @@ -406,6 +406,9 @@ int Xorriso_option_rollback(struct XorrisO *xorriso, int flag); /* Option -speed */ int Xorriso_option_speed(struct XorrisO *xorriso, char *speed, int flag); +/* Option -split_size */ +int Xorriso_option_split_size(struct XorrisO *xorriso, char *s, int flag); + /* Option -status */ int Xorriso_option_status(struct XorrisO *xorriso, char *mode, int flag); diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index 3c3e6b9d..caa388f3 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -77,6 +77,7 @@ struct XorrisO { /* the global context of xorriso */ int did_something_useful; int add_plainly; + off_t split_size; /* >>> put libisofs aspects here <<< */ @@ -444,5 +445,9 @@ int Splitparts_get(struct SplitparT *o, int idx, char **name, int *partno, int Splitpart__parse(char *name, int *partno, int *total_parts, off_t *offset, off_t *bytes, off_t *total_bytes, int flag); +int Splitpart__compose(char *adr, int partno, int total_parts, + off_t offset, off_t bytes, off_t total_bytes, int flag); + + #endif /* Xorriso_private_includeD */ diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 5e9762f1..c91c8a77 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.03.27.103344" +#define Xorriso_timestamP "2008.03.29.164038" diff --git a/xorriso/xorrisoburn.c b/xorriso/xorrisoburn.c index a3d37f6d..a490e0d8 100644 --- a/xorriso/xorrisoburn.c +++ b/xorriso/xorrisoburn.c @@ -56,12 +56,20 @@ #endif /* Xorriso_standalonE */ - +/* Some private in advance declarations */ int Xorriso_pacifier_loop(struct XorrisO *xorriso, struct burn_drive *drive, int flag); int Xorriso__read_pacifier(IsoImage *image, IsoFileSource *filesource); +int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume, + IsoDir *dir, char *disk_path, char *img_name, + char *nominal_source, char *nominal_target, + off_t offset, off_t cut_size, + IsoNode **node, int flag); + +int Xorriso_is_split(struct XorrisO *xorriso, IsoNode *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) @@ -1384,6 +1392,45 @@ int Xorriso_transfer_properties(struct XorrisO *xorriso, struct stat *stbuf, } +int Xorriso_graft_split(struct XorrisO *xorriso, IsoImage *volume, + IsoDir *dir, char *disk_path, char *img_name, + char *nominal_source, char *nominal_target, + off_t size, IsoNode **node, int flag) +{ + int ret; + IsoDir *new_dir= NULL; + IsoNode *part_node; + int partno, total_parts; + off_t offset; + char part_name[SfileadrL], sfe[5*SfileadrL]; + + ret= iso_tree_add_new_dir(dir, img_name, &new_dir); + if(ret<0) + return(ret); + *node= (IsoNode *) new_dir; + + total_parts= size / xorriso->split_size; + if(size % xorriso->split_size) + total_parts++; + for(partno= 1; partno<=total_parts; partno++) { + offset = xorriso->split_size * (off_t) (partno-1); + Splitpart__compose(part_name, partno, total_parts, offset, + xorriso->split_size, size, 0); + ret= Xorriso_tree_graft_node(xorriso, volume, + new_dir, disk_path, part_name, + nominal_source, nominal_target, + offset, xorriso->split_size, + &part_node, 8); + if(ret<=0) + return(0); + } + sprintf(xorriso->info_text, "Split into %d parts: %s", + total_parts, Text_shellsafe(nominal_target, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + return(1); +} + + /* @param flag bit3= cut_out_node: offset and size are valid */ @@ -1394,13 +1441,48 @@ int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume, IsoNode **node, int flag) { int ret; + struct stat stbuf; + char sfe[5*SfileadrL]; + off_t size= 0; + static off_t limit= ((off_t) 4) * ((off_t) 1024*1024*1024) - (off_t) 1; - if(flag&8) + if(flag&8) { + if(cut_size > limit) { + sprintf(xorriso->info_text, + "File piece exceeds size limit of %.f bytes: %.f from %s\n", + (double) limit, (double) cut_size, + Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } ret= iso_tree_add_new_cut_out_node(volume, dir, img_name, disk_path, offset, cut_size, node); - else - ret= iso_tree_add_new_node(volume, dir, img_name, disk_path, node); + if(ret<0) + goto ex; + } else { + if(stat(disk_path, &stbuf)!=-1) + if(S_ISREG(stbuf.st_mode)) + size= stbuf.st_size; + if(xorriso->split_size > 0 && size > xorriso->split_size) { + ret= Xorriso_graft_split(xorriso, volume, dir, disk_path, img_name, + nominal_source, nominal_target, size, + node, 0); + if(ret<=0) + goto ex; + return(1); + } else if(size > limit) { + sprintf(xorriso->info_text, + "File exceeds size limit of %.f bytes: %s\n", + (double) limit, Text_shellsafe(disk_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= iso_tree_add_new_node(volume, dir, img_name, disk_path, node); + if(ret<0) + goto ex; + } +ex:; if(ret<0) { Xorriso_process_msg_queues(xorriso,0); Xorriso_report_iso_error(xorriso, nominal_source, ret, @@ -1422,7 +1504,7 @@ int Xorriso_add_tree(struct XorrisO *xorriso, IsoDir *dir, IsoNode *node; IsoSymlink *iso_symlink; int ret, target_is_dir, source_is_dir, source_is_link, fret, was_failure= 0; - int do_not_dive; + int do_not_dive, target_is_split= 0; struct DirseQ *dirseq= NULL; char *name, *img_name, *srcpt, *stbuf_src= ""; struct stat stbuf, hstbuf; @@ -1561,12 +1643,16 @@ cannot_lstat:; ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1); if(ret>0) { target_is_dir= LIBISO_ISDIR(node); - if(!(target_is_dir && source_is_dir)) { + target_is_split= 0; + if(target_is_dir) + target_is_split= Xorriso_is_split(xorriso, node, 0); + + 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)) { + (xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) { ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, img_path, 1|8); if(ret<=0) goto was_problem; @@ -1778,6 +1864,7 @@ int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter, IsoDir *dir, *hdir; IsoNode *node; int done= 0, is_dir= 0, l, ret, target_is_dir, source_is_dir, resolve_link= 0; + int target_is_split; struct stat stbuf; for(cpt= img_path; 1; cpt++) { @@ -1880,12 +1967,17 @@ int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter, ret= Xorriso_node_from_path(xorriso, volume, path, &node, 1); if(ret>0) { target_is_dir= LIBISO_ISDIR(node); - if(!(target_is_dir && source_is_dir)) { + + target_is_split= 0; + if(target_is_dir) + target_is_split= Xorriso_is_split(xorriso, node, 0); + + 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)) { + (xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) { ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, path, 1|8); if(ret<=0) return(ret); @@ -4692,13 +4784,17 @@ int Xorriso_iso_file_close(struct XorrisO *xorriso, void **stream, int flag) } +/* @param flag bit0= in_node is valid, do not resolve iso_adr +*/ int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr, + void *in_node, struct SplitparT **parts, int *count, struct stat *total_stbuf, int flag) { int ret, i; int partno, total_parts, first_total_parts= -1; - off_t offset, bytes, total_bytes, first_total_bytes= -1, first_bytes, size; + off_t offset, bytes, total_bytes, first_total_bytes= -1, first_bytes= -1; + off_t size; IsoImage *volume; IsoDir *dir_node; IsoDirIter *iter= NULL; @@ -4709,12 +4805,16 @@ int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr, *count= 0; *parts= NULL; - ret= Xorriso_get_volume(xorriso, &volume, 0); - if(ret<=0) - return(-1); - ret= Xorriso_node_from_path(xorriso, volume, iso_adr, &node, 1); - if(ret<=0) - return(-1); + if(flag&1) { + node= (IsoNode *) in_node; + } else { + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(-1); + ret= Xorriso_node_from_path(xorriso, volume, iso_adr, &node, 1); + if(ret<=0) + return(-1); + } if(!LIBISO_ISDIR(node)) return(0); dir_node= (IsoDir *) node; @@ -4797,3 +4897,17 @@ ex:; return(ret); } + +int Xorriso_is_split(struct XorrisO *xorriso, IsoNode *node, int flag) +{ + struct SplitparT *split_parts= NULL; + int split_count= 0, ret; + struct stat stbuf; + + ret= Xorriso_identify_split(xorriso, "", (void *) node, &split_parts, + &split_count, &stbuf, 1); + if(split_parts!=NULL) + Splitparts_destroy(&split_parts, split_count, 0); + return(ret>0); +} + diff --git a/xorriso/xorrisoburn.h b/xorriso/xorrisoburn.h index 2a58a314..9a28a4ca 100644 --- a/xorriso/xorrisoburn.h +++ b/xorriso/xorrisoburn.h @@ -197,7 +197,10 @@ int Xorriso_cut_out(struct XorrisO *xorriso, char *disk_path, struct SplitparT; +/* @param flag bit0= in_node is valid, do not resolve iso_adr +*/ int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr, + void *in_node, struct SplitparT **parts, int *count, struct stat *total_stbuf, int flag);