From 05de7ec5ee569408208a547369bc7541fd76520c Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 3 Nov 2020 09:27:41 +0100 Subject: [PATCH] New -osirrox option sparse= controls extraction into sparse files --- xorriso/base_obj.c | 2 + xorriso/misc_funct.c | 17 ++- xorriso/misc_funct.h | 13 +- xorriso/opts_d_h.c | 1 + xorriso/opts_i_o.c | 16 ++ xorriso/opts_p_z.c | 28 ++-- xorriso/read_run.c | 297 +++++++++++++++++++++++++++++++++++- xorriso/text_io.c | 21 ++- xorriso/xorriso.1 | 17 ++- xorriso/xorriso.info | 112 ++++++++------ xorriso/xorriso.texi | 17 ++- xorriso/xorriso_private.h | 3 + xorriso/xorriso_timestamp.h | 2 +- 13 files changed, 464 insertions(+), 82 deletions(-) diff --git a/xorriso/base_obj.c b/xorriso/base_obj.c index 59e2ea00..5f3e1e28 100644 --- a/xorriso/base_obj.c +++ b/xorriso/base_obj.c @@ -473,6 +473,8 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->show_hfs_cmd_count= 0; m->show_hfs_cmds= NULL; + m->sparse_min_gap= 0; + m->result_line[0]= 0; m->result_line_counter= 0; m->result_page_counter= 0; diff --git a/xorriso/misc_funct.c b/xorriso/misc_funct.c index cadf78f9..5aa2ddf4 100644 --- a/xorriso/misc_funct.c +++ b/xorriso/misc_funct.c @@ -1,7 +1,7 @@ /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images. - Copyright 2007-2019 Thomas Schmitt, + Copyright 2007-2020 Thomas Schmitt, Provided under GPL version 2 or later. @@ -1367,3 +1367,18 @@ int Xorriso__format_guid(uint8_t guid[16], char *text, int flag) return(1); } + +int Xorriso__parse_size_param(char *cpt, int key_l, int l, double *num) +{ + char text[16]; + + *num= 0.0; + if(l <= key_l || l >= key_l + 16) + return(0); + strncpy(text, cpt + key_l, l - key_l); + text[l - key_l]= 0; + *num= Scanf_io_size(text, 0); + return(1); +} + + diff --git a/xorriso/misc_funct.h b/xorriso/misc_funct.h index 5b8c41e1..bb27772f 100644 --- a/xorriso/misc_funct.h +++ b/xorriso/misc_funct.h @@ -1,11 +1,12 @@ /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images. - Copyright 2007-2019 Thomas Schmitt, + Copyright 2007-2020 Thomas Schmitt, Provided under GPL version 2 or later. - This file contains declarations of cellaneous helper functions of xorriso. + This file contains declarations of miscellaneous helper functions of + xorriso. */ @@ -114,5 +115,13 @@ int Xorriso__exchange_prefix(char *source_prefix, char *target_prefix, */ int Xorriso__format_guid(uint8_t guid[16], char *text, int flag); +/* @param cpt start of keyword=value string + @param key_l length from cpt of keyword= string + @param l length from cpt up to end of value string + @param num result +*/ +int Xorriso__parse_size_param(char *cpt, int key_l, int l, double *num); + + #endif /* ! Xorriso_pvt_misc_includeD */ diff --git a/xorriso/opts_d_h.c b/xorriso/opts_d_h.c index 41f9fc7c..1ebba0d4 100644 --- a/xorriso/opts_d_h.c +++ b/xorriso/opts_d_h.c @@ -2308,6 +2308,7 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag) " [:\"sort_lba_on\"|\"sort_lba_off\"]", " [:\"strict_acl_on\"|\"strict_acl_off\"]", " [:\"check_md5_on\"|\"check_md5_off\"|\"check_md5_force\"]", +" [:\"sparse=off\"|\"sparse=\"number]", " By default \"off\" the inverse operation of xorriso from ISO", " image to disk filesystem is disabled. \"on\" allows xorriso", " to create, overwrite, delete files in the disk filesystem.", diff --git a/xorriso/opts_i_o.c b/xorriso/opts_i_o.c index 064268bc..05568046 100644 --- a/xorriso/opts_i_o.c +++ b/xorriso/opts_i_o.c @@ -1746,6 +1746,7 @@ int Xorriso_option_osirrox(struct XorrisO *xorriso, char *mode, int flag) { int l, allow_restore; char *npt, *cpt; + double num= 0.0; allow_restore= xorriso->allow_restore; @@ -1799,6 +1800,21 @@ int Xorriso_option_osirrox(struct XorrisO *xorriso, char *mode, int flag) xorriso->do_md5|= 3 << 6; } else if(strncmp(cpt, "check_md5_off", l)==0 && l >= 13) { xorriso->do_md5&= ~(3 << 6); + } else if(strncmp(cpt, "sparse=", 7) == 0 && l >= 7) { + if(strncmp(cpt + 7, "off", 3) == 0 && l == 10) { + num= 0.0; + } else { + Xorriso__parse_size_param(cpt, 7, l, &num); + if(num < 1.0) + num= 0.0; + if(num > 1.0 * 1024.0 * 1024.0 * 1024.0) { + strcpy(xorriso->info_text, + "osirrox sparse= too large (allowed: off, 1 to 1g)"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + } + xorriso->sparse_min_gap= num; } else { unknown_mode:; sprintf(xorriso->info_text, "-osirrox: unknown mode '%s'", cpt); diff --git a/xorriso/opts_p_z.c b/xorriso/opts_p_z.c index 13a65751..68d5dca2 100644 --- a/xorriso/opts_p_z.c +++ b/xorriso/opts_p_z.c @@ -147,8 +147,11 @@ int Xorriso_option_paste_in(struct XorrisO *xorriso, char *iso_rr_path, (double) startbyte, (double) (startbyte+bytecount)); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + Xorriso_pacifier_reset(xorriso, 0); ret= Xorriso_paste_in(xorriso, disk_path, startbyte, bytecount, iso_rr_path, 0); + Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count, + xorriso->pacifier_total, "", 1 | 4 | 8 | 32); return(ret); } @@ -2245,19 +2248,6 @@ int Xorriso_option_xattr(struct XorrisO *xorriso, char *mode, int flag) } -static int parse_zisofs_param(char *cpt, int key_l, int l, double *num) -{ - char text[16]; - - *num= 0.0; - if(l <= key_l || l >= key_l + 16) - return(0); - strncpy(text, cpt + key_l, l - key_l); - text[l - key_l]= 0; - *num= Scanf_io_size(text, 0); - return(1); -} - /* Option -zisofs */ int Xorriso_option_zisofs(struct XorrisO *xorriso, char *mode, int flag) { @@ -2307,7 +2297,7 @@ int Xorriso_option_zisofs(struct XorrisO *xorriso, char *mode, int flag) /* (ignored info from -status) */; } else if(strncmp(cpt, "block_size=", 11)==0) { - parse_zisofs_param(cpt, 11, l, &num); + Xorriso__parse_size_param(cpt, 11, l, &num); if (num != (1 << 15) && num != (1 << 16) && num != (1 << 17)) { sprintf(xorriso->info_text, "-zisofs: Unsupported block size (allowed 32k, 64k, 128k)"); @@ -2342,7 +2332,7 @@ int Xorriso_option_zisofs(struct XorrisO *xorriso, char *mode, int flag) } } else if(strncmp(cpt, "max_bpt=", 8) == 0) { - parse_zisofs_param(cpt, 8, l, &num); + Xorriso__parse_size_param(cpt, 8, l, &num); if(num < 1024.0 || num > 128.0 * 1024.0 * 1024.0 * 1024.0) { sprintf(xorriso->info_text, "-zisofs: Unsupported block pointer pool size (allowed: 1k to 128g)"); @@ -2357,7 +2347,7 @@ int Xorriso_option_zisofs(struct XorrisO *xorriso, char *mode, int flag) xorriso->zisofs_max_file_blocks= xorriso->zisofs_max_total_blocks; } else if(strncmp(cpt, "max_bpt_f=", 10) == 0) { - parse_zisofs_param(cpt, 10, l, &num); + Xorriso__parse_size_param(cpt, 10, l, &num); if(num < 1024.0 || num > 128.0 * 1024.0 * 1024.0 * 1024.0) { sprintf(xorriso->info_text, "-zisofs: Unsupported block pointer list size (allowed: 1k to 128g)"); @@ -2368,7 +2358,7 @@ int Xorriso_option_zisofs(struct XorrisO *xorriso, char *mode, int flag) xorriso->zisofs_max_total_blocks= xorriso->zisofs_max_file_blocks; } else if(strncmp(cpt, "block_size_v2=", 14) == 0) { - parse_zisofs_param(cpt, 14, l, &num); + Xorriso__parse_size_param(cpt, 14, l, &num); for(i= 15 ; i <= 20; i++) if(num == (1 << i)) break; @@ -2380,11 +2370,11 @@ int Xorriso_option_zisofs(struct XorrisO *xorriso, char *mode, int flag) xorriso->zisofs_v2_block_size= num; } else if(strncmp(cpt, "bpt_target=", 11) == 0) { - parse_zisofs_param(cpt, 11, l, &num); + Xorriso__parse_size_param(cpt, 11, l, &num); xorriso->zisofs_block_number_target= num; } else if(strncmp(cpt, "bpt_free_ratio=", 15) == 0) { - parse_zisofs_param(cpt, 15, l, &num); + Xorriso__parse_size_param(cpt, 15, l, &num); /* 0 means to libisofs "do not change" */ if(num == 0.0) num= -1.0; diff --git a/xorriso/read_run.c b/xorriso/read_run.c index ba13fd6e..d6cf5287 100644 --- a/xorriso/read_run.c +++ b/xorriso/read_run.c @@ -533,6 +533,278 @@ ex:; } +/* If defined the position accounting will be done by lseek() and used to + * verify the position accounting in struct Xorriso_sparse_statE. + * # def ine Xorriso_check_sparsE yes + */ + +struct Xorriso_sparse_statE { + int use_lseek; + off_t cur_pos; + off_t after_last_written; + int warnings; +}; + + +#ifdef Xorriso_check_sparsE + +static int Xorriso_sparse_warn(struct XorrisO *xorriso, + struct Xorriso_sparse_statE *sparse_state, + int occasion, char *msg, int flag) +{ + if(sparse_state->warnings & (1 << occasion)) + return(1); + sparse_state->warnings|= 1 << occasion; + Xorriso_msgs_submit(xorriso, 0, msg, 0, "SORRY", 0); + return(1); +} + +#endif /* Xorriso_check_sparsE */ + + +static int Xorriso_sparse_init(struct XorrisO *xorriso, + struct Xorriso_sparse_statE **sparse_state, + int write_fd, int flag) +{ + struct Xorriso_sparse_statE *o= NULL; + off_t cur_pos; + struct stat stbuf; + int ret; + + *sparse_state= NULL; + + /* Check whether sparse writing is disabled */ + if(xorriso->sparse_min_gap <= 0) + {ret= 0; goto ex;} + + /* Analyze write_fd */ + ret= fstat(write_fd, &stbuf); + if(ret == -1) + {ret= 0; goto ex;} + if(!S_ISREG(stbuf.st_mode)) + {ret= 0; goto ex;} + cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR); + if(cur_pos < stbuf.st_size) + {ret= 0; goto ex;} + + Xorriso_alloc_meM(o, struct Xorriso_sparse_statE, 1); + + /* Initialize sparse_state */ + o->use_lseek= 1; + o->cur_pos= o->after_last_written= cur_pos; + o->warnings= 0; + + ret= 1; +ex:; + if(ret >= 1) + *sparse_state= o; + else + Xorriso_free_meM(o); + return(ret); +} + + +static int Xorriso_sparse_zeroize(struct XorrisO *xorriso, + struct Xorriso_sparse_statE *sparse_state, + int write_fd, off_t start, off_t count, + int flag) +{ + int ret, buf_size= 32 * 1024, buf_fill, wret; + off_t todo, seek_ret; + char *buf= NULL; + + if(count <= 0) + {ret= 2; goto ex;} + Xorriso_alloc_meM(buf, char, buf_size); + + seek_ret= lseek(write_fd, start, SEEK_SET); + if(seek_ret == -1) + {ret= -1; goto ex;} + sparse_state->cur_pos= seek_ret; + for(todo= count; todo > 0; ) { + if(buf_size < todo) + buf_fill= buf_size; + else + buf_fill= todo; + wret= write(write_fd, buf, buf_fill); + if(wret <= 0) + {ret= wret; goto ex;} + todo-= wret; + sparse_state->cur_pos+= wret; + } + ret= 1; +ex:; + Xorriso_free_meM(buf); + return(ret); +} + + +/* @param flag bit0= this is the last buffer of the stream +*/ +static int Xorriso_sparse_write(struct XorrisO *xorriso, + struct Xorriso_sparse_statE *sparse_state, + int write_fd, char *buf, int count, + int flag) +{ + int wret, i, ret; + off_t cur_pos= -1, seek_ret; + static char zero[32]= {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; + + if(sparse_state == NULL) + goto do_write; + if(!sparse_state->use_lseek) + goto do_write; + if(flag & 1) + goto do_write; + +#ifdef Xorriso_check_sparsE + + cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR); + if(cur_pos == -1) + goto do_write; + if(cur_pos != sparse_state->cur_pos) { + Xorriso_sparse_warn(xorriso, sparse_state, 0, + "cur_pos deviation in Xorriso_sparse_write:intro", 0); + sparse_state->cur_pos= cur_pos; + } + +#else + + cur_pos= sparse_state->cur_pos; + +#endif + + /* Check for all zeros */ + if(count % 32) + goto do_write; + for(i= 0; i < count; i+= 32) + if(memcmp(buf + i, zero, 32)) + break; + if(i < count) + goto do_write; + + /* Omit write() until next non-zero buffer or end of writing */ + +#ifdef Xorriso_check_sparsE + + /* Only for debugging: Do real lseek() instead of write() */ + seek_ret= lseek(write_fd, cur_pos + count, SEEK_SET); + if(seek_ret == -1) + return(-1); + +#endif + + sparse_state->cur_pos= cur_pos + count; + return(count); + +do_write: + if(sparse_state != NULL) { + /* Check whether the gap since after_last_written is too small. + If so: fill the whole gap by writing zeros. + */ + if(sparse_state->after_last_written < cur_pos) { + if(xorriso->sparse_min_gap > cur_pos - sparse_state->after_last_written) { + ret= Xorriso_sparse_zeroize(xorriso, sparse_state, write_fd, + sparse_state->after_last_written, + cur_pos - sparse_state->after_last_written, 0); + if(ret < 0) + return(ret); + if(ret == 0) { + seek_ret= lseek(write_fd, cur_pos, SEEK_SET); + if(seek_ret == -1) + return(-1); + sparse_state->cur_pos= seek_ret; + } + } + } + } + + + if(sparse_state != NULL) { + +#ifdef Xorriso_check_sparsE + + cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR); + if(cur_pos != sparse_state->cur_pos) { + Xorriso_sparse_warn(xorriso, sparse_state, 1, + "cur_pos deviation in Xorriso_sparse_write:do_write", 0); + sparse_state->cur_pos= cur_pos; + } + +#else + + /* lseek() has been delayed until now */ + if(sparse_state->after_last_written != sparse_state->cur_pos) { + seek_ret= lseek(write_fd, sparse_state->cur_pos, SEEK_SET); + if(seek_ret == -1) + return(-1); + } + +#endif /* ! Xorriso_check_sparsE */ + + } + wret= write(write_fd, buf, count); + if(sparse_state != NULL && wret > 0 && cur_pos >= 0) + sparse_state->cur_pos= sparse_state->after_last_written= cur_pos + wret; + return(wret); +} + + +static int Xorriso_sparse_finish(struct XorrisO *xorriso, + struct Xorriso_sparse_statE **sparse_state, + int write_fd, int flag) +{ + int ret; + off_t cur_pos; + struct Xorriso_sparse_statE *o; + + if(sparse_state == NULL) + return(0); + o= *sparse_state; + if(o == NULL) + return(1); + if(write_fd == -1) + {ret= 1; goto ex;} + +#ifdef Xorriso_check_sparsE + + cur_pos= lseek(write_fd, (off_t) 0, SEEK_CUR); + if(cur_pos == -1) + {ret= -1; goto ex;} + if(cur_pos != o->cur_pos) { + Xorriso_sparse_warn(xorriso, o, 2, + "cur_pos deviation in Xorriso_sparse_finish", 0); + o->cur_pos= cur_pos; + } + +#else + + cur_pos= o->cur_pos; + +#endif /* ! Xorriso_check_sparsE */ + + if(o->after_last_written < cur_pos) { + /* Check whether the gap since after_last_written is too small. + If so: fill the whole gap by writing zeros, else: write a last zero byte. + */ + if(xorriso->sparse_min_gap > cur_pos - o->after_last_written) + ret= Xorriso_sparse_zeroize(xorriso, o, write_fd, o->after_last_written, + cur_pos - o->after_last_written, 0); + else + ret= Xorriso_sparse_zeroize(xorriso, o, write_fd, cur_pos - 1, (off_t) 1, + 0); + if(ret <= 0) + goto ex; + } + ret= 1; +ex:; + Xorriso_free_meM(o); + *sparse_state= NULL; + return(ret); +} + + /* @param flag bit0= Minimal transfer: access permissions only bit1= *_offset and bytes are valid for writing to regular file bit2= This is not a parameter. Do not report if ignored @@ -567,7 +839,8 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, off_t catsize; char disk_md5[16], iso_md5[16]; void *ctx= NULL; - int use_md5= 0, i; + int use_md5= 0, i, sparse_ret= 3; + struct Xorriso_sparse_statE *sparse_state= NULL; Xorriso_alloc_meM(buf, char, buf_size); Xorriso_alloc_meM(temp_path, char, SfileadrL); @@ -679,6 +952,9 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, goto cannot_restore; } } + if(ISO_NODE_IS_FILE(node)) + Xorriso_sparse_init(xorriso, &sparse_state, write_fd, 0); + while(todo>0) { wanted= buf_size; if(wanted>todo) @@ -731,7 +1007,11 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, ret= read_count - img_offset; } - wret= write(write_fd, buf_pt, ret); + if(sparse_state == NULL) + wret= write(write_fd, buf_pt, ret); + else + wret= Xorriso_sparse_write(xorriso, sparse_state, write_fd, buf_pt, ret, + 0); if(wret>=0) { todo-= wret; xorriso->pacifier_byte_count+= wret; @@ -774,8 +1054,11 @@ bad_md5:; } } } - if(write_fd != -1) + + if(write_fd != -1) { + sparse_ret= Xorriso_sparse_finish(xorriso, &sparse_state, write_fd, 0); close(write_fd); + } write_fd= -1; if(todo > 0 && xorriso->extract_error_mode == 2) { unlink(open_path_pt); @@ -798,6 +1081,12 @@ bad_md5:; } ret= -(todo > 0); l_errno= 0; + if(sparse_ret <= 0) { + strcpy(xorriso->info_text, "Could not finalize sparse extraction of "); + Text_shellsafe(disk_path, xorriso->info_text, 1 | 2); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, + sparse_ret < 0 ? errno : 0, "FAILURE", 0); + } } else if(LIBISO_ISLNK(node)) { what= "symbolic link"; @@ -898,6 +1187,8 @@ ex:; Xorriso_iso_file_close(xorriso, &data_stream, 0); if(ctx != NULL) Xorriso_md5_end(xorriso, &ctx, disk_md5, 0); + if(sparse_state != NULL) + Xorriso_sparse_finish(xorriso, &sparse_state, -1, 0); Xorriso_process_msg_queues(xorriso,0); return(ret); } diff --git a/xorriso/text_io.c b/xorriso/text_io.c index 19e75214..faccb96a 100644 --- a/xorriso/text_io.c +++ b/xorriso/text_io.c @@ -2990,18 +2990,29 @@ int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag) if(xorriso->allow_restore == -1) sprintf(line,"-osirrox %s\n", mode_pt); else - sprintf(line,"-osirrox %s:%s:%s:%s:%s:%s:%s\n", mode_pt, + sprintf(line,"-osirrox %s:%s:%s:%s:%s\n", mode_pt, xorriso->do_concat_split ? "concat_split_on" : "concat_split_off", xorriso->do_auto_chmod ? "auto_chmod_on" : "auto_chmod_off", xorriso->do_restore_sort_lba ? "sort_lba_on" : "sort_lba_off", - xorriso->drives_exclusive ? "o_excl_on" : "o_excl_off", + xorriso->drives_exclusive ? "o_excl_on" : "o_excl_off"); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + + is_default = ((xorriso->do_strict_acl & 1) == 0 && + (xorriso->do_md5 & (64 | 128)) == 0 && + xorriso->sparse_min_gap == 0); + sprintf(line,"-osirrox %s:%s:sparse=", (xorriso->do_strict_acl & 1) ? "strict_acl_on" : "strict_acl_off", (xorriso->do_md5 & 64) ? (xorriso->do_md5 & 128) ? "check_md5_force" : "check_md5_on" - : "check_md5_off" - ); + : "check_md5_off"); + if(xorriso->sparse_min_gap <= 0) + strcat(line, "off"); + else + Sfile_off_t_text(line + strlen(line), xorriso->sparse_min_gap, 0); + strcat(line, "\n"); if(!(is_default && no_defaults)) - Xorriso_status_result(xorriso,filter,fp,flag&2); + Xorriso_status_result(xorriso, filter, fp, flag & 2); is_default= (xorriso->mount_opts_flag == 0); sprintf(line,"-mount_opts %s\n", diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index 3819850d..75505c40 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -9,7 +9,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 "Version 1.5.3, Oct 27, 2020" +.TH XORRISO 1 "Version 1.5.3, Nov 02, 2020" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -5004,6 +5004,21 @@ MD5 of the copied content gets computed and compared with the recorded MD5. A mismatch causes an error message of severity SORRY. Option \fBcheck_md5_force\fR causes an error message if \-md5 is "on" but no MD5 is recorded for the data file. +.br +Option \fBsparse=\fR controls production of sparse files during +extraction of files from the ISO filesystem. +Default is \fBsparse=off\fR. +.br +A positive number like in \fBsparse=1m\fR sets the minimum requirement +for the length of a sequence of 0\-bytes which shall be represented by a gap. +This saves disk space if the disk filesystem supports sparse files. +A gap gets created by help of lseek(2) if a sequence of read buffers, which +contain only 0\-bytes, bears at least the minimum amount of bytes. Expect +read buffers to be in the size range of 32k or 64k. +.br +Command \-paste_in creates gaps only if the writing begins at or after the end +of the existing disk file. So the sequence of \-paste_in commands matters. +Command \-concat does not create sparse files. .TP \fB\-extract\fR iso_rr_path disk_path Copy the file objects at and underneath iso_rr_path to their corresponding diff --git a/xorriso/xorriso.info b/xorriso/xorriso.info index 6bc252f8..2f81836b 100644 --- a/xorriso/xorriso.info +++ b/xorriso/xorriso.info @@ -4221,6 +4221,20 @@ The directory permissions on disk have to allow rwx. compared with the recorded MD5. A mismatch causes an error message of severity SORRY. Option *check_md5_force* causes an error message if -md5 is "on" but no MD5 is recorded for the data file. + Option *sparse=* controls production of sparse files during + extraction of files from the ISO filesystem. Default is + *sparse=off*. + A positive number like in *sparse=1m* sets the minimum requirement + for the length of a sequence of 0-bytes which shall be represented + by a gap. This saves disk space if the disk filesystem supports + sparse files. A gap gets created by help of lseek(2) if a sequence + of read buffers, which contain only 0-bytes, bears at least the + minimum amount of bytes. Expect read buffers to be in the size + range of 32k or 64k. + Command -paste_in creates gaps only if the writing begins at or + after the end of the existing disk file. So the sequence of + -paste_in commands matters. Command -concat does not create sparse + files. -extract iso_rr_path disk_path Copy the file objects at and underneath iso_rr_path to their corresponding addresses at and underneath disk_path. This is the @@ -5519,14 +5533,14 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top * -compare_l reports ISO/disk differences: Navigate. (line 147) * -compare_r reports ISO/disk differences: Navigate. (line 143) * -compliance controls standard compliance: SetWrite. (line 62) -* -concat copies ISO file content: Restore. (line 125) +* -concat copies ISO file content: Restore. (line 139) * -copyright_file sets copyright file name: SetWrite. (line 245) -* -cpax copies files to disk: Restore. (line 107) +* -cpax copies files to disk: Restore. (line 121) * -cpr inserts like with cp -r: Insert. (line 164) -* -cpx copies files to disk: Restore. (line 96) +* -cpx copies files to disk: Restore. (line 110) * -cp_clone copies ISO directory tree: Insert. (line 196) -* -cp_rx copies file trees to disk: Restore. (line 110) -* -cp_rx copies file trees to disk <1>: Restore. (line 118) +* -cp_rx copies file trees to disk: Restore. (line 124) +* -cp_rx copies file trees to disk <1>: Restore. (line 132) * -cut_out inserts piece of data file: Insert. (line 139) * -data_cache_size adjusts read cache size: Loading. (line 353) * -dev acquires one drive for input and output: AqDrive. (line 12) @@ -5553,10 +5567,10 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top * -error_behavior controls error workarounds: Exception. (line 92) * -external_filter registers data filter: Filter. (line 20) * -external_filter unregisters data filter: Filter. (line 47) -* -extract copies file tree to disk: Restore. (line 69) -* -extract_cut copies file piece to disk: Restore. (line 87) -* -extract_l copies files to disk: Restore. (line 83) -* -extract_single copies file to disk: Restore. (line 80) +* -extract copies file tree to disk: Restore. (line 83) +* -extract_cut copies file piece to disk: Restore. (line 101) +* -extract_l copies files to disk: Restore. (line 97) +* -extract_single copies file to disk: Restore. (line 94) * -file_name_limit curbs length of file names: Loading. (line 267) * -file_size_limit limits data file size: SetInsert. (line 7) * -find traverses and alters ISO tree: CmdFind. (line 7) @@ -5610,7 +5624,7 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top * -md5 controls handling of MD5 sums: Loading. (line 184) * -mkdir creates ISO directory: Insert. (line 177) * -modesty_on_drive keep drive buffer hungry: SetWrite. (line 406) -* -mount issues mount command for ISO session: Restore. (line 153) +* -mount issues mount command for ISO session: Restore. (line 167) * -mount_cmd composes mount command line: Inquiry. (line 49) * -mount_cmd controls mount command: Inquiry. (line 65) * -msg_op perform operations on program messages: Frontend. (line 27) @@ -5630,7 +5644,7 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top * -pacifier controls pacifier text form: Emulation. (line 166) * -padding sets amount or mode of image padding: SetWrite. (line 494) * -page set terminal geometry: DialogCtl. (line 18) -* -paste_in copies file into disk file: Restore. (line 121) +* -paste_in copies file into disk file: Restore. (line 135) * -pathspecs sets meaning of = with -add: SetInsert. (line 115) * -path_list inserts paths from disk file: Insert. (line 81) * -pkt_output consolidates text output: Frontend. (line 7) @@ -5803,7 +5817,7 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top * Emulation, pacifier form, -pacifier: Emulation. (line 166) * Examples: Examples. (line 6) * extattr, _definition: Extras. (line 66) -* File content, copy, -concat: Restore. (line 125) +* File content, copy, -concat: Restore. (line 139) * File names, curb length, -file_name_limit: Loading. (line 267) * File names, if neither Rock Ridge nor Joliet: Loading. (line 229) * Filter, apply to file tree, -set_filter_r: Filter. (line 84) @@ -5966,22 +5980,22 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top * Relocation directory, set name, -rr_reloc_dir: SetWrite. (line 150) * Rename, in ISO image, -move: Manip. (line 31) * Rename, in ISO image, -mv: Manip. (line 37) -* Restore, copy file into disk file, -paste_in: Restore. (line 121) -* Restore, copy file piece to disk, -extract_cut: Restore. (line 87) -* Restore, copy file to disk, -extract_single: Restore. (line 80) -* Restore, copy file tree to disk, -extract: Restore. (line 69) -* Restore, copy file trees to disk, -cp_rx: Restore. (line 110) -* Restore, copy file trees to disk, -cp_rx <1>: Restore. (line 118) -* Restore, copy files to disk, -cpax: Restore. (line 107) -* Restore, copy files to disk, -cpx: Restore. (line 96) -* Restore, copy files to disk, -extract_l: Restore. (line 83) +* Restore, copy file into disk file, -paste_in: Restore. (line 135) +* Restore, copy file piece to disk, -extract_cut: Restore. (line 101) +* Restore, copy file to disk, -extract_single: Restore. (line 94) +* Restore, copy file tree to disk, -extract: Restore. (line 83) +* Restore, copy file trees to disk, -cp_rx: Restore. (line 124) +* Restore, copy file trees to disk, -cp_rx <1>: Restore. (line 132) +* Restore, copy files to disk, -cpax: Restore. (line 121) +* Restore, copy files to disk, -cpx: Restore. (line 110) +* Restore, copy files to disk, -extract_l: Restore. (line 97) * Restore, enable ISO-to-disk, -osirrox: Restore. (line 18) * Result layout, more shell-like, -sh_style_result: Scripting. (line 61) * Rock Ridge, _definition: Extras. (line 6) * Session, altered start address, -displacement: Loading. (line 78) * Session, info string, -session_string: Inquiry. (line 74) -* Session, issue mount command, -mount: Restore. (line 153) +* Session, issue mount command, -mount: Restore. (line 167) * Session, log when written, -session_log: Scripting. (line 134) * Session, mount command line, -mount_cmd: Inquiry. (line 49) * Session, mount parameters, -mount_opts: Inquiry. (line 65) @@ -6066,32 +6080,32 @@ Node: Inquiry197292 Node: Navigate206174 Node: Verify214881 Node: Restore226030 -Node: Emulation235196 -Node: Scripting245652 -Node: Frontend253435 -Node: Examples263061 -Node: ExDevices264239 -Node: ExCreate264900 -Node: ExDialog266200 -Node: ExGrowing267471 -Node: ExModifying268280 -Node: ExBootable268790 -Node: ExCharset269345 -Node: ExPseudo270241 -Node: ExCdrecord271168 -Node: ExMkisofs271488 -Node: ExGrowisofs273385 -Node: ExException274538 -Node: ExTime274996 -Node: ExIncBackup275454 -Node: ExRestore279480 -Node: ExRecovery280426 -Node: Files280998 -Node: Environ282332 -Node: Seealso283080 -Node: Bugreport283797 -Node: Legal284388 -Node: CommandIdx285400 -Node: ConceptIdx303016 +Node: Emulation236013 +Node: Scripting246469 +Node: Frontend254252 +Node: Examples263878 +Node: ExDevices265056 +Node: ExCreate265717 +Node: ExDialog267017 +Node: ExGrowing268288 +Node: ExModifying269097 +Node: ExBootable269607 +Node: ExCharset270162 +Node: ExPseudo271058 +Node: ExCdrecord271985 +Node: ExMkisofs272305 +Node: ExGrowisofs274202 +Node: ExException275355 +Node: ExTime275813 +Node: ExIncBackup276271 +Node: ExRestore280297 +Node: ExRecovery281243 +Node: Files281815 +Node: Environ283149 +Node: Seealso283897 +Node: Bugreport284614 +Node: Legal285205 +Node: CommandIdx286217 +Node: ConceptIdx303833  End Tag Table diff --git a/xorriso/xorriso.texi b/xorriso/xorriso.texi index 8c17e6a1..e0ab533d 100644 --- a/xorriso/xorriso.texi +++ b/xorriso/xorriso.texi @@ -50,7 +50,7 @@ @c man .\" First parameter, NAME, should be all caps @c man .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection @c man .\" other parameters are allowed: see man(7), man(1) -@c man .TH XORRISO 1 "Version 1.5.3, Oct 27, 2020" +@c man .TH XORRISO 1 "Version 1.5.3, Nov 02, 2020" @c man .\" Please adjust this date whenever revising the manpage. @c man .\" @c man .\" Some roff macros, for reference: @@ -5739,6 +5739,21 @@ MD5 of the copied content gets computed and compared with the recorded MD5. A mismatch causes an error message of severity SORRY. Option @strong{check_md5_force} causes an error message if -md5 is "on" but no MD5 is recorded for the data file. +@* +Option @strong{sparse=} controls production of sparse files during +extraction of files from the ISO filesystem. +Default is @strong{sparse=off}. +@* +A positive number like in @strong{sparse=1m} sets the minimum requirement +for the length of a sequence of 0-bytes which shall be represented by a gap. +This saves disk space if the disk filesystem supports sparse files. +A gap gets created by help of lseek(2) if a sequence of read buffers, which +contain only 0-bytes, bears at least the minimum amount of bytes. Expect +read buffers to be in the size range of 32k or 64k. +@* +Command -paste_in creates gaps only if the writing begins at or after the end +of the existing disk file. So the sequence of -paste_in commands matters. +Command -concat does not create sparse files. @c man .TP @item -extract iso_rr_path disk_path @kindex -extract copies file tree to disk diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index 2951235d..554caa29 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -864,6 +864,9 @@ struct XorrisO { /* the global context of xorriso */ int show_hfs_cmd_count; char **show_hfs_cmds; + /* Extraction to sparse files */ + off_t sparse_min_gap; + /* result (stdout, R: ) */ char result_line[10*SfileadrL]; int result_line_counter; diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 146b0840..f5b54358 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2020.10.31.195038" +#define Xorriso_timestamP "2020.11.03.082729"