Enabled -hardlinks for options -extract, -extract_l and -cp*x

master
Thomas Schmitt 14 years ago
parent 5fcd3217f3
commit 5b13b266db
  1. 43
      xorriso/xorriso.1
  2. 434
      xorriso/xorriso.c
  3. 33
      xorriso/xorriso_private.h
  4. 2
      xorriso/xorriso_timestamp.h
  5. 676
      xorriso/xorrisoburn.c
  6. 11
      xorriso/xorrisoburn.h

@ -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 17, 2009"
.TH XORRISO 1 "May 26, 2009"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -69,7 +69,7 @@ Can check media for damages and copy readable blocks to disk.
.br
Scans for optical drives, blanks re-useable optical media.
.br
Reads its instructions from command line arguments, dialog, and batch files.
Reads its instructions from command line arguments, dialog, and files.
.br
Provides navigation commands for interactive ISO image manipulation.
.br
@ -127,9 +127,9 @@ Adding a session to an existing ISO image is in this text referred as
The multi-session model of the MMC standard does not apply to all media
types. But program growisofs by Andy Polyakov showed how to extend this
functionality to overwriteable media or disk files which carry valid ISO 9660
filesystems. This expansion method is referred as emulated growing.
filesystems.
.PP
xorriso provides both ways of growing as well as an own method named
xorriso provides growing as well as an own method named
\fBmodifying\fR which produces a completely new ISO image from the old
one and the modifications.
See paragraph Creating, Growing, Modifying, Blind Growing below.
@ -535,7 +535,6 @@ Set the image expansion method to growing.
.br
This is only allowed as long as no changes are pending in the currently
loaded ISO image. Eventually one has to perform -commit or -rollback first.
Violation yields a FAILURE event.
.br
Special address string "-" means standard output, to which several restrictions
apply. See above paragraph "Libburn drives".
@ -613,13 +612,12 @@ overall ISO image will not be mountable or will produce read errors when
accessing file content. xorriso will write the session to the address
as obtained from examining -outdev and not necessarily to predicted_nwa.
.br
During a run of blind growing, the input drive gets released before output
begins. The output drive gets released when writing is done.
During a run of blind growing, the input drive is given up before output
begins. The output drive is given up when writing is done.
.TP
\fB\-load\fR entity id
Load a particular (possibly outdated) ISO image from a -dev or -indev which
hosts more than one session. Usually all available sessions are shown with
option -toc.
Load a particular (possibly outdated) ISO image from -dev or -indev.
Usually all available sessions are shown with option -toc.
.br
entity depicts the kind of addressing. id depicts the particular
address. The following entities are defined:
@ -681,6 +679,14 @@ Mode "on" preserves eventual inode numbers from the loaded image.
When committing a session it searches for families of iso_rr files
which stem from the same disk file, have identical content and have
identical properties. The family members all get the same inode number.
Whether these numbers are respected at mount time depends on the operating
system.
.br
xorriso commands which extract files from an ISO image try to restore files
with the same inode number as hardlinks. This applies only to files which
get extracted during execution of that same command. A large number of
hardlink families may exhaust -temp_mem_limit if not -osirrox option
"sort_lba_on" is in effect.
.br
Mode "on" automatically enables \fB\-compliance new_rr\fR. This may be
overridden by a following -compliance old_rr . In this case the resulting
@ -702,10 +708,10 @@ See also options -getfattr, -setfattr and above paragraph about xattr.
.TP
\fB\-disk_dev_ino\fR "on"|"ino_only"|"off"
Enable or disable processing of recorded file identification numbers
(dev_t and ino_t). They are eventually stored as xattr "isofs.di" and allow
(dev_t and ino_t). They are eventually stored as xattr and allow
to substantially accelerate file comparison. The root node gets a global start
timestamp in "isofs.st". If during comparison a file with younger timestamps
is found in the ISO image, then it is suspected to have inconsistent content.
timestamp. If during comparison a file with younger timestamps is found in the
ISO image, then it is suspected to have inconsistent content.
.br
If device numbers and inode numbers of the disk filesystems are persistent
and if no irregular alterations of timestamps or system clock happen,
@ -2614,6 +2620,12 @@ Option "auto_chmod_off" is default. If "auto_chmod_on" is set then access
restrictions for disk directories get circumvented if those directories
are owned by the effective user who runs xorriso. This happens by temporarily
granting rwx permission to the owner.
.br
Option "sort_lba_on" may improve read performance with optical drives. It
allows to restore large numbers of hardlinks without exhausting
-temp_mem_limit. It does not preserve directory mtime and it needs
-osirrox option auto_chmod_on in order to extract directories which offer no
write permission. Default is "sort_lba_off".
.TP
\fB\-extract\fR iso_rr_path disk_path
Restore the file objects at and underneath iso_rr_path to their corresponding
@ -2891,7 +2903,8 @@ Mode "on" is
.TP
\fB\-temp_mem_limit\fR number["k"|"m"]
Set the maximum size of temporary memory to be used for image dependent
buffering. Currently this applies to pattern expansion only.
buffering. Currently this applies to pattern expansion, LBA sorting,
restoring of hardlinks.
.br
Default is 16m = 16 MiB, minimum 64k = 64 kiB, maximum 1024m = 1 GiB.
.TP
@ -3345,7 +3358,7 @@ on media and if the expected changes are much smaller than the full backup.
To apply zisofs compression to those data files which get newly copied from
the local filesystem, perform immediately before -commit :
.br
-find / -type f -lba_range -1 2000000000 -exec set_filter --zisofs --
-find / -type f -pending_data -exec set_filter --zisofs --
.br
Option -disk_dev_ino depends on stable device and inode numbers on disk.
Without it, an update run will probably save no time but last longer than

