New option -split_size, automated splitting of oversized files

This commit is contained in:
Thomas Schmitt 2008-03-29 16:44:39 +00:00
parent 3474a6a981
commit 691955d387
7 changed files with 194 additions and 28 deletions

View File

@ -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 Map a byte interval of a regular disk file into a regular file in the ISO
image. image.
This may be necessary if the disk file is larger than a single media, or if 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, it exceeds the traditional limit of 2 GiB - 1 for old operating systems,
or the limit of 4 GiB - 2 kiB for newer ones. or the limit of 4 GiB - 1 for newer ones.
.br .br
A clumsy remedy for this limit is to backup file pieces and to concatenate 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. 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 as regular files. The parts have names which describe the splitting
by 5 numbers which are separated by some non-numerical text: by 5 numbers which are separated by some non-numerical text:
.br .br
part_number, total_parts, byte_offset, byte_count, disk_path_size part_number, total_parts, byte_offset, byte_count, disk_file_size
.br .br
Scaling characters like "m" or "k" are taken into respect and may Scaling characters like "m" or "k" are taken into respect and may
serve as separators as well. All digits are interpreted as decimal, 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 Setting "on" allows automatic -rm_r. I.e. a non-directory can replace an
existing directory and all its subordinates. existing directory and all its subordinates.
.TP .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: .B Settings for result writing:
.TP .TP
Rock Ridge info will be generated by the program unconditionally. Rock Ridge info will be generated by the program unconditionally.

View File

