New option -extract_cut

This commit is contained in:
Thomas Schmitt 2008-09-02 16:48:59 +00:00
parent 33427c7bdb
commit 34a76c8eea
5 changed files with 270 additions and 14 deletions

View File

@ -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

View File

@ -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);

View File

@ -1 +1 @@
#define Xorriso_timestamP "2008.08.27.122127"
#define Xorriso_timestamP "2008.09.02.164803"

View File

@ -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);
}

View File

@ -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 */