From 4fdf92da424733c923dedeeb2ede089b3d7592af Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Thu, 14 May 2009 08:20:33 +0000 Subject: [PATCH] Enhanced option -extract_cut for handling filtered files --- libisoburn/trunk/xorriso/xorriso.1 | 25 ++--- libisoburn/trunk/xorriso/xorriso.c | 4 +- libisoburn/trunk/xorriso/xorriso_timestamp.h | 2 +- libisoburn/trunk/xorriso/xorrisoburn.c | 109 ++++++++++++++----- 4 files changed, 97 insertions(+), 43 deletions(-) diff --git a/libisoburn/trunk/xorriso/xorriso.1 b/libisoburn/trunk/xorriso/xorriso.1 index f3f74f7b..26405026 100644 --- a/libisoburn/trunk/xorriso/xorriso.1 +++ b/libisoburn/trunk/xorriso/xorriso.1 @@ -2,7 +2,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH XORRISO 1 "May 09, 2009" +.TH XORRISO 1 "May 14, 2009" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -1138,7 +1138,7 @@ Examples: .br /usr/bin/bzip2 -- .br - -external_filter bunzip2 suffix=.bz2:remove_suffix:if_nonempty \\ + -external_filter bunzip2 suffix=.bz2:remove_suffix \\ .br /usr/bin/bunzip2 -- .TP @@ -2131,7 +2131,8 @@ With occasion "file_extraction" there are three behaviors: .br "delete" removes files which encountered errors during content extraction. .br -"best_effort" starts a revovery attempt by means of -extract_cut. +"best_effort" starts a revovery attempt by means of -extract_cut if the +file content stems from the loaded ISO image and is not filtered. .TP .B Dialog mode control: .TP @@ -2633,17 +2634,15 @@ composed from iso_rr_path by replacing iso_rr_prefix by disk_prefix. \fB\-extract_cut\fR iso_rr_path byte_offset byte_count disk_path Copy a byte interval from a data file out of an ISO image into a newly created disk file. -Two restrictions apply: +The main purpose for this is to allow handling of large files if they +are not supported by mount -t iso9660 and if the reading system is unable +to buffer them as a whole. .br -The data bytes of iso_rr_path need to be already stored in the loaded ISO image -and byte_offset must be a multiple of 2048, e.g. an integer with suffix -s, m, or g. -.br -This option is implemented by a special run of -check_media and governed by -most of the options which can be set by -check_media_defaults. -Its main purpose is to allow handling of large files if they are not supported -by mount -t iso9660 and if the reading system is unable to buffer them as -a whole. +If the data bytes of iso_rr_path are stored in the loaded ISO image, +and no filter is applied, +and byte_offset is a multiple of 2048, then a special run of -check_media +is performed. It may be quicker and more rugged than the general reading +method. .TP \fB\-cpx\fR iso_rr_path [***] disk_path Extract single leaf file objects from the ISO image and store them under diff --git a/libisoburn/trunk/xorriso/xorriso.c b/libisoburn/trunk/xorriso/xorriso.c index e772a6e8..734b87e1 100644 --- a/libisoburn/trunk/xorriso/xorriso.c +++ b/libisoburn/trunk/xorriso/xorriso.c @@ -14693,8 +14693,8 @@ int Xorriso_option_extract_cut(struct XorrisO *xorriso, char *iso_rr_path, bytecount= num; sprintf(xorriso->info_text, "-extract_cut from %s , byte %.f to %.f, and store as %s", - disk_path, (double) startbyte, (double) (startbyte+bytecount), - iso_rr_path); + iso_rr_path, (double) startbyte, (double) (startbyte+bytecount), + disk_path); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); ret= Xorriso_extract_cut(xorriso, iso_rr_path, disk_path, diff --git a/libisoburn/trunk/xorriso/xorriso_timestamp.h b/libisoburn/trunk/xorriso/xorriso_timestamp.h index 7853e4bd..6e7abacc 100644 --- a/libisoburn/trunk/xorriso/xorriso_timestamp.h +++ b/libisoburn/trunk/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2009.05.09.201742" +#define Xorriso_timestamP "2009.05.14.082045" diff --git a/libisoburn/trunk/xorriso/xorrisoburn.c b/libisoburn/trunk/xorriso/xorrisoburn.c index cde24280..d767c96c 100644 --- a/libisoburn/trunk/xorriso/xorrisoburn.c +++ b/libisoburn/trunk/xorriso/xorrisoburn.c @@ -3159,8 +3159,25 @@ int Xorriso_restore_implicit_properties(struct XorrisO *xorriso, } +int Xorriso_is_plain_image_file(struct XorrisO *xorriso, IsoNode *node, + int flag) +{ + int ret, lba; + IsoStream *stream; + + ret= Xorriso__file_start_lba(node, &lba, 0); + if(ret > 0) { /* Stream source is from loaded image */ + stream= iso_file_get_stream((IsoFile *) node); + if(stream != NULL) + if(iso_stream_get_input_stream(stream, 0) == NULL) + return(1); + } + return(0); +} + + /* @param flag bit0= Minimal transfer: access permissions only - bit1= offset and bytes is valid for writing to regular file + bit1= *_offset and bytes are valid for writing to regular file bit2= This is not a parameter. Do not report if ignored bit3= do not restore properties bit4= issue pacifier messages with long lasting copying @@ -3168,15 +3185,16 @@ int Xorriso_restore_implicit_properties(struct XorrisO *xorriso, 2 regularly not installed (disallowed device, UNIX domain socket) */ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, - char *img_path, char *disk_path, - off_t offset, off_t bytes, int flag) + char *img_path, off_t img_offset, + char *disk_path, off_t disk_offset, off_t bytes, + int flag) { int ret= 0, write_fd= -1, wanted, wret, open_flags, l_errno= 0; int target_deleted= 0; char *what= "[unknown filetype]", sfe[5*SfileadrL], sfe2[5*SfileadrL]; - char buf[32*1024], type_text[5], temp_path[SfileadrL]; + char buf[32*1024], type_text[5], temp_path[SfileadrL], *buf_pt; char *link_target, *open_path_pt= NULL; - off_t todo= 0, size, seek_ret, last_p_count= 0, already_done; + off_t todo= 0, size, seek_ret, last_p_count= 0, already_done, read_count= 0; void *data_stream= NULL; mode_t mode; dev_t dev= 0; @@ -3228,7 +3246,7 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, } if(write_fd==-1) { open_flags= O_WRONLY|O_CREAT; - if(offset==0 || !(flag&2)) + if(disk_offset==0 || !(flag&2)) open_flags|= O_EXCL; write_fd= open(open_path_pt, open_flags, S_IRUSR|S_IWUSR); l_errno= errno; @@ -3239,12 +3257,12 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, if(flag&2) { if(bytesinfo_text, "Cannot address byte %.f in filesystem path %s", - (double) offset, Text_shellsafe(open_path_pt, sfe, 0)); + (double) disk_offset, Text_shellsafe(open_path_pt, sfe, 0)); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); goto cannot_restore; } @@ -3255,7 +3273,8 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, wanted= todo; ret= Xorriso_iso_file_read(xorriso, data_stream, buf, wanted, 0); if(ret<=0) { - if(xorriso->extract_error_mode == 0) { + if(xorriso->extract_error_mode == 0 && + Xorriso_is_plain_image_file(xorriso, node, 0)) { close(write_fd); write_fd= -1; already_done= (size - todo) / (off_t) 2048; @@ -3280,7 +3299,18 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, } break; } - wret= write(write_fd, buf, ret); + read_count+= ret; + buf_pt= buf; + + if(img_offset > read_count - ret) { + /* skip the desired amount of bytes */ + if(read_count <= img_offset) + continue; + buf_pt= buf + (img_offset - (read_count - ret)); + ret= read_count - img_offset; + } + + wret= write(write_fd, buf_pt, ret); if(wret>=0) { todo-= wret; xorriso->pacifier_byte_count+= wret; @@ -3509,8 +3539,8 @@ int Xorriso_restore_disk_object(struct XorrisO *xorriso, first_part_node= part_node; if(offset+bytes>total_bytes) bytes= total_bytes-offset; - ret= Xorriso_tree_restore_node(xorriso, part_node, part_path, disk_path, - offset, bytes, + ret= Xorriso_tree_restore_node(xorriso, part_node, part_path, (off_t) 0, + disk_path, offset, bytes, (!!(flag&64)) | 2 | (flag&4) | 8 | ( 16 * !(flag&2))); if(ret<=0) goto restoring_failed; @@ -3534,8 +3564,8 @@ int Xorriso_restore_disk_object(struct XorrisO *xorriso, img_path_pt= img_path; - ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, disk_path, - offset, bytes, + ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, (off_t) 0, + disk_path, offset, bytes, (flag&(4|8)) | (!!(flag&64)) | ((flag&1)<<1) | ( 16 * !(flag&2))); if(ret>0 && (flag&8)) ret= Xorriso_restore_properties(xorriso, disk_path, node, 2 | !!(flag&64)); @@ -7848,6 +7878,12 @@ int Xorriso_iso_file_open(struct XorrisO *xorriso, char *pathname, Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } + if(!iso_stream_is_repeatable(iso_stream)) { + sprintf(xorriso->info_text, + "The data production of the file in the image is one-time only"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } ret= iso_stream_open(iso_stream); if(ret<0) { sprintf(xorriso->info_text, @@ -7855,13 +7891,6 @@ int Xorriso_iso_file_open(struct XorrisO *xorriso, char *pathname, Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } - if(!iso_stream_is_repeatable(iso_stream)) { - sprintf(xorriso->info_text, - "The data production of the file in the image is one-time only"); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); - iso_stream_close(iso_stream); - return(0); - } Xorriso_process_msg_queues(xorriso,0); *stream= iso_stream; @@ -8669,9 +8698,9 @@ int Xorriso_extract_cut(struct XorrisO *xorriso, char *img_path, char *disk_path, off_t img_offset, off_t bytes, int flag) { - int ret, stbuf_ret; + int ret, stbuf_ret, read_raw; double mem_lut= 0.0; - char eff_img_path[SfileadrL], eff_disk_path[SfileadrL]; + char eff_img_path[SfileadrL], eff_disk_path[SfileadrL], sfe[SfileadrL*5]; IsoImage *volume; IsoNode *node; @@ -8696,10 +8725,36 @@ int Xorriso_extract_cut(struct XorrisO *xorriso, disk_path, &stbuf_ret, 0); if(ret<=0 || ret==3) return(0); - ret= Xorriso_read_file_data(xorriso, node, eff_img_path, eff_disk_path, - img_offset, (off_t) 0, bytes, 0); - if(ret<=0) - return(ret); + + /* If it is a non-filtered stream from the ISO image + and img_offset is a multiple of 2048 + then use Xorriso_read_file_data() for random access offset. + */ + if(!LIBISO_ISREG(node)) { + Xorriso_msgs_submit(xorriso, 0, eff_disk_path, 0, "ERRFILE", 0); + sprintf(xorriso->info_text, "-extract_cut: ISO file %s is not a data file", + Text_shellsafe(eff_img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + read_raw= 0; + if((img_offset % 2048) == 0) { + ret= Xorriso_is_plain_image_file(xorriso, node, 0); + if(ret > 0) + read_raw= 1; + } + if (read_raw) { + ret= Xorriso_read_file_data(xorriso, node, eff_img_path, eff_disk_path, + img_offset, (off_t) 0, bytes, 0); + if(ret<=0) + return(ret); + } else { + ret= Xorriso_tree_restore_node(xorriso, node, eff_img_path, img_offset, + eff_disk_path, (off_t) 0, bytes, 2 | 8); + if(ret<=0) + return(ret); + } + ret= Xorriso_restore_properties(xorriso, eff_disk_path, node, 0); if(ret<=0) return(ret);