From 34a76c8eeae89e042e5248a35a30b5d62dfc9ec2 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 2 Sep 2008 16:48:59 +0000 Subject: [PATCH] New option -extract_cut --- libisoburn/trunk/xorriso/xorriso.1 | 16 +- libisoburn/trunk/xorriso/xorriso.c | 55 ++++- libisoburn/trunk/xorriso/xorriso_timestamp.h | 2 +- libisoburn/trunk/xorriso/xorrisoburn.c | 206 ++++++++++++++++++- libisoburn/trunk/xorriso/xorrisoburn.h | 5 + 5 files changed, 270 insertions(+), 14 deletions(-) diff --git a/libisoburn/trunk/xorriso/xorriso.1 b/libisoburn/trunk/xorriso/xorriso.1 index 6e2aa32d..74e28693 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 "Aug 27, 2008" +.TH XORRISO 1 "Sep 02, 2008" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -1875,6 +1875,20 @@ restored. Performs -extract with each of the iso_rr_path arguments. disk_path will be composed from iso_rr_path by replacing iso_rr_prefix by disk_prefix. .TP +\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: +.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. +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. +.TP \fB\-cpx\fR iso_rr_path [***] disk_path Extract single leaf file objects from the ISO image and store them under the address given by disk_path. If more then one iso_rr_path is given then diff --git a/libisoburn/trunk/xorriso/xorriso.c b/libisoburn/trunk/xorriso/xorriso.c index 3ff5f433..8a2b8519 100644 --- a/libisoburn/trunk/xorriso/xorriso.c +++ b/libisoburn/trunk/xorriso/xorriso.c @@ -3227,6 +3227,8 @@ int Checkmediajob_new(struct CheckmediajoB **o, int flag) strcpy(m->abort_file_path, "/var/opt/xorriso/do_abort_check_media"); m->data_to_path[0]= 0; m->data_to_fd= -1; + m->data_to_offset= 0; + m->data_to_limit= -1; m->patch_lba0= 0; m->patch_lba0_msc1= -1; m->sector_map_path[0]= 0; @@ -10731,6 +10733,44 @@ int Xorriso_option_extract(struct XorrisO *xorriso, char *iso_path, } +/* Option -extract_cut */ +int Xorriso_option_extract_cut(struct XorrisO *xorriso, char *isorr_path, + char *start, char *count, char *disk_path, int flag) +{ + int ret; + double num; + off_t startbyte, bytecount; + + num= Scanf_io_size(start, 0); + if(num<0 || num > 1.0e18) { /* 10^18 = 10^3 ^ 6 < 2^10 ^ 6 = 2^60 */ + sprintf(xorriso->info_text, + "-extract_cut: startbyte address negative or much too large (%s)", + start); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + startbyte= num; + num= Scanf_io_size(count, 0); + if(num<=0 || num > 1.0e18) { + sprintf(xorriso->info_text, + "-extract_cut: bytecount zero, negative or much too large (%s)", + count); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + 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), + isorr_path); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + + ret= Xorriso_extract_cut(xorriso, isorr_path, disk_path, + startbyte, bytecount, 0); + return(ret); +} + + /* Option -file_size_limit */ int Xorriso_option_file_size_limit(struct XorrisO *xorriso, int argc, char **argv, int *idx, int flag) @@ -11399,6 +11439,8 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag) " Perform -extract_r with each iso_rr_path.", " -extract_single iso_rr_path disk_path", " Like -extract but with directory do not restore sub tree.", +" -extract_cut iso_rr_path byte_offset byte_count disk_path", +" Copy a byte interval from iso_rr_path to disk_path.", " -cpx iso_rr_path [***] disk_path", " Copy leaf file objects from ISO image to disk filesystem.", " -cpax iso_rr_path [***] disk_path", @@ -13469,7 +13511,7 @@ int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv, "" }; static char arg4_commands[][40]= { - "cut_out", "paste_in", + "cut_out","extract_cut","paste_in", "" }; static char argn_commands[][40]= { @@ -13761,6 +13803,17 @@ next_command:; (*idx)+= 2; ret= Xorriso_option_extract(xorriso, arg1, arg2, 0); + } else if(strcmp(cmd,"extract_cut")==0) { + (*idx)+= 4; + if((*idx)>argc) { + sprintf(xorriso->info_text, + "-extract_cut: Not enough arguments. Needed are: disk_path start count so_rr_path"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; + } else + ret= Xorriso_option_extract_cut(xorriso, arg1, arg2, + argv[(*idx)-2], argv[(*idx)-1], 0); + } else if(strcmp(cmd,"extract_l")==0) { ret= Xorriso_option_map_l(xorriso, argc, argv, idx, 3<<8); diff --git a/libisoburn/trunk/xorriso/xorriso_timestamp.h b/libisoburn/trunk/xorriso/xorriso_timestamp.h index a9d7656a..d02b9dd4 100644 --- a/libisoburn/trunk/xorriso/xorriso_timestamp.h +++ b/libisoburn/trunk/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.08.27.122127" +#define Xorriso_timestamP "2008.09.02.164803" diff --git a/libisoburn/trunk/xorriso/xorrisoburn.c b/libisoburn/trunk/xorriso/xorrisoburn.c index 84de0417..5cd31242 100644 --- a/libisoburn/trunk/xorriso/xorrisoburn.c +++ b/libisoburn/trunk/xorriso/xorrisoburn.c @@ -2398,8 +2398,10 @@ int Xorriso_restore_is_identical(struct XorrisO *xorriso, void *in_node, #ifdef Xorriso_libisofs_0_6_7 ret= Xorriso__file_start_lba(node, &dummy, 0); - if(ret != 0) + if(ret != 0) { + Xorriso_process_msg_queues(xorriso, 0); return(0); + } #else /* Xorriso_libisofs_0_6_7 */ @@ -2661,8 +2663,12 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, if(wanted>todo) wanted= todo; ret= Xorriso_iso_file_read(xorriso, data_stream, buf, wanted, 0); - if(ret<=0) + if(ret<=0) { + + /* >>> eventually call Xorriso_read_file_data() */; + break; + } wret= write(write_fd, buf, ret); if(wret>=0) { todo-= wret; @@ -3650,8 +3656,17 @@ int Xorriso_toc(struct XorrisO *xorriso, int flag) } if(flag&(1|4)) ret= 0; - else + else { ret= isoburn_read_iso_head(drive, lba, &image_blocks, volume_id, 1); + if(image_blocks > track_size) { + sprintf(xorriso->info_text, + "Session %d bears ISO image size %ds larger than track size %ds", + session_no + 1, image_blocks, track_size); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", + 0); + image_blocks= track_size; + } + } if(ret>0 && track_no==0) { sprintf(respt, "ISO session : %3d , %9d , %9ds , %s\n", session_no+1, lba, image_blocks , volume_id); @@ -4188,7 +4203,7 @@ int Xorriso__node_lba_cmp(const void *node1, const void *node2) int lba1= 0, lba2= 0; ret= Xorriso__file_start_lba(*((IsoNode **) node1), &lba1, 0); - if(ret!=1) + if(ret!=1) lba1= 0; ret= Xorriso__file_start_lba(*((IsoNode **) node2), &lba2, 0); if(ret!=1) @@ -5675,8 +5690,10 @@ int Xorriso_file_eval_damage(struct XorrisO *xorriso, IsoNode *node, ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas, &size, 0); - if(ret <= 0) + if(ret <= 0) { + Xorriso_process_msg_queues(xorriso, 0); return(ret); + } for(sect= 0; sect < lba_count; sect++) { for(i= start_lbas[sect]; i <= end_lbas[sect]; i+= sector_size) { if(Sectorbitmap_is_set(map, i / sector_size, 0) == 0) { @@ -5711,8 +5728,10 @@ int Xorriso_report_lba(struct XorrisO *xorriso, char *show_path, ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas, &size, 0); - if(ret < 0) + if(ret < 0) { + Xorriso_process_msg_queues(xorriso, 0); {ret= -1; goto ex;} + } if(ret == 0) {ret= 1; goto ex;} /* it is ok to ignore other types */ for(i= 0; i < lba_count; i++) { @@ -5964,8 +5983,10 @@ int Xorriso_findi_test(struct XorrisO *xorriso, struct FindjoB *job, if(start_lba >= 0 && end_lba >= 0) { ret= Xorriso__start_end_lbas(node, &lba_count, &file_start_lbas, &file_end_lbas, &size, 0); - if(ret <= 0) + if(ret <= 0) { + Xorriso_process_msg_queues(xorriso, 0); goto ex; + } for(i= 0; i < lba_count; i++) { if(file_end_lbas[i] < start_lba || file_start_lbas[i] > end_lba) {ret= 0; goto ex;} @@ -7132,7 +7153,7 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist, struct burn_drive *drive; struct burn_drive_info *dinfo; char data[64*1024], sfe[5*SfileadrL]; - off_t data_count, to_read; + off_t data_count, to_read, read_count= 0, write_amount; double pre_read_time, post_read_time, time_diff, total_time_diff= 0; double last_abort_file_time= 0; struct stat stbuf; @@ -7285,10 +7306,18 @@ abort_check:; if(time_diff > 1.0 && i > 0) quality= Xorriso_read_quality_sloW; } + + write_amount= data_count; if(data_count > 0) { + read_count+= data_count; + if(job->data_to_limit >= 0 && read_count > job->data_to_limit) + write_amount-= (read_count - job->data_to_limit); + } + if(write_amount > 0) { if(job->data_to_fd >= 0) { - ret= lseek(job->data_to_fd, ((off_t) (i + from_lba)) * (off_t) 2048, - SEEK_SET); + ret= lseek(job->data_to_fd, + ((off_t) (i + from_lba)) * (off_t) 2048 + job->data_to_offset, + SEEK_SET); if(ret == -1) { failed_to_write:; sprintf(xorriso->info_text, "Cannot write %d bytes to lba %d of %s", @@ -7298,7 +7327,7 @@ failed_to_write:; "FAILURE", 0); {ret= 0; goto ex;} } - ret= write(job->data_to_fd, data, data_count); + ret= write(job->data_to_fd, data, write_amount); if(ret == -1) goto failed_to_write; } @@ -7525,3 +7554,158 @@ ex:; burn_disc_free_multi_caps(&caps); return(ret); } + + +int Xorriso_read_file_data(struct XorrisO *xorriso, IsoNode *node, + char *img_path, char *disk_path, + off_t img_offset, off_t disk_offset, + off_t bytes, int flag) +{ + int ret, i, lba_count= 0, *start_lbas= NULL, *end_lbas= NULL, read_chunk= 16; + int lba, count; + off_t size= 0, file_base_bytes= 0, file_processed_bytes= 0, img_adr; + off_t new_file_base_bytes, upto_file_bytes; + char sfe[5*SfileadrL]; + struct SpotlisT *spotlist= NULL; + struct CheckmediajoB *job= NULL; + + upto_file_bytes= img_offset + bytes; + + /* >>> make Xorriso_check_interval() ready for copying in byte granularity */ + if(img_offset % (off_t) 2048) { + sprintf(xorriso->info_text, + "Image address offset is not a multiple of 2048"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + + ret= Xorriso__start_end_lbas(node, &lba_count, &start_lbas, &end_lbas, &size, + 0); + if(ret <= 0) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "File object %s is currently not a data file from the loaded image", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + goto ex; + } + if(img_offset + bytes < size && bytes > 0) + size= img_offset + bytes; + + ret= Checkmediajob_new(&job, 0); + if(ret <= 0) + goto ex; + ret= Spotlist_new(&spotlist, 0); + if(ret <= 0) + {ret= -1; goto ex;} + + /* do overall job programming: + >>> ??? time_limit, item_limit + >>> ??? abort_file_path + */ + if(Sfile_str(job->data_to_path, disk_path, 0) <= 0) + {ret= -1; goto ex;} + + Xorriso_open_job_data_to(xorriso, job, 0); + if(ret <= 0) + goto ex; + + for(i= 0; i < lba_count && file_base_bytes < upto_file_bytes; i++) { + lba= start_lbas[i]; + count= end_lbas[i] + 1 - start_lbas[i]; + new_file_base_bytes= file_base_bytes + ((off_t) count) * (off_t) 2048; + + /* skip intervals before img_offset */ + if(new_file_base_bytes <= img_offset) { + file_base_bytes= new_file_base_bytes; + continue; + } + /* Eventually adjust first interval start */ + img_adr= ((off_t) lba) * (off_t) 2048; + if(file_base_bytes < img_offset) { + img_adr+= img_offset - file_base_bytes; + lba= img_adr / (off_t) 2048; + count= end_lbas[i] + 1 - lba; + file_base_bytes= img_offset; + } + + /* Eventually omit surplus blocks */ + if(new_file_base_bytes > upto_file_bytes) + count-= (new_file_base_bytes - upto_file_bytes) / (off_t) 2048; + /* adjust job */ + job->data_to_offset= file_processed_bytes - img_adr + disk_offset; + job->data_to_limit= size - file_base_bytes; + + file_processed_bytes+= ((off_t) count) * (off_t) 2048; + ret= Xorriso_check_interval(xorriso, spotlist, job, lba, count, read_chunk, + 0); + if(ret <= 0) + goto ex; + if (ret == 2) { + sprintf(xorriso->info_text, "Attempt aborted to extract data from %s", + Text_shellsafe(img_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + file_base_bytes= new_file_base_bytes; + } + + /* >>> use spotlist to evaluate damage */; + + ret= 1; +ex:; + if(start_lbas != NULL) + free((char *) start_lbas); + if(end_lbas != NULL) + free((char *) end_lbas); + Spotlist_destroy(&spotlist, 0); + Checkmediajob_destroy(&job, 0); + return(ret); +} + + +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; + double mem_lut= 0.0; + char eff_img_path[SfileadrL], eff_disk_path[SfileadrL]; + IsoImage *volume; + IsoNode *node; + + ret= Xorriso_get_volume(xorriso, &volume, 0); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, + img_path, eff_img_path, 0); + if(ret<=0) + return(ret); + ret= Xorriso_node_from_path(xorriso, volume, eff_img_path, &node, 0); + if(ret<=0) + return(ret); + ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, + disk_path, eff_disk_path, 2 | 4); + if(ret<=0) + return(ret); + Xorriso_pacifier_reset(xorriso, 0); + mem_lut= xorriso->last_update_time; + + ret= Xorriso_handle_collision(xorriso, node, img_path, eff_disk_path, + 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); + ret= Xorriso_restore_properties(xorriso, eff_disk_path, node, 0); + if(ret<=0) + return(ret); + + if(mem_lut != xorriso->last_update_time) + Xorriso_pacifier_callback(xorriso, "sectors examined", + xorriso->pacifier_count, 0, "", 1); + return(1); +} + diff --git a/libisoburn/trunk/xorriso/xorrisoburn.h b/libisoburn/trunk/xorriso/xorrisoburn.h index 6d03261b..60fbfc55 100644 --- a/libisoburn/trunk/xorriso/xorrisoburn.h +++ b/libisoburn/trunk/xorriso/xorrisoburn.h @@ -310,6 +310,8 @@ struct CheckmediajoB { char data_to_path[SfileadrL]; int data_to_fd; + off_t data_to_offset; /* usually 0 with image copy, negative with file copy */ + off_t data_to_limit; /* used with file copy */ int patch_lba0; int patch_lba0_msc1; @@ -332,6 +334,9 @@ struct CheckmediajoB { int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, struct CheckmediajoB *job, int flag); +int Xorriso_extract_cut(struct XorrisO *xorriso, + char *img_path, char *disk_path, + off_t img_offset, off_t bytes, int flag); #endif /* Xorrisoburn_includeD */