@ -2960,6 +2960,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag)
strcpy(m->wdx, m->initial_wdx); strcpy(m->wdx, m->initial_wdx);
m->did_something_useful= 0; m->did_something_useful= 0;
m->add_plainly= 0; m->add_plainly= 0;
m->split_size= 0;
m->do_joliet= 0; m->do_joliet= 0;
m->do_follow_pattern= 1; m->do_follow_pattern= 1;
m->do_follow_param= 0; 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->wdx[0] ? Text_shellsafe(xorriso->wdx,sfe,0) : "'/'"));
Xorriso_status_result(xorriso,filter,fp,flag&2); 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); is_default= (xorriso->add_plainly==0);
sprintf(line,"-add_plainly %s\n", sprintf(line,"-add_plainly %s\n",
(xorriso->add_plainly == 1 ? "unknown" : (xorriso->add_plainly == 1 ? "unknown" :
@ -4679,7 +4692,7 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr,
/* Splitfile parts */ /* Splitfile parts */
if((S_ISREG(s1.st_mode) || S_ISBLK(s1.st_mode)) && S_ISDIR(s2.st_mode)) { 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); &split_count, &s2, 0);
if(is_split>0) if(is_split>0)
(*result)|= (1<<17); (*result)|= (1<<17);
@ -7620,9 +7633,6 @@ int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter,
if(compare_result&(8|64)) { if(compare_result&(8|64)) {
/* file type, minor+major with device file */ /* 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 */ ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1); /* rm_r */
if(ret>0) { if(ret>0) {
deleted= 1; deleted= 1;
@ -7643,8 +7653,7 @@ delete:;
content bytes differ */ content bytes differ */
if(is_split) { if(is_split) {
/* >>> SPLIT : differing content or size */; ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL,
ret= Xorriso_identify_split(xorriso, iso_rr_path,
&split_parts, &split_count, &stbuf, 0); &split_parts, &split_count, &stbuf, 0);
if(ret<=0) if(ret<=0)
{ret= -1; goto ex;} /* (should not happen) */ {ret= -1; goto ex;} /* (should not happen) */
@ -7709,7 +7718,7 @@ delete:;
/* access permissions, user id, group id, mtime, atime, ctime */ /* access permissions, user id, group id, mtime, atime, ctime */
if(is_split) { 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); &split_parts, &split_count, &stbuf, 0);
if(ret<=0) if(ret<=0)
{ret= -1; goto ex;} /* (should not happen) */ {ret= -1; goto ex;} /* (should not happen) */
@ -8637,7 +8646,6 @@ ex:;
/* SPLIT : proposed target format /* SPLIT : proposed target format
part_{partno}_of_{total_parts}_at_{offset}_with_{bytes}_of_{total_bytes} 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 */ /* Option -status */
int Xorriso_option_status(struct XorrisO *xorriso, char *mode, int flag) int Xorriso_option_status(struct XorrisO *xorriso, char *mode, int flag)
{ {
@ -11220,6 +11247,10 @@ next_command:;
(*idx)++; (*idx)++;
ret= Xorriso_option_speed(xorriso, arg1, 0); 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) { } else if(strcmp(cmd,"status")==0) {
(*idx)++; (*idx)++;
ret= Xorriso_option_status(xorriso, arg1, 0); ret= Xorriso_option_status(xorriso, arg1, 0);

View File

@ -406,6 +406,9 @@ int Xorriso_option_rollback(struct XorrisO *xorriso, int flag);
/* Option -speed */ /* Option -speed */
int Xorriso_option_speed(struct XorrisO *xorriso, char *speed, int flag); 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 */ /* Option -status */
int Xorriso_option_status(struct XorrisO *xorriso, char *mode, int flag); int Xorriso_option_status(struct XorrisO *xorriso, char *mode, int flag);

View File

@ -77,6 +77,7 @@ struct XorrisO { /* the global context of xorriso */
int did_something_useful; int did_something_useful;
int add_plainly; int add_plainly;
off_t split_size;
/* >>> put libisofs aspects here <<< */ /* >>> 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, int Splitpart__parse(char *name, int *partno, int *total_parts,
off_t *offset, off_t *bytes, off_t *total_bytes, int flag); 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 */ #endif /* Xorriso_private_includeD */

View File

@ -1 +1 @@
#define Xorriso_timestamP "2008.03.27.103344" #define Xorriso_timestamP "2008.03.29.164038"

View File

@ -56,12 +56,20 @@
#endif /* Xorriso_standalonE */ #endif /* Xorriso_standalonE */
/* Some private in advance declarations */
int Xorriso_pacifier_loop(struct XorrisO *xorriso, struct burn_drive *drive, int Xorriso_pacifier_loop(struct XorrisO *xorriso, struct burn_drive *drive,
int flag); int flag);
int Xorriso__read_pacifier(IsoImage *image, IsoFileSource *filesource); 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_ISDIR(node) (iso_node_get_type(node) == LIBISO_DIR)
#define LIBISO_ISREG(node) (iso_node_get_type(node) == LIBISO_FILE) #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 @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) IsoNode **node, int flag)
{ {
int ret; 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, ret= iso_tree_add_new_cut_out_node(volume, dir, img_name, disk_path,
offset, cut_size, node); offset, cut_size, node);
else if(ret<0)
ret= iso_tree_add_new_node(volume, dir, img_name, disk_path, node); 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) { if(ret<0) {
Xorriso_process_msg_queues(xorriso,0); Xorriso_process_msg_queues(xorriso,0);
Xorriso_report_iso_error(xorriso, nominal_source, ret, Xorriso_report_iso_error(xorriso, nominal_source, ret,
@ -1422,7 +1504,7 @@ int Xorriso_add_tree(struct XorrisO *xorriso, IsoDir *dir,
IsoNode *node; IsoNode *node;
IsoSymlink *iso_symlink; IsoSymlink *iso_symlink;
int ret, target_is_dir, source_is_dir, source_is_link, fret, was_failure= 0; 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; struct DirseQ *dirseq= NULL;
char *name, *img_name, *srcpt, *stbuf_src= ""; char *name, *img_name, *srcpt, *stbuf_src= "";
struct stat stbuf, hstbuf; struct stat stbuf, hstbuf;
@ -1561,12 +1643,16 @@ cannot_lstat:;
ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1); ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1);
if(ret>0) { if(ret>0) {
target_is_dir= LIBISO_ISDIR(node); 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); Xorriso_process_msg_queues(xorriso,0);
/* handle overwrite situation */; /* handle overwrite situation */;
if(xorriso->do_overwrite==1 || 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); ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, img_path, 1|8);
if(ret<=0) if(ret<=0)
goto was_problem; goto was_problem;
@ -1778,6 +1864,7 @@ int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter,
IsoDir *dir, *hdir; IsoDir *dir, *hdir;
IsoNode *node; IsoNode *node;
int done= 0, is_dir= 0, l, ret, target_is_dir, source_is_dir, resolve_link= 0; int done= 0, is_dir= 0, l, ret, target_is_dir, source_is_dir, resolve_link= 0;
int target_is_split;
struct stat stbuf; struct stat stbuf;
for(cpt= img_path; 1; cpt++) { 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); ret= Xorriso_node_from_path(xorriso, volume, path, &node, 1);
if(ret>0) { if(ret>0) {
target_is_dir= LIBISO_ISDIR(node); 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); Xorriso_process_msg_queues(xorriso,0);
/* handle overwrite situation */; /* handle overwrite situation */;
if(xorriso->do_overwrite==1 || 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); ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, path, 1|8);
if(ret<=0) if(ret<=0)
return(ret); 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, int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr,
void *in_node,
struct SplitparT **parts, int *count, struct SplitparT **parts, int *count,
struct stat *total_stbuf, int flag) struct stat *total_stbuf, int flag)
{ {
int ret, i; int ret, i;
int partno, total_parts, first_total_parts= -1; 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; IsoImage *volume;
IsoDir *dir_node; IsoDir *dir_node;
IsoDirIter *iter= NULL; IsoDirIter *iter= NULL;
@ -4709,12 +4805,16 @@ int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr,
*count= 0; *count= 0;
*parts= NULL; *parts= NULL;
ret= Xorriso_get_volume(xorriso, &volume, 0); if(flag&1) {
if(ret<=0) node= (IsoNode *) in_node;
return(-1); } else {
ret= Xorriso_node_from_path(xorriso, volume, iso_adr, &node, 1); ret= Xorriso_get_volume(xorriso, &volume, 0);
if(ret<=0) if(ret<=0)
return(-1); return(-1);
ret= Xorriso_node_from_path(xorriso, volume, iso_adr, &node, 1);
if(ret<=0)
return(-1);
}
if(!LIBISO_ISDIR(node)) if(!LIBISO_ISDIR(node))
return(0); return(0);
dir_node= (IsoDir *) node; dir_node= (IsoDir *) node;
@ -4797,3 +4897,17 @@ ex:;
return(ret); 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);
}

View File

@ -197,7 +197,10 @@ int Xorriso_cut_out(struct XorrisO *xorriso, char *disk_path,
struct SplitparT; struct SplitparT;
/* @param flag bit0= in_node is valid, do not resolve iso_adr
*/
int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr, int Xorriso_identify_split(struct XorrisO *xorriso, char *iso_adr,
void *in_node,
struct SplitparT **parts, int *count, struct SplitparT **parts, int *count,
struct stat *total_stbuf, int flag); struct stat *total_stbuf, int flag);