@ -10,7 +10,7 @@ or
-Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
-o xorriso/xorriso \
xorriso/xorriso.c xorriso/xorrisoburn.c \
-lpthread -lreadline -lburn -lisofs -lisoburn
-lz -lacl -lpthread -lreadline -lburn -lisofs -lisoburn
or
@ -2260,7 +2260,7 @@ failed:;
/*
@param flag Bitfield for control purposes
see
see Xorriso_lst_new_binary()
*/
int Xorriso_lst_new(struct Xorriso_lsT **lstring, char *text,
struct Xorriso_lsT *link, int flag)
@ -5240,7 +5240,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag)
m->add_plainly= 0;
m->split_size= 0;
strcpy(m->list_delimiter, "--");
m->ino_behavior= 3;
m->ino_behavior= 7;
m->do_joliet= 0;
m->do_aaip= 0;
m->relax_compliance= 0;
@ -5315,6 +5315,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag)
m->allow_restore= 0;
m->do_concat_split= 1;
m->do_auto_chmod= 0;
m->do_restore_sort_lba= 0;
m->dialog= 0;
m->bsl_interpretation= 0;
m->search_mode= 0;
@ -5391,12 +5392,18 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag)
m->node_counter= 0;
m->node_array_size= 0;
m->node_array= NULL;
m->node_targets= NULL;
m->node_targets_availmem= 0;
m->node_disk_prefixes= NULL;
m->node_img_prefixes= NULL;
m->perm_stack= NULL;
m->result_line[0]= 0;
m->result_line_counter= 0;
m->result_page_counter= 0;
m->result_open_line_len= 0;
m->info_text[0]= 0;
ret= Sfile_leafname(progname, leafname, 0);
@ -5457,16 +5464,6 @@ int Xorriso_destroy_re(struct XorrisO *m, int flag)
}
int Xorriso_destroy_node_array(struct XorrisO *xorriso, int flag)
{
if(xorriso->node_array != NULL)
free(xorriso->node_array);
xorriso->node_array= NULL;
xorriso->node_counter= xorriso->node_array_size= 0;
return(1);
}
/* @param flag bit0= global shutdown of libraries */
int Xorriso_destroy(struct XorrisO **xorriso, int flag)
{
@ -5485,8 +5482,7 @@ int Xorriso_destroy(struct XorrisO **xorriso, int flag)
Xorriso_lst_destroy_all(&(m->drive_blacklist), 0);
Xorriso_lst_destroy_all(&(m->drive_greylist), 0);
Xorriso_lst_destroy_all(&(m->drive_whitelist), 0);
if(m->node_array != NULL)
free(m->node_array);
Xorriso_destroy_node_array(m, 0);
Xorriso_detach_libraries(m, flag&1);
free((char *) m);
@ -7216,9 +7212,10 @@ 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\n", mode_pt,
sprintf(line,"-osirrox %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_auto_chmod ? "auto_chmod_on" : "auto_chmod_off",
xorriso->do_restore_sort_lba ? "sort_lba_on" : "sort_lba_off"
);
if(!(is_default && no_defaults))
@ -7596,11 +7593,9 @@ int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag)
if(!(is_default && no_defaults))
Xorriso_status_result(xorriso,filter,fp,flag&2);
is_default= ((xorriso->ino_behavior & (1 | 2)) == 3);
switch (xorriso->ino_behavior & 3) {
is_default= ((xorriso->ino_behavior & (1 | 2)) == 7);
switch (xorriso->ino_behavior & 7) {
case 0: form= "on";
break; case 1: form= "new_ino";
break; case 2: form= "no_hardlinks";
break; default: form= "off";
}
sprintf(line,"-hardlinks %s\n", form);
@ -8354,7 +8349,7 @@ int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter,
if(strncmp(iso_path, iso_prefix, strlen(iso_prefix))!=0)
return(-1);
if(strlen(disk_prefix)+strlen(iso_path)-strlen(iso_prefix)>=SfileadrL)
if(strlen(disk_prefix)+strlen(iso_path)-strlen(iso_prefix)+1>=SfileadrL)
return(-1);
if(iso_path[strlen(iso_prefix)]=='/')
strcpy(adrc, iso_path+strlen(iso_prefix)+1);
@ -10057,6 +10052,7 @@ ex:
bit3= this is for overwriting and not for plain removal
bit4= count deleted files in xorriso->pacifier_count
bit5= with bit0 only remove directory content, not the directory
bit6= permission to call Xorriso_make_accessible()
@return <=0 = error
1 = removed leaf file object
2 = removed directory or tree
@ -10064,10 +10060,13 @@ ex:
*/
int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag)
{
int ret, is_dir= 0;
int ret, is_dir= 0, made_accessible= 0;
struct stat victim_stbuf, *victim_node= NULL;
struct DirseQ *dirseq= NULL;
char *sfe= NULL, *sub_path= NULL;
struct PermiteM *perm_stack_mem;
perm_stack_mem= xorriso->perm_stack;
/* Avoiding large local memory objects in order to save stack space */
sfe= malloc(5*SfileadrL);
@ -10082,10 +10081,19 @@ int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag)
ret= lstat(path, &victim_stbuf);
if(ret==-1) {
sprintf(xorriso->info_text, "Cannot lstat(%s)",
Text_shellsafe(path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
{ret= 0; goto ex;}
if((flag & 64) && errno == EACCES) {
ret= Xorriso_make_accessible(xorriso, path, 0);
if(ret < 0)
goto ex;
made_accessible= 1;
ret= lstat(path, &victim_stbuf);
}
if(ret==-1) {
sprintf(xorriso->info_text, "Cannot lstat(%s)",
Text_shellsafe(path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
{ret= 0; goto ex;}
}
}
if(strcmp(path, "/")==0) {
sprintf(xorriso->info_text, "May not delete root directory");
@ -10199,16 +10207,30 @@ dir_not_removed:;
ret= rmdir(path);
else
ret= unlink(path);
if(ret==-1) {
sprintf(xorriso->info_text, "Cannot delete from disk filesystem %s",
Text_shellsafe(path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
ret= -1; goto ex;
if(ret == -1) {
if((flag & 64) && errno == EACCES && !made_accessible) {
ret= Xorriso_make_accessible(xorriso, path, 0);
if(ret < 0)
goto ex;
made_accessible= 1;
if(is_dir)
ret= rmdir(path);
else
ret= unlink(path);
}
if(ret == -1) {
sprintf(xorriso->info_text, "Cannot delete from disk filesystem %s",
Text_shellsafe(path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
ret= -1; goto ex;
}
}
if(flag&16)
xorriso->pacifier_count++;
ret= 1+!!is_dir;
ex:;
if(made_accessible)
Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
if(sfe!=NULL)
free(sfe);
if(sub_path!=NULL)
@ -11838,6 +11860,11 @@ int Xorriso_path_is_excluded(struct XorrisO *xorriso, char *path, int flag)
}
/* @param flag bit7= return 4 if restore fails from denied permission
do not issue error message
@return <=0 failure , 1 success ,
4 with bit7: permission to create file was denied
*/
int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path,
char *tmp_path, int *fd, int flag)
{
@ -11853,6 +11880,8 @@ int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path,
strcat(tmp_path, "_tmp_xorriso_restore_XXXXXX");
*fd= mkstemp(tmp_path);
if(*fd==-1) {
if(errno == EACCES && (flag & 128))
return(4);
strcpy(xorriso->info_text, "Cannot create temporary file : ");
Text_shellsafe(tmp_path, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
@ -11863,6 +11892,10 @@ int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path,
}
/* @param flag bit0= change regardless of xorriso->do_auto_chmod
bit1= desired is only rx
@return -1=severe error , -2= cannot chmod, 0= nothing to do, 1 = chmoded
*/
int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag)
{
int ret, is_link= 0;
@ -11870,9 +11903,11 @@ int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag)
mode_t mode, desired= S_IRUSR | S_IWUSR | S_IXUSR;
struct stat stbuf;
if(!xorriso->do_auto_chmod)
if(!(xorriso->do_auto_chmod || (flag & 1)))
return(0);
if(flag & 2)
desired &= ~S_IWUSR;
path_pt= disk_path;
ret= lstat(path_pt, &stbuf);
if(ret==-1)
@ -11891,10 +11926,10 @@ int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag)
return(ret);
path_pt= link_target;
}
if(stbuf.st_uid!=geteuid())
return(0);
if((stbuf.st_mode & desired) == desired)
return(0);
if(stbuf.st_uid!=geteuid())
return(-2);
mode= (stbuf.st_mode | desired) & 07777;
ret= chmod(path_pt, mode);
@ -11903,6 +11938,7 @@ int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag)
"Cannot change access permissions of disk directory: chmod %o %s",
(unsigned int) (mode & 07777), Text_shellsafe(path_pt, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0);
return(-2);
}
ret= Permstack_push(&(xorriso->perm_stack), path_pt, &stbuf, 0);
if(ret<=0)
@ -11911,6 +11947,106 @@ int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag)
}
int Xorriso_make_accessible(struct XorrisO *xorriso, char *disk_path, int flag)
{
int done= 0, ret, just_rx= 2;
char *npt, *apt, path[SfileadrL], *wpt;
apt= disk_path;
wpt= path;
for(npt= apt; !done; apt= npt + 1) {
npt= strchr(apt, '/');
if(npt == NULL)
break;
if(strchr(npt + 1, '/') == NULL)
just_rx= 0;
strncpy(wpt, apt, npt + 1 - apt);
wpt+= npt + 1 - apt;
*wpt= 0;
ret= Xorriso_auto_chmod(xorriso, path, just_rx);
if(ret == -1)
return(-1);
if(ret == -2)
return(0);
}
return(1);
}
/* @param flag bit0= prefer to find a match after *img_prefixes
(but deliver img_prefixes if no other can be found)
*/
int Xorriso_make_restore_path(struct XorrisO *xorriso,
struct Xorriso_lsT **img_prefixes, struct Xorriso_lsT **disk_prefixes,
char img_path[SfileadrL], char disk_path[SfileadrL], int flag)
{
int li;
struct Xorriso_lsT *s, *d, *found_s= NULL, *found_d= NULL;
char *ipfx, *dpfx;
/* Obtain disk_path by replacing start piece of img_path */
d= *disk_prefixes;
for(s= *img_prefixes; s != NULL;
s= Xorriso_lst_get_next(s, 0), d= Xorriso_lst_get_next(d, 0)) {
ipfx= Xorriso_lst_get_text(s, 0);
li= strlen(ipfx);
dpfx= Xorriso_lst_get_text(d, 0);
if(strncmp(img_path, ipfx, li) != 0)
continue;
if(img_path[li] != 0 && img_path[li] != '/')
continue;
if(strlen(dpfx) + strlen(img_path) - li + 1 >= SfileadrL)
return(-1);
if(img_path[li]=='/')
sprintf(disk_path, "%s/%s", dpfx, img_path + strlen(ipfx) + 1);
else
strcpy(disk_path, dpfx);
found_s= s;
found_d= d;
if(s != *img_prefixes || !(flag & 1))
break;
}
*img_prefixes= found_s;
*disk_prefixes= found_d;
return(found_s != NULL);
}
/* @param flag bit0=permission to run Xorriso_make_accessible
*/
int Xorriso_restore_make_hl(struct XorrisO *xorriso,
char *old_path, char *new_path, int flag)
{
int ret;
struct PermiteM *perm_stack_mem;
ret= link(old_path, new_path);
if(ret == 0)
return(1);
if(errno == EACCES && (flag & 1)) {
perm_stack_mem= xorriso->perm_stack;
ret= Xorriso_make_accessible(xorriso, new_path, 0);
if(ret > 0) {
ret= link(old_path, new_path);
if(ret == 0) {
Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
return(1);
}
}
Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
}
sprintf(xorriso->info_text, "Hardlinking failed: ");
Text_shellsafe(new_path, xorriso->info_text, 1);
strcat(xorriso->info_text, " -> ");
Text_shellsafe(old_path, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
return(0);
}
/* @param flag bit0= mark untested areas as valid
*/
int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso,
@ -12725,6 +12861,92 @@ ex:;
}
/* @param flag bit0= no hardlink reconstruction
bit1= do not set xorriso->node_*_prefixes
bit5= -extract_single: eventually do not insert directory tree
*/
int Xorriso_restore_sorted(struct XorrisO *xorriso, int count,
char **src_array, char **tgt_array, int flag)
{
int i, ret, with_node_array= 0, hflag= 0, hret;
if(xorriso->do_restore_sort_lba ||
!((xorriso->ino_behavior & 4) || (flag & 1))) {
/* Count affected nodes */
Xorriso_destroy_node_array(xorriso, 0);
for(i= 0; i < count; i++) {
if(src_array[i] == NULL || tgt_array[i] == NULL)
continue;
if(xorriso->do_restore_sort_lba) {
/* sort_lba : Make directories plus node_array and then
run array extractor (with eventual hardlink detection)
*/
hflag= (1 << 7) | ((!!(flag & 2)) << 9);
} else {
/* Hardlink detection: Have a sorted node_array with list of pathnames
for binary lookup in Xorriso_restore()
*/
hflag= 3 << 7;
}
ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
(off_t) 0, (off_t) 0, hflag);
if(ret <= 0) {
hret= Xorriso_eval_problem_status(xorriso, ret, 0);
if(ret < 0)
goto ex;
}
with_node_array= 1;
}
}
if(with_node_array) {
/* Allocate and fill node array */
if(xorriso->node_counter <= 0)
{ret= 2; goto ex;}
ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit,
!xorriso->do_restore_sort_lba);
if(ret<=0)
goto ex;
for(i= 0; i < count; i++) {
if(src_array[i] == NULL || tgt_array[i] == NULL)
continue;
ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
(off_t) 0, (off_t) 0, 2 << 7);
if(ret <= 0) {
hret= Xorriso_eval_problem_status(xorriso, ret, 0);
if(ret < 0)
goto ex;
}
}
}
/* Perform restore operations */
if(xorriso->do_restore_sort_lba) {
ret= Xorriso_restore_node_array(xorriso, 0);
if(ret <= 0)
goto ex;
} else {
if(with_node_array)
Xorriso_sort_node_array(xorriso, 0);
for(i= 0; i < count; i++) {
if(src_array[i] == NULL || tgt_array[i] == NULL)
continue;
ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
(off_t) 0, (off_t) 0, 0);
if(ret <= 0) {
hret= Xorriso_eval_problem_status(xorriso, ret, flag & 32);
if(ret < 0)
goto ex;
}
}
}
ret= 1;
ex:;
return(ret);
}
/* ---------------------------- Options API ------------------------ */
@ -14123,6 +14345,8 @@ int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv,
int i, ret, is_dir= 0, was_failure= 0, fret, end_idx_dummy;
char eff_origin[SfileadrL], eff_dest[SfileadrL];
char dest_dir[SfileadrL], leafname[SfileadrL], sfe[5*SfileadrL];
char **eff_src_array= NULL, **eff_tgt_array= NULL;
int optc= 0;
char **optv= NULL;
struct stat stbuf;
@ -14142,6 +14366,17 @@ int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv,
ret= 0; goto ex;
}
if(xorriso->do_restore_sort_lba || !(xorriso->ino_behavior & 4)) {
eff_src_array= calloc(optc, sizeof(char *));
eff_tgt_array= calloc(optc, sizeof(char *));
if(eff_src_array == NULL || eff_tgt_array == NULL) {
Xorriso_no_malloc_memory(xorriso, NULL, 0);
ret= -1; goto ex;
}
for(i= 0; i < optc; i++)
eff_src_array[i]= eff_tgt_array[i]= NULL;
}
/* Perform copying */
Xorriso_pacifier_reset(xorriso, 0);
for(i= 0; i<optc && !xorriso->request_to_abort; i++) {
@ -14181,16 +14416,25 @@ int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv,
goto problem_handler;
}
}
ret= Xorriso_restore(xorriso, eff_origin, eff_dest, (off_t) 0, (off_t) 0,
16 | ((!(flag&2))<<6));
if(ret<=0 || xorriso->request_to_abort)
goto problem_handler;
if(ret==3 || (flag&1))
if(eff_src_array != NULL) {
eff_src_array[i]= strdup(eff_origin);
eff_tgt_array[i]= strdup(eff_dest);
if(eff_src_array[i] == NULL || eff_tgt_array[i] == NULL) {
Xorriso_no_malloc_memory(xorriso, &(eff_src_array[i]), 0);
ret= -1; goto ex;
}
} else {
ret= Xorriso_restore(xorriso, eff_origin, eff_dest, (off_t) 0, (off_t) 0,
16 | ((!(flag&2))<<6));
if(ret<=0 || xorriso->request_to_abort)
goto problem_handler;
if(ret==3 || (flag&1))
continue;
sprintf(xorriso->info_text,
"Copied from ISO image to disk: %s '%s' = '%s'\n",
(ret>1 ? "directory" : "file"), eff_origin, eff_dest);
Xorriso_info(xorriso, 0);
sprintf(xorriso->info_text,
"Copied from ISO image to disk: %s '%s' = '%s'\n",
(ret>1 ? "directory" : "file"), eff_origin, eff_dest);
Xorriso_info(xorriso, 0);
}
continue; /* regular bottom of loop */
problem_handler:;
was_failure= 1;
@ -14199,11 +14443,21 @@ problem_handler:;
continue;
goto ex;
}
if(eff_src_array != NULL) {
ret= Xorriso_restore_sorted(xorriso, optc, eff_src_array, eff_tgt_array, 0);
if(ret <= 0)
was_failure= 1;
}
if(xorriso->pacifier_count>0)
Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count,
xorriso->pacifier_total, "", 1|4);
ret= !was_failure;
ex:;
i= optc;
Sfile_destroy_argv(&i, &eff_src_array, 0);
i= optc;
Sfile_destroy_argv(&i, &eff_tgt_array, 0);
Xorriso_opt_args(xorriso, "-cp*x",
argc, argv, *idx, &end_idx_dummy, &optc, &optv, 256);
return(ret);
@ -14643,19 +14897,20 @@ int Xorriso_option_external_filter(struct XorrisO *xorriso,
/* Options -extract , -extract_single */
/* @param flag bit0=do not report the restored item
bit1=do not reset pacifier, no final pacifier message
bit2= do not make lba-sorted node array for hardlink detection
bit5= -extract_single: eventually do not insert directory tree
*/
int Xorriso_option_extract(struct XorrisO *xorriso, char *iso_path,
char *disk_path, int flag)
{
int ret;
char eff_origin[SfileadrL], eff_dest[SfileadrL], *ipth;
char eff_origin[SfileadrL], eff_dest[SfileadrL], *ipth, *eopt[1], *edpt[1];
if(xorriso->allow_restore <= 0) {
sprintf(xorriso->info_text,
"-extract: image-to-disk copies are not enabled by option -osirrox");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
ret= 0; goto ex;
}
if(!(flag&2))
Xorriso_pacifier_reset(xorriso, 0);
@ -14666,29 +14921,36 @@ int Xorriso_option_extract(struct XorrisO *xorriso, char *iso_path,
if(disk_path[0]==0) {
sprintf(xorriso->info_text, "-extract: Empty disk_path given");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1);
return(0);
ret= 0; goto ex;
}
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_dest,
2|4);
if(ret<=0)
return(ret);
goto ex;
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, ipth, eff_origin, 2|8);
if(ret<=0)
return(ret);
ret= Xorriso_restore(xorriso, eff_origin, eff_dest,
(off_t) 0, (off_t) 0, (flag&32));
goto ex;
eopt[0]= eff_origin;
edpt[0]= eff_dest;
ret= Xorriso_restore_sorted(xorriso, 1, eopt, edpt, (flag & 32 ? 33 : 0));
if(!(flag&2))
Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count,
xorriso->pacifier_total, "", 1|4);
if(ret<=0)
return(ret);
goto ex;
if(!(flag&1)) {
sprintf(xorriso->info_text, "Extracted from ISO image: %s '%s'='%s'\n",
(ret>1 ? "directory" : "file"), eff_origin, eff_dest);
Xorriso_info(xorriso,0);
}
return(1);
ret= 1;
ex:;
if(!(flag & (4 | 32)))
Xorriso_destroy_node_array(xorriso, 0);
return(ret);
}
@ -15334,9 +15596,9 @@ int Xorriso_option_grow_blindly(struct XorrisO *xorriso, char *msc2, int flag)
int Xorriso_option_hardlinks(struct XorrisO *xorriso, char *mode, int flag)
{
if(strcmp(mode, "off")==0) {
xorriso->ino_behavior|= 1 | 2;
xorriso->ino_behavior|= 1 | 2 | 4;
} else if(strcmp(mode, "on")==0) {
xorriso->ino_behavior&= ~(1 | 2);
xorriso->ino_behavior&= ~(1 | 2 | 4);
} else {
sprintf(xorriso->info_text, "-hardlinks: unknown mode '%s'", mode);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
@ -15398,6 +15660,8 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag)
" Like -charset but only for conversion to media.",
" -local_charset name",
" Override system assumption of the local character set name.",
" -hardlinks \"on\"|\"off\"",
" Enable resp. disable recording and restoring of hardlinks.",
" -acl \"on\"|\"off\"",
" Enable resp. disable reading and writing of ACLs.",
" -xattr \"on\"|\"off\"",
@ -15719,7 +15983,8 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag)
"Restore options which copy file objects from ISO image to disk filesystem:",
" -osirrox \"on\"|\"device_files\"|\"off\"|\"banned\"",
" [:\"concat_split_on\"|\"concat_split_off\"]",
" [:\"auto_chmod__on\"|\"auto_chmod__off\"]",
" [:\"auto_chmod_on\"|\"auto_chmod_off\"]",
" [:\"sort_lba_on\"|\"sort_lba_off\"]",
" 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.",
@ -15728,7 +15993,7 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag)
" Copy tree under iso_rr_path onto disk address disk_path.",
" This avoids the pitfalls of cp -r addressing rules.",
" -extract_l iso_rr_prefix disk_prefix iso_rr_path [***]",
" Perform -extract_r with each iso_rr_path.",
" Perform -extract 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",
@ -16283,7 +16548,7 @@ int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv,
int ns_flag= 2|4, nt_flag= 2, opt_args_flag= 2;
char source_prefix[SfileadrL], target_prefix[SfileadrL], *cmd, **optv= NULL;
char eff_source[SfileadrL], eff_target[SfileadrL], *source_pt, *s_wd, *t_wd;
char sfe[5*SfileadrL];
char sfe[5*SfileadrL], **eff_src_array= NULL, **eff_tgt_array= NULL;
cmd= "-map_l";
s_wd= xorriso->wdx;
@ -16324,6 +16589,19 @@ int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv,
if(ret<=0)
goto ex;
if(mode == 3 &&
(xorriso->do_restore_sort_lba || !(xorriso->ino_behavior & 4))) {
eff_src_array= calloc(optc, sizeof(char *));
eff_tgt_array= calloc(optc, sizeof(char *));
if(eff_src_array == NULL || eff_tgt_array == NULL) {
Xorriso_no_malloc_memory(xorriso, NULL, 0);
ret= -1; goto ex;
}
for(i= 0; i < optc; i++)
eff_src_array[i]= eff_tgt_array[i]= NULL;
}
for(i= 0; i<optc; i++) {
ret= Xorriso_normalize_img_path(xorriso, s_wd, optv[i],
eff_source, ns_flag);
@ -16351,8 +16629,18 @@ int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv,
ret= Xorriso_option_compare(xorriso, eff_source, eff_target, 2|8);
else if(mode==2)
ret= Xorriso_option_update(xorriso, eff_source, eff_target, 2|8);
else if(mode==3)
ret= Xorriso_option_extract(xorriso, eff_source, eff_target, 2);
else if(mode==3) {
if(eff_src_array != NULL) {
eff_src_array[i]= strdup(eff_source);
eff_tgt_array[i]= strdup(eff_target);
if(eff_src_array[i] == NULL || eff_tgt_array[i] == NULL) {
Xorriso_no_malloc_memory(xorriso, &(eff_src_array[i]), 0);
ret= -1; goto ex;
}
} else {
ret= Xorriso_option_extract(xorriso, eff_source, eff_target, 2 | 4);
}
}
if(ret>0 && !xorriso->request_to_abort)
continue; /* regular bottom of loop */
@ -16362,6 +16650,19 @@ int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv,
continue;
goto ex;
}
ret= 1;
if(mode == 3 && eff_src_array != NULL) {
ret= Xorriso_lst_append_binary(&(xorriso->node_disk_prefixes),
target_prefix, strlen(target_prefix) + 1, 0);
if(ret <= 0)
goto ex;
ret= Xorriso_lst_append_binary(&(xorriso->node_img_prefixes),
source_prefix, strlen(source_prefix) + 1, 0);
if(ret <= 0)
goto ex;
ret= Xorriso_restore_sorted(xorriso, optc, eff_src_array, eff_tgt_array, 0);
}
if(mode==0)
Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count,
xorriso->pacifier_total, "", 1);
@ -16371,11 +16672,14 @@ int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv,
else if(mode==3)
Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count,
xorriso->pacifier_total, "", 1|4);
ret= 1;
ex:;
Xorriso_destroy_node_array(xorriso, 0);
i= optc;
Sfile_destroy_argv(&i, &eff_src_array, 0);
i= optc;
Sfile_destroy_argv(&i, &eff_tgt_array, 0);
(*idx)= end_idx;
Xorriso_opt_args(xorriso, cmd, argc, argv, *idx, &end_idx, &optc, &optv,
256);
Xorriso_opt_args(xorriso, cmd, argc, argv, *idx, &end_idx, &optc, &optv, 256);
if(ret<=0)
return(ret);
return(!was_failure);
@ -16853,6 +17157,10 @@ int Xorriso_option_osirrox(struct XorrisO *xorriso, char *mode, int flag)
xorriso->do_auto_chmod= 1;
else if(strncmp(cpt, "auto_chmod_off", l)==0)
xorriso->do_auto_chmod= 0;
else if(strncmp(cpt, "sort_lba_on", l)==0)
xorriso->do_restore_sort_lba= 1;
else if(strncmp(cpt, "sort_lba_off", l)==0)
xorriso->do_restore_sort_lba= 0;
else {
unknown_mode:;
sprintf(xorriso->info_text, "-osirrox: unknown mode '%s'", cpt);

@ -104,6 +104,8 @@ struct XorrisO { /* the global context of xorriso */
unique ones for all loaded IsoNode.
bit1= at image generation time:
Do not consolidate suitable nodes to hardlinks.
bit2= at restore-to-disk time:
Do not consolidate suitable nodes to hardlinks.
*/
int do_joliet;
@ -258,6 +260,10 @@ struct XorrisO { /* the global context of xorriso */
int do_auto_chmod; /* 1= eventually temporarily open access permissions
of self-owned directories during restore
*/
int do_restore_sort_lba; /* 1= restore via node_array rather than via
tree traversal. Better read performance,
no directory mtime restore, needs do_auto_chmod
*/
int dialog; /* 0=off , 1=single-line , 2=multi-line */
@ -386,6 +392,10 @@ struct XorrisO { /* the global context of xorriso */
int node_counter;
int node_array_size;
void **node_array;
char **node_targets; /* Memorizes eventual hardlink target paths */
off_t node_targets_availmem;
struct Xorriso_lsT *node_disk_prefixes;
struct Xorriso_lsT *node_img_prefixes;
struct PermiteM *perm_stack; /* Temporarily altered dir access permissions */
@ -541,6 +551,11 @@ int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd,
int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag);
/* @param flag bit7= return 4 if restore fails from denied permission
do not issue error message
@return <=0 failure , 1 success ,
4 with bit7: permission to create file was denied
*/
int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path,
char *tmp_path, int *fd, int flag);
@ -551,8 +566,24 @@ int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path,
int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag);
/* @param flag bit0= change regardless of xorriso->do_auto_chmod
bit1= desired is only rx
*/
int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag);
int Xorriso_make_accessible(struct XorrisO *xorriso, char *disk_path,int flag);
/* @param flag bit0= prefer to find a match after *img_prefixes
(but deliver img_prefixes if no other can be found)
*/
int Xorriso_make_restore_path(struct XorrisO *xorriso,
struct Xorriso_lsT **img_prefixes, struct Xorriso_lsT **disk_prefixes,
char img_path[SfileadrL], char disk_path[SfileadrL], int flag);
int Xorriso_restore_make_hl(struct XorrisO *xorriso,
char *old_path, char *new_path, int flag);
int Xorriso_protect_stdout(struct XorrisO *xorriso, int flag);
@ -609,8 +640,6 @@ int Xorriso_path_setfattr(struct XorrisO *xorriso, void *in_node, char *path,
int Xorriso_status_result(struct XorrisO *xorriso, char *filter, FILE *fp,
int flag);
int Xorriso_destroy_node_array(struct XorrisO *xorriso, int flag);
int Sfile_str(char target[SfileadrL], char *source, int flag);
double Sfile_microtime(int flag);

@ -1 +1 @@
#define Xorriso_timestamP "2009.05.17.115101"
#define Xorriso_timestamP "2009.05.26.140055"

@ -88,12 +88,17 @@ int Xorriso_read_file_data(struct XorrisO *xorriso, IsoNode *node,
off_t img_offset, off_t disk_offset,
off_t bytes, int flag);
int Xorriso_path_from_node(struct XorrisO *xorriso, IsoNode *in_node,
char path[SfileadrL], int flag);
int Xorriso_node_from_path(struct XorrisO *xorriso, IsoImage *volume,
char *path, IsoNode **node, int flag);
int Xorriso_path_from_lba(struct XorrisO *xorriso, IsoNode *node, int lba,
char path[SfileadrL], int flag);
int Xorriso__node_lba_cmp(const void *node1, const void *node2);
#define LIBISO_ISDIR(node) (iso_node_get_type(node) == LIBISO_DIR)
#define LIBISO_ISREG(node) (iso_node_get_type(node) == LIBISO_FILE)
@ -121,6 +126,139 @@ int Xorriso_path_from_lba(struct XorrisO *xorriso, IsoNode *node, int lba,
/* ------------------------------------------------------------------------ */
int Xorriso_destroy_node_array(struct XorrisO *xorriso, int flag)
{
int i;
if(xorriso->node_array != NULL) {
for(i= 0; i < xorriso->node_counter; i++)
iso_node_unref((IsoNode *) xorriso->node_array[i]);
free(xorriso->node_array);
}
if(xorriso->node_targets != NULL) {
for(i= 0; i < xorriso->node_counter; i++)
if(xorriso->node_targets[i] != NULL)
free(xorriso->node_targets[i]);
free(xorriso->node_targets);
}
xorriso->node_array= NULL;
xorriso->node_targets= NULL;
xorriso->node_targets_availmem= 0;
xorriso->node_counter= xorriso->node_array_size= 0;
Xorriso_lst_destroy_all(&(xorriso->node_disk_prefixes), 0);
Xorriso_lst_destroy_all(&(xorriso->node_img_prefixes), 0);
return(1);
}
/* @param flag bit0= allocate xorriso->node_targets too
*/
int Xorriso_new_node_array(struct XorrisO *xorriso, off_t mem_limit, int flag)
{
int i;
xorriso->node_array= calloc(xorriso->node_counter, sizeof(IsoNode *));
if(xorriso->node_array == NULL) {
Xorriso_no_malloc_memory(xorriso, NULL, 0);
return(-1);
}
for(i= 0; i < xorriso->node_counter; i++)
xorriso->node_array[i]= NULL;
if(flag & 1) {
xorriso->node_targets= calloc(xorriso->node_counter, sizeof(char *));
if(xorriso->node_array == NULL) {
free(xorriso->node_array);
xorriso->node_array= NULL;
Xorriso_no_malloc_memory(xorriso, NULL, 0);
return(-1);
}
for(i= 0; i < xorriso->node_counter; i++)
xorriso->node_targets[i]= NULL;
xorriso->node_targets_availmem= mem_limit
- xorriso->node_counter * sizeof(void *)
- xorriso->node_counter * sizeof(char *);
if(xorriso->node_targets_availmem < 0)
xorriso->node_targets_availmem= 0;
}
xorriso->node_array_size= xorriso->node_counter;
xorriso->node_counter= 0;
return(1);
}
int Xorriso__findi_sorted_ino_cmp(const void *p1, const void *p2)
{
int ret;
IsoNode *n1, *n2;
n1= *((IsoNode **) p1);
n2= *((IsoNode **) p2);
ret= Xorriso__node_lba_cmp(&n1, &n2);
if(ret)
return (ret > 0 ? 1 : -1);
ret= iso_node_cmp_ino(n1, n2, 0);
return(ret);
}
int Xorriso__findi_sorted_cmp(const void *p1, const void *p2)
{
int ret;
ret= Xorriso__findi_sorted_ino_cmp(p1, p2);
if(ret)
return (ret > 0 ? 1 : -1);
if(p1 != p2)
return(p1 < p2 ? -1 : 1);
return(0);
}
int Xorriso_sort_node_array(struct XorrisO *xorriso, int flag)
{
if(xorriso->node_counter <= 0)
return(0);
qsort(xorriso->node_array, xorriso->node_counter, sizeof(IsoNode *),
Xorriso__findi_sorted_cmp);
return(1);
}
int Xorriso_search_in_node_array(struct XorrisO *xorriso,
void *node, int *idx, int flag)
{
int ret, l, r, p, n;
if(xorriso->node_array_size <= 0 || xorriso->node_array == NULL)
return(0);
n= xorriso->node_counter;
if(n == 0)
return(0);
l= 0;
r= n + 1;
while(1) {
p= (r - l) / 2;
if(p == 0)
break;
p+= l;
ret= Xorriso__findi_sorted_ino_cmp(&(xorriso->node_array[p - 1]), &node);
if(ret < 0)
l= p;
else if(ret > 0)
r= p;
else {
*idx= p - 1;
return(1);
}
}
return(0);
}
/* ------------------------------------------------------------------------ */
@ -3187,8 +3325,11 @@ int Xorriso_is_plain_image_file(struct XorrisO *xorriso, IsoNode *node,
bit2= This is not a parameter. Do not report if ignored
bit3= do not restore properties
bit4= issue pacifier messages with long lasting copying
bit7= return 4 if restore fails from denied permission
do not issue error message
@return <0 severe error , 0 failure , 1 success ,
2 regularly not installed (disallowed device, UNIX domain socket)
4 with bit7: permission to restore was denied
*/
int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node,
char *img_path, off_t img_offset,
@ -3220,6 +3361,8 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node,
goto ex;
open_path_pt= disk_path;
ret= stat(open_path_pt, &stbuf);
if(ret == -1 && errno == EACCES && (flag & 128))
{ret= 4; goto ex;}
if(flag&2) {
if(ret!=-1 && !S_ISREG(stbuf.st_mode)) {
sprintf(xorriso->info_text,
@ -3244,8 +3387,9 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node,
}
if(ret==2) {
/* Extract to temporary file and rename only after copying */
ret= Xorriso_make_tmp_path(xorriso, disk_path, temp_path, &write_fd, 0);
if(ret<=0)
ret= Xorriso_make_tmp_path(xorriso, disk_path, temp_path, &write_fd,
128);
if(ret <= 0 || ret == 4)
goto ex;
open_path_pt= temp_path;
}
@ -3256,6 +3400,8 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node,
open_flags|= O_EXCL;
write_fd= open(open_path_pt, open_flags, S_IRUSR|S_IWUSR);
l_errno= errno;
if(write_fd == -1 && errno == EACCES && (flag & 128))
{ret= 4; goto ex;}
if(write_fd==-1)
goto cannot_restore;
}
@ -3422,6 +3568,8 @@ probably_damaged:;
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
ret= 0; goto ex;
}
if(ret == -1 && l_errno == EACCES && (flag & 128))
{ret= 4; goto ex;}
if(ret==-1) {
cannot_restore:;
sprintf(xorriso->info_text,
@ -3454,6 +3602,7 @@ ex:;
@param node intended source of overwriting or NULL
@param flag
bit4= return 3 on rejection by exclusion or user
bit6= permission to call Xorriso_make_accessible()
*/
int Xorriso_restore_overwrite(struct XorrisO *xorriso,
IsoNode *node, char *img_path,
@ -3474,7 +3623,7 @@ int Xorriso_restore_overwrite(struct XorrisO *xorriso,
if(ret>0) /* will be handled properly by restore functions */
ret= Xorriso_reassure_restore(xorriso, path, 8);
else
ret= Xorriso_rmx(xorriso, (off_t) 0, path, 8);
ret= Xorriso_rmx(xorriso, (off_t) 0, path, 8 | (flag & 64));
if(ret<=0)
return(ret);
if(ret==3) {
@ -3495,13 +3644,178 @@ int Xorriso_restore_overwrite(struct XorrisO *xorriso,
}
/* @param flag bit0= do not accept node_targets[i] != NULL as *node_idx
bit1= use *node_idx as found index rather than searching it
*/
int Xorriso_search_hardlinks(struct XorrisO *xorriso, IsoNode *node,
int *node_idx, int *min_hl, int *max_hl, int flag)
{
int idx, ret, i;
void *np;
*min_hl= *max_hl= -1;
np= node;
if(flag & 2) {
idx= *node_idx;
} else {
*node_idx= -1;