With -update_r : detecting hardlink splits and fusions on disk

This commit is contained in:
Thomas Schmitt 2009-06-15 12:15:12 +00:00
parent b7bb047464
commit bf702dc38e
6 changed files with 634 additions and 52 deletions

View File

@ -668,30 +668,37 @@ terminal where xorriso runs. Before attributing this local character set
to the produced ISO image, check whether the terminal properly displays
all intended filenames, especially exotic national characters.
.TP
\fB\-hardlinks\fR "on"|"off"
\fB\-hardlinks\fR "on"|"off"|"without_update"|"start_update"|"end_update"
Enable or disable loading and recording of hardlink relations.
.br
In default mode "off", iso_rr files lose their inode numbers at image load
time. Each iso_rr file object which has no inode number at image generation
time will get a new unique inode number if -compliance is set to -new_rr.
time will get a new unique inode number if -compliance is set to new_rr.
.br
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
which stem from the same disk file, have identical content filtering 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 hard links. This applies only to files which
Commands -update and -update_r detect splits and fusions of hard links in
filesystems which have stable device and inode numbers.
Multiple -update_r commands should be surrounded by -hardlinks "start_update"
and -hardlinks "end_update". This avoids multiple sorting of ISO image nodes.
"start_update" implies "on".
Mode "without_update" avoids hardlink processing during update commands.
.br
xorriso commands which extract files from an ISO image try to hardlink files
with identical inode number. 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
image will violate the RRIP-1.10 specs for entry PX in the same way as
mkisofs does.
Hardlink processing automatically enables \fB\-compliance new_rr\fR.
This may be overridden by a following -compliance old_rr . In this case
the resulting image will violate the RRIP-1.10 specs for entry PX in
the same way as mkisofs does.
.TP
\fB\-acl\fR "on"|"off"
Enable or disable processing of ACLs.

View File

@ -5397,6 +5397,9 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag)
m->node_disk_prefixes= NULL;
m->node_img_prefixes= NULL;
m->di_count= 0;
m->di_array= NULL;
m->perm_stack= NULL;
m->result_line[0]= 0;
@ -5483,6 +5486,8 @@ int Xorriso_destroy(struct XorrisO **xorriso, int flag)
Xorriso_lst_destroy_all(&(m->drive_greylist), 0);
Xorriso_lst_destroy_all(&(m->drive_whitelist), 0);
Xorriso_destroy_node_array(m, 0);
Xorriso_destroy_di_array(m, 0);
Xorriso_detach_libraries(m, flag&1);
free((char *) m);
@ -7593,9 +7598,10 @@ 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 & 7) == 7);
switch (xorriso->ino_behavior & 7) {
is_default= ((xorriso->ino_behavior & 15) == 7);
switch (xorriso->ino_behavior & 15) {
case 0: form= "on";
break; case 8: form= "without_update";
break; default: form= "off";
}
sprintf(line,"-hardlinks %s\n", form);
@ -7969,6 +7975,8 @@ cannot_address:;
bit21= mismatch of recorded dev,inode
bit22= no recorded dev,inode found in node
bit23= timestamps younger than xorriso->isofs_st_in
bit24= hardlink split
bit25= hardlink fusion
@param flag bit0= compare atime
bit1= compare ctime
bit2= check only existence of both file objects
@ -8220,15 +8228,18 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr,
((flag & 2) && xorriso->isofs_st_in <= s2.st_ctime)))
(*result)|= 1 << 23;
if(xorriso->do_aaip & 32) {
/* dev,inode comparison. Eventually skip content comparison */
if((xorriso->do_aaip & 32) || !(xorriso->ino_behavior & 2)) {
/* dev,inode comparison.
For skipping content comparison or for hardlink detection.
*/
ret= Xorriso_record_dev_inode(xorriso, "", s1.st_dev, s1.st_ino, NULL,
iso_adr, 1 | 2 | ((flag & (1 << 28)) >> 23) | (xorriso->do_aaip & 128));
if(ret < 0) {
ret= -1; goto ex;
} else if(ret == 0) { /* match */
if((xorriso->do_aaip & 64) && S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)){
content_shortcut= 1;
if(xorriso->do_aaip & 32)
content_shortcut= 1;
if((*result) & (8 | 128 | 256 | 512 | 1024 | (1 << 23))) {
(*result)|= (1 << 15); /* content bytes differ */
if(((*result) & (1 << 23)) &&
@ -8260,8 +8271,10 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr,
sprintf(respt, "%s dev_ino : differing\n", a);
if(!(flag&(1<<31)))
Xorriso_result(xorriso,0);
if((xorriso->do_aaip & 64) && S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)){
content_shortcut= 1;
if(xorriso->do_aaip & 32)
content_shortcut= 1;
(*result)|= (1 << 15); /* content bytes differ */
sprintf(respt,
"%s content : assuming inequality after dev_ino mismatch\n", a);
@ -8319,7 +8332,7 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr,
if(was_error)
ret= -1;
else
ret= (((*result)&~((1<<17)|(1<<18)))==0);
ret= (((*result) & ~((1 << 17) | (1 << 18) | (1 << 23)))==0);
ex:;
if(split_parts!=NULL)
Splitparts_destroy(&split_parts, split_count, 0);
@ -11634,7 +11647,11 @@ int Xorriso_as_cdrskin(struct XorrisO *xorriso, int argc, char **argv,
/* @param boss_iter Opaque handle to be forwarded to actions in ISO image
Set to NULL if calling this function from outside ISO world
@param flag bit2= -follow: this is not a command parameter
@param flag bit0= widen hardlink sibling:
Do not call Xorriso_hardlink_update()
Overwrite exactly if normal mode would not,
else do nothing
bit2= -follow: this is not a command parameter
@return <=0 error, 1= ok , 2= iso_rr_path node object has been deleted ,
3= no action taken
*/
@ -11642,7 +11659,7 @@ int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter,
int compare_result, char *disk_path,
char *iso_rr_path, int flag)
{
int ret, deleted= 0, is_split= 0, i, loop_count;
int ret, deleted= 0, is_split= 0, i, loop_count, late_hardlink_update= 0;
char sfe[5*SfileadrL];
struct stat stbuf;
struct SplitparT *split_parts= NULL;
@ -11660,6 +11677,8 @@ int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter,
}
if(compare_result&((1<<11)|(1<<13))) {
if(flag & 1)
{ret= 3; goto ex;}
/* cannot open regular disk file, early eof of disk file */
sprintf(xorriso->info_text, "Problems with reading disk file %s",
Text_shellsafe(disk_path, sfe, 0));
@ -11670,8 +11689,26 @@ int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter,
xorriso->info_text[0]= 0;
is_split= !!(compare_result & (1<<17));
if((!(xorriso->ino_behavior & 2)) && (compare_result & (2 | (3 << 21))) &&
!(flag & 1)) {
if(compare_result & 2) {
/* File is not yet in image */
late_hardlink_update= 1;
} else {
/* Hard link relation has changed resp. was not recorded. */
ret= Xorriso_hardlink_update(xorriso, &compare_result,
disk_path, iso_rr_path, flag & 4);
if(ret < 0)
goto ex;
if(ret == 2)
{ret= 1; goto ex;}
}
}
if(compare_result&(8|64)) {
/* file type, minor+major with device file */
if(flag & 1)
{ret= 3; goto ex;}
ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1); /* rm_r */
if(ret>0) {
deleted= 1;
@ -11691,6 +11728,9 @@ delete:;
/* iso_adr not existing, size, cannot open iso file, early eof of iso file
content bytes differ */
if(flag & 1)
{ret= 3; goto ex;}
overwrite:;
if(is_split) {
ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL,
&split_parts, &split_count, &stbuf, 0);
@ -11755,12 +11795,25 @@ delete:;
if(ret>0 && !(compare_result&2))
deleted= 1;
}
sprintf(xorriso->info_text, "Added/overwrote ");
if(late_hardlink_update) {
/* Handle eventual hardlink siblings of newly created file */
ret= Xorriso_hardlink_update(xorriso, &compare_result,
disk_path, iso_rr_path, 1 | (flag & 4));
if(ret < 0)
goto ex;
}
if(flag & 1)
sprintf(xorriso->info_text, "Widened hard link ");
else
sprintf(xorriso->info_text, "Added/overwrote ");
} else if(compare_result&(4|16|32|256|512|1024|(1<<19)|(1<<20)|(1<<22))) {
/* access permissions, user id, group id, mtime, atime, ctime, ACL, xattr,
dev_ino missing */
if(flag & 1)
goto overwrite;
if(is_split) {
ret= Xorriso_identify_split(xorriso, iso_rr_path, NULL,
&split_parts, &split_count, &stbuf, 0);
@ -11789,6 +11842,8 @@ delete:;
ret= Xorriso_copy_properties(xorriso, disk_path, iso_rr_path, 4);
sprintf(xorriso->info_text, "Adjusted attributes of ");
} else if(flag & 1) {
goto overwrite;
} else
ret= 1;
if(ret>0 && xorriso->info_text[0]) {
@ -13134,7 +13189,7 @@ int Xorriso_option_alter_date(struct XorrisO *xorriso,
if(flag&1) {
ret= Findjob_new(&job, optv[i], 0);
if(ret<=0) {
Xorriso_no_findjob(xorriso, "-chmod_r", 0);
Xorriso_no_findjob(xorriso, "-alter_date", 0);
{ret= -1; goto ex;}
}
Findjob_set_action_ad(job, t_type, t, 0);
@ -15599,10 +15654,24 @@ int Xorriso_option_grow_blindly(struct XorrisO *xorriso, char *msc2, int flag)
/* Option -hardlinks "on"|"off" */
int Xorriso_option_hardlinks(struct XorrisO *xorriso, char *mode, int flag)
{
if(strcmp(mode, "off")==0) {
int ret;
if(strcmp(mode, "off") == 0) {
xorriso->ino_behavior|= 1 | 2 | 4;
} else if(strcmp(mode, "on")==0) {
xorriso->ino_behavior&= ~8;
} else if(strcmp(mode, "on") == 0) {
xorriso->ino_behavior&= ~(1 | 2 | 4 | 8);
} else if(strcmp(mode, "without_update") == 0) {
xorriso->ino_behavior&= ~(1 | 2 | 4);
xorriso->ino_behavior|= 8;
Xorriso_destroy_di_array(xorriso, 0);
} else if(strcmp(mode, "start_update") == 0) {
xorriso->ino_behavior&= ~(1 | 2 | 4 | 8);
ret= Xorriso_make_di_array(xorriso, 0);
if(ret <= 0)
return(ret);
} else if(strcmp(mode, "end_update") == 0) {
Xorriso_destroy_di_array(xorriso, 0);
} else {
sprintf(xorriso->info_text, "-hardlinks: unknown mode '%s'", mode);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
@ -15664,8 +15733,10 @@ 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 hard links.",
" -hardlinks \"on\"|\"off\"|\"start_update\"|\"end_update\"|\"without_update\"",
" Enable resp. disable recording and restoring of hard links,",
" or prepare for -update_r, or release prepared memory, or",
" disable hardlink detection with -update_r.",
" -acl \"on\"|\"off\"",
" Enable resp. disable reading and writing of ACLs.",
" -xattr \"on\"|\"off\"",
@ -16542,7 +16613,9 @@ int Xorriso_option_map(struct XorrisO *xorriso, char *disk_path,
/* Options -map_l , -compare_l , -update_l , -extract_l */
/* @param flag bit8-11= mode 0= -map_l
/* @param flag bit4= do not establish and dispose xorriso->di_array
for update_l
bit8-11= mode 0= -map_l
1= -compare_l
2= -update_l
3= -extract_l
@ -16551,7 +16624,7 @@ int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv,
int *idx, int flag)
{
int ret, end_idx, optc= 0, was_failure= 1, i, fret, mode;
int ns_flag= 2|4, nt_flag= 2, opt_args_flag= 2;
int ns_flag= 2|4, nt_flag= 2, opt_args_flag= 2, made_di_array= 0;
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], **eff_src_array= NULL, **eff_tgt_array= NULL;
@ -16607,6 +16680,14 @@ int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv,
for(i= 0; i < optc; i++)
eff_src_array[i]= eff_tgt_array[i]= NULL;
}
if(mode == 2 && !((xorriso->ino_behavior & 2) || (flag & 16) ||
xorriso->di_array != NULL)) {
/* Create all-image node array sorted by isofs.di */
ret= Xorriso_make_di_array(xorriso, 0);
if(ret <= 0)
goto ex;
made_di_array= 1;
}
for(i= 0; i<optc; i++) {
ret= Xorriso_normalize_img_path(xorriso, s_wd, optv[i],
@ -16634,7 +16715,7 @@ int Xorriso_option_map_l(struct XorrisO *xorriso, int argc, char **argv,
else if(mode==1)
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);
ret= Xorriso_option_update(xorriso, eff_source, eff_target, 2 | 8 | 16);
else if(mode==3) {
if(eff_src_array != NULL) {
eff_src_array[i]= strdup(eff_source);
@ -16685,6 +16766,8 @@ ex:;
i= optc;
Sfile_destroy_argv(&i, &eff_tgt_array, 0);
(*idx)= end_idx;
if(made_di_array)
Xorriso_destroy_di_array(xorriso, 0);
Xorriso_opt_args(xorriso, cmd, argc, argv, *idx, &end_idx, &optc, &optv, 256);
if(ret<=0)
return(ret);
@ -18425,12 +18508,13 @@ int Xorriso_option_uid(struct XorrisO *xorriso, char *uid, int flag)
bit1= do not reset pacifier, no final pacifier message
bit2= do not issue pacifier messages at all
bit3= recursive: -update_r
bit4= do not establish and dispose xorriso->di_array
*/
int Xorriso_option_update(struct XorrisO *xorriso, char *disk_path,
char *iso_path, int flag)
{
int ret, mem_pci, zero= 0, result, uret, follow_links;
int not_in_iso= 0, not_on_disk= 0;
int not_in_iso= 0, not_on_disk= 0, made_di_array= 0;
double mem_lut= 0.0, start_time;
char *ipth, *argv[6], sfe[5*SfileadrL];
char eff_origin[SfileadrL], eff_dest[SfileadrL];
@ -18475,6 +18559,16 @@ int Xorriso_option_update(struct XorrisO *xorriso, char *disk_path,
ret= 0;
if(ret!=0)
goto report_outcome;
if(!((xorriso->ino_behavior & 2) || (flag & 16) ||
xorriso->di_array != NULL)) {
/* Create all-image node array sorted by isofs.di */
made_di_array= 1;
ret= Xorriso_make_di_array(xorriso, 0);
if(ret <= 0)
goto ex;
}
if(flag&8) {
xorriso->find_compare_result= 1;
ret= Xorriso_iso_lstat(xorriso, eff_dest, &stbuf, 0);
@ -18560,7 +18654,13 @@ report_outcome:;
" (runtime %.1f s)\n", Sfile_microtime(0)-start_time);
if(flag&1)
Xorriso_info(xorriso,0);
if(ret<0)
ex:;
if(made_di_array) {
/* Dispose all-image node array sorted by isofs.di */
Xorriso_destroy_di_array(xorriso, 0);
}
if(ret < 0)
return(ret);
return(1);
}

View File

@ -106,6 +106,8 @@ struct XorrisO { /* the global context of xorriso */
Do not consolidate suitable nodes to hardlinks.
bit2= at restore-to-disk time:
Do not consolidate suitable nodes to hardlinks.
bit3= with update:
Do not try to detect hardlink splits and joinings.
*/
int do_joliet;
@ -389,6 +391,7 @@ struct XorrisO { /* the global context of xorriso */
int find_compare_result; /* 1=everything matches , 0=mismatch , -1=error */
/* LBA sorting and hardlink matching facility */
int node_counter;
int node_array_size;
void **node_array;
@ -397,6 +400,10 @@ struct XorrisO { /* the global context of xorriso */
struct Xorriso_lsT *node_disk_prefixes;
struct Xorriso_lsT *node_img_prefixes;
/* Array of all nodes in the tree, sorted by disk dev,ino */
int di_count;
void **di_array;
struct PermiteM *perm_stack; /* Temporarily altered dir access permissions */
/* result (stdout, R: ) */
@ -640,6 +647,10 @@ 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_compare_2_files(struct XorrisO *xorriso, char *disk_adr,
char *iso_adr, char *adr_common_tail,
int *result, int flag);
int Sfile_str(char target[SfileadrL], char *source, int flag);
double Sfile_microtime(int flag);
@ -990,6 +1001,10 @@ int Findjob_test_2(struct XorrisO *xorriso, struct FindjoB *o,
int Findjob_set_action_found_path(struct FindjoB *o, int flag);
/* @param flag bit0= recursive
*/
int Findjob_set_action_target(struct FindjoB *o, int action, char *target,
int flag);
int Findjob_get_action(struct FindjoB *o, int flag);
int Findjob_get_action_parms(struct FindjoB *o, char **target, char **text_2,

View File

@ -1 +1 @@
#define Xorriso_timestamP "2009.06.03.082041"
#define Xorriso_timestamP "2009.06.15.121525"

View File

@ -124,6 +124,10 @@ int Xorriso__node_lba_cmp(const void *node1, const void *node2);
isoburn_igopt_always_gmt | \
isoburn_igopt_rrip_version_1_10 | isoburn_igopt_aaip_susp_1_10 )
#ifdef NIX
/* <<< */
unsigned long Xorriso_get_di_counteR= 0;
#endif /* NIX */
/* ------------------------------------------------------------------------ */
@ -154,12 +158,39 @@ int Xorriso_destroy_node_array(struct XorrisO *xorriso, int flag)
}
int Xorriso_destroy_di_array(struct XorrisO *xorriso, int flag)
{
int i;
if(xorriso->di_array != NULL) {
for(i= 0; i < xorriso->di_count; i++)
if(xorriso->di_array[i] != NULL)
iso_node_unref((IsoNode *) xorriso->di_array[i]);
free(xorriso->di_array);
xorriso->di_array= NULL;
}
xorriso->di_count= 0;
#ifdef NIX
/* <<< */
fprintf(stderr, "xorriso_DEBUG: get_di_count= %lu\n",
Xorriso_get_di_counteR);
#endif /* NIX */
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;
if(xorriso->node_counter <= 0) {
Xorriso_destroy_node_array(xorriso, 0);
return(1);
}
xorriso->node_array= calloc(xorriso->node_counter, sizeof(IsoNode *));
if(xorriso->node_array == NULL) {
Xorriso_no_malloc_memory(xorriso, NULL, 0);
@ -228,14 +259,12 @@ int Xorriso_sort_node_array(struct XorrisO *xorriso, int flag)
}
int Xorriso_search_in_node_array(struct XorrisO *xorriso,
void *node, int *idx, int flag)
int Xorriso__search_node(void *node_array[], int n,
int (*cmp)(const void *p1, const void *p2),
void *node, int *idx, int flag)
{
int ret, l, r, p, n;
int ret, l, r, p, pos;
if(xorriso->node_array_size <= 0 || xorriso->node_array == NULL)
return(0);
n= xorriso->node_counter;
if(n == 0)
return(0);
l= 0;
@ -245,13 +274,24 @@ int Xorriso_search_in_node_array(struct XorrisO *xorriso,
if(p == 0)
break;
p+= l;
ret= Xorriso__findi_sorted_ino_cmp(&(xorriso->node_array[p - 1]), &node);
/* NULL elements may indicate invalid nodes. Their first valid right neigbor
will serve as proxy. If none exists, then the test pushes leftwards.
*/
for(pos= p - 1; pos < n; pos++)
if(node_array[pos] != NULL)
break;
if(pos < n)
ret= (*cmp)(&(node_array[pos]), &node);
else
ret= 1;
if(ret < 0)
l= p;
else if(ret > 0)
r= p;
else {
*idx= p - 1;
*idx= pos;
return(1);
}
}
@ -259,6 +299,139 @@ int Xorriso_search_in_node_array(struct XorrisO *xorriso,
}
int Xorriso_search_in_node_array(struct XorrisO *xorriso,
void *node, int *idx, int flag)
{
int ret;
if(xorriso->node_array_size <= 0 || xorriso->node_array == NULL)
return(0);
ret= Xorriso__search_node(xorriso->node_array, xorriso->node_counter,
Xorriso__findi_sorted_ino_cmp, node, idx, 0);
return ret;
}
int Xorriso__get_di(IsoNode *node, dev_t *dev, ino_t *ino, int flag)
{
int ret, i, i_end, imgid, error_code;
size_t value_length= 0;
char *value= NULL, msg[ISO_MSGS_MESSAGE_LEN], severity[80];
unsigned char *vpt;
static char *name= "isofs.di";
#ifdef NIX
/* <<< */
Xorriso_get_di_counteR++;
#endif /* NIX */
*dev= 0;
*ino= 0;
ret= iso_node_lookup_attr(node, name, &value_length, &value, 0);
if(ret <= 0) {
/* Drop any pending messages because there is no xorriso to take them */
iso_obtain_msgs("NEVER", &error_code, &imgid, msg, severity);
return(ret);
}
vpt= (unsigned char *) value;
for(i= 1; i <= vpt[0] && i < value_length; i++)
*dev= ((*dev) << 8) | vpt[i];
i_end= i + vpt[i] + 1;
for(i++; i < i_end && i < value_length; i++)
*ino= ((*ino) << 8) | vpt[i];
#ifdef NIX
/* <<< */
if(*ino > 10000000 || *ino < 0) {
fprintf(stderr,
"xorriso_DEBUG: name= '%s' , vl= %lu , i_end= %d\n",
iso_node_get_name(node), (unsigned long) value_length, i_end);
fprintf(stderr, " ");
for(i= 0; i < value_length; i++)
fprintf(stderr, " %-3.3u", (unsigned int) vpt[i]);
fprintf(stderr, "\n");
}
#endif
free(value);
return(1);
}
int Xorriso__di_ino_cmp(const void *p1, const void *p2)
{
int ret;
IsoNode *n1, *n2;
dev_t d1, d2;
ino_t i1, i2;
n1= *((IsoNode **) p1);
n2= *((IsoNode **) p2);
ret= Xorriso__get_di(n1, &d1, &i1, 0);
if(ret <= 0)
{d1= 0; i1= 0;}
ret= Xorriso__get_di(n2, &d2, &i2, 0);
if(ret <= 0)
{d2= 0; i2= 0;}
if(d1 < d2)
return(-1);
if(d1 > d2)
return(1);
if(i1 < i2)
return(-1);
if(i1 > i2)
return(1);
if(d1 == 0 && i1 == 0 && n1 != n2)
return(n1 < n2 ? -1 : 1);
return(0);
}
int Xorriso__di_cmp(const void *p1, const void *p2)
{
int ret;
IsoNode *n1, *n2;
ret= Xorriso__di_ino_cmp(p1, p2);
if(ret)
return(ret);
n1= *((IsoNode **) p1);
n2= *((IsoNode **) p2);
if(n1 != n2)
return(n1 < n2 ? -1 : 1);
return(0);
}
int Xorriso__sort_di(void *node_array[], int count, int flag)
{
if(count <= 0)
return(0);
qsort(node_array, count, sizeof(IsoNode *), Xorriso__di_cmp);
return(1);
}
int Xorriso_invalidate_di_item(struct XorrisO *xorriso, IsoNode *node,
int flag)
{
int ret, idx;
if(xorriso->di_array == NULL)
return(1);
ret= Xorriso__search_node(xorriso->di_array, xorriso->di_count,
Xorriso__di_cmp, node, &idx, 0);
if(ret <= 0)
return(ret == 0);
if(xorriso->di_array[idx] != NULL)
iso_node_unref(xorriso->di_array[idx]);
xorriso->di_array[idx]= NULL;
return(1);
}
/* ------------------------------------------------------------------------ */
@ -393,6 +566,7 @@ int Xorriso_detach_libraries(struct XorrisO *xorriso, int flag)
iso_image_unref((IsoImage *) xorriso->in_volset_handle);
xorriso->in_volset_handle= NULL;
Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
Xorriso_destroy_di_array(xorriso, 0);
}
if(flag&1) {
if(xorriso->libs_are_started==0)
@ -550,6 +724,7 @@ int Xorriso_create_empty_iso(struct XorrisO *xorriso, int flag)
iso_image_unref((IsoImage *) xorriso->in_volset_handle);
xorriso->in_volset_handle= NULL;
Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
Xorriso_destroy_di_array(xorriso, 0);
xorriso->loaded_volid[0]= 0;
xorriso->volset_change_pending= 0;
xorriso->no_volset_present= 0;
@ -728,7 +903,7 @@ int Xorriso_aquire_drive(struct XorrisO *xorriso, char *adr, int flag)
aquire_flag= 1 | ((flag&(8|4))>>1) | ((xorriso->toc_emulation_flag & 3)<<3);
if(!(xorriso->do_aaip & 1))
aquire_flag|= 32;
if(!(xorriso->do_aaip & 4))
if((xorriso->ino_behavior & (1 | 2)) && !(xorriso->do_aaip & (4 | 32)))
aquire_flag|= 64;
ret= isoburn_drive_aquire(&dinfo, libburn_adr, aquire_flag);
Xorriso_process_msg_queues(xorriso,0);
@ -827,6 +1002,7 @@ int Xorriso_aquire_drive(struct XorrisO *xorriso, char *adr, int flag)
iso_image_unref((IsoImage *) xorriso->in_volset_handle);
xorriso->in_volset_handle= NULL;
Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
Xorriso_destroy_di_array(xorriso, 0);
/* check for invalid state */
if(state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE &&
@ -842,7 +1018,7 @@ int Xorriso_aquire_drive(struct XorrisO *xorriso, char *adr, int flag)
goto ex;
ext= isoburn_ropt_noiso1999;
if(!(xorriso->do_aaip & (1 | 4 | 32)))
if((xorriso->ino_behavior & (1 | 2)) && !(xorriso->do_aaip & (1 | 4 | 32)))
ext|= isoburn_ropt_noaaip;
if(!(xorriso->do_aaip & 1))
ext|= isoburn_ropt_noacl;
@ -1017,6 +1193,7 @@ int Xorriso_give_up_drive(struct XorrisO *xorriso, int flag)
iso_image_unref((IsoImage *) xorriso->in_volset_handle);
xorriso->in_volset_handle= NULL;
Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
Xorriso_destroy_di_array(xorriso, 0);
xorriso->loaded_volid[0]= 0;
xorriso->isofs_st_out= time(0) - 1;
xorriso->isofs_st_in= 0;
@ -1490,7 +1667,7 @@ int Xorriso_write_session(struct XorrisO *xorriso, int flag)
}
}
if(xorriso->do_aaip & 16) {
if((xorriso->do_aaip & 16) || !(xorriso->ino_behavior & 2)) {
/* Overwrite isofs.st of root node by xorriso->isofs_st_out */
char *name= "isofs.st";
char timestamp[16], *value= timestamp;
@ -1506,7 +1683,8 @@ int Xorriso_write_session(struct XorrisO *xorriso, int flag)
ext= isoburn_igopt_rockridge |
((!!xorriso->do_joliet) * isoburn_igopt_joliet) |
(( !(xorriso->ino_behavior & 2)) * isoburn_igopt_hardlinks) |
((!!(xorriso->do_aaip & (2 | 8 | 16 | 256))) * isoburn_igopt_aaip);
(( (!(xorriso->ino_behavior & 2)) ||
(xorriso->do_aaip & (2 | 8 | 16 | 256))) * isoburn_igopt_aaip);
isoburn_igopt_set_extensions(sopts, ext);
isoburn_igopt_set_relaxed(sopts, relax);
isoburn_igopt_set_sort_files(sopts, 1);
@ -1965,6 +2143,11 @@ int Xorriso_node_from_path(struct XorrisO *xorriso, IsoImage *volume,
path_pt= path;
if(path[0]==0)
path_pt= "/";
if(volume == NULL) {
ret= Xorriso_get_volume(xorriso, &volume, 0);
if(ret <= 0)
return(ret);
}
*node= NULL;
ret= iso_tree_path_to_node(volume, path_pt, node);
Xorriso_process_msg_queues(xorriso,0);
@ -2295,7 +2478,7 @@ int Xorriso_transfer_properties(struct XorrisO *xorriso, struct stat *stbuf,
}
}
if((flag & 4) && (xorriso->do_aaip & 16)) {
if((flag & 4) && ((xorriso->do_aaip & 16) || !(xorriso->ino_behavior & 2))) {
ret= Xorriso_record_dev_inode(xorriso, disk_path, (dev_t) 0, (ino_t) 0,
(void *) node, "", flag & 32);
if(ret <= 0)
@ -2403,7 +2586,7 @@ int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume,
goto ex;
}
if(stbuf_valid && (xorriso->do_aaip & 16)) {
if(stbuf_valid && ((xorriso->do_aaip & 16) || !(xorriso->ino_behavior & 2))) {
ret= Xorriso_record_dev_inode(xorriso, disk_path,
stbuf.st_dev, stbuf.st_ino, (void *) *node, "", 1);
if(ret <= 0)
@ -2425,6 +2608,7 @@ ex:;
/* @param flag bit0= recursion is active
bit1= do not report added files
bit6= do not delete eventually existing node from di_array
*/
int Xorriso_add_tree(struct XorrisO *xorriso, IsoDir *dir,
char *img_dir_path, char *disk_dir_path,
@ -2586,7 +2770,8 @@ cannot_lstat:;
/* handle overwrite situation */;
if(xorriso->do_overwrite==1 ||
(xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) {
ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, img_path, 1|8);
ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, img_path,
1 | 8 | (flag & 64));
if(ret<=0)
goto was_problem;
if(ret==3) {
@ -2659,7 +2844,8 @@ cannot_lstat:;
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
} else {
ret= Xorriso_add_tree(xorriso, (IsoDir *) node,
img_path, disk_path, own_link_stack, 1|(flag&2));
img_path, disk_path, own_link_stack,
1 | (flag & (2 | 64)));
}
if(ret<=0)
goto was_problem;
@ -2781,6 +2967,7 @@ int Xorriso_copy_properties(struct XorrisO *xorriso,
bit3= use offset and cut_size for cut_out_node
bit4= return 3 on rejection by exclusion or user
bit5= if directory then do not add sub tree
bit6= do not delete eventually existing node from di_array
bit7= no special handling of split file directories
@return <=0 = error , 1 = added simple node , 2 = added directory ,
3 = rejected
@ -2911,7 +3098,8 @@ int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter,
/* handle overwrite situation */;
if(xorriso->do_overwrite==1 ||
(xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) {
ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, path, 1|8);
ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, path,
1 | 8 | (flag & 64));
if(ret<=0)
return(ret);
if(ret==3) {
@ -2968,7 +3156,7 @@ attach_source:;
(IsoNode *) dir, 4 | 32);
if(!(flag&32)) {
ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL,
flag&2);
flag & (2 | 64));
if(ret<=0)
return(ret);
}
@ -5728,6 +5916,7 @@ cannot_iter:;
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= do not delete eventually existing node from di_array
@return <=0 = error
1 = removed simple node
2 = removed directory or tree
@ -5828,7 +6017,8 @@ cannot_create_iter:;
if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0)
{ret= 0; goto rm_r_problem_handler;}
strcpy(sub_name, name);
ret= Xorriso_rmi(xorriso, iter, mem, sub_path, (flag&(1|2|8|16))|4);
ret= Xorriso_rmi(xorriso, iter, mem, sub_path,
(flag & ( 1 | 2 | 8 | 16 | 64)) | 4);
if(ret==3 || ret<=0 || xorriso->request_to_abort) {
rm_r_problem_handler:;
not_removed= 1;
@ -5925,6 +6115,9 @@ dir_not_removed:;
}
}
if(!(flag & 64))
Xorriso_invalidate_di_item(xorriso, victim_node, 0);
#ifdef Libisofs_iso_dir_iter_sufficienT
if(boss_iter!=NULL) {
@ -5950,6 +6143,7 @@ dir_not_removed:;
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
ret= -1; goto ex;
}
if(flag&16)
xorriso->pacifier_count++;
xorriso->volset_change_pending= 1;
@ -10185,14 +10379,16 @@ ex:;
int Xorriso_set_ignore_aclea(struct XorrisO *xorriso, int flag)
{
int ret;
int ret, hflag;
IsoImage *volume;
ret= Xorriso_get_volume(xorriso, &volume, 1);
if(ret<=0)
return(ret);
iso_image_set_ignore_aclea(volume,
((~xorriso->do_aaip) & 1) | (((~xorriso->do_aaip) & (4 | 16)) >> 1));
hflag= (~xorriso->do_aaip) & 1;
if((xorriso->ino_behavior & (1 | 2)) && !(xorriso->do_aaip & (4 | 16)))
hflag|= 2;
iso_image_set_ignore_aclea(volume, hflag);
return(1);
}
@ -11395,3 +11591,251 @@ int Xorriso_status_zisofs(struct XorrisO *xorriso, char *filter, FILE *fp,
return(1);
}
/* @param flag bit0= overwrite existing di_array (else return 2)
bit1= make di_array despite xorriso->ino_behavior bit 3
*/
int Xorriso_make_di_array(struct XorrisO *xorriso, int flag)
{
int ret;
struct FindjoB *job= NULL;
struct stat dir_stbuf;
#ifdef NIX
/* <<< */
unsigned long old_gdic;
old_gdic= Xorriso_get_di_counteR;
#endif /* NIX */
if((xorriso->ino_behavior & 8 ) && !(flag & 2))
return(2);
if(xorriso->di_array != NULL && !(flag & 1))
return(2);
Xorriso_destroy_di_array(xorriso, 0);
ret= Findjob_new(&job, "/", 0);
if(ret<=0) {
Xorriso_no_findjob(xorriso, "xorriso", 0);
{ret= -1; goto ex;}
}
Findjob_set_action_target(job, 30, NULL, 0);
Xorriso_destroy_node_array(xorriso, 0);
ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
&dir_stbuf, 0, 0);
if(ret <= 0)
goto ex;
ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit, 0);
if(ret <= 0)
goto ex;
Findjob_set_action_target(job, 31, NULL, 0);
ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
&dir_stbuf, 0, 0);
if(ret <= 0)
goto ex;
xorriso->di_count= xorriso->node_counter;
xorriso->di_array= xorriso->node_array;
xorriso->node_counter= 0;
xorriso->node_array_size= 0;
xorriso->node_array= 0;
Xorriso__sort_di((void *) xorriso->di_array, xorriso->di_count, 0);
ret= 1;
ex:;
#ifdef NIX
/* <<< */
fprintf(stderr, "xorriso_DEBUG: sort_count= %lu\n",
Xorriso_get_di_counteR - old_gdic);
#endif /* NIX */
Findjob_destroy(&job, 0);
return(ret);
}
/* @param flag bit0= return 1 even if matching nodes were found but node is
not among them
*/
int Xorriso_search_di_range(struct XorrisO *xorriso, IsoNode *node,
int *idx, int *low, int *high, int flag)
{
int ret, i, found;
*high= *low= *idx= -1;
ret= Xorriso__search_node(xorriso->di_array, xorriso->di_count,
Xorriso__di_ino_cmp, node, &found, 0);
if(ret <= 0)
return(0);
*low= *high= found;
for(i= found + 1; i < xorriso->di_count; i++)
if(xorriso->di_array[i] != NULL) {
if(Xorriso__di_ino_cmp(&node, &(xorriso->di_array[i])) != 0)
break;
*high= i;
}
for(i= found - 1; i >= 0; i--)
if(xorriso->di_array[i] != NULL) {
if(Xorriso__di_ino_cmp(&node, &(xorriso->di_array[i])) != 0)
break;
*low= i;
}
for(i= *low; i <= *high; i++)
if(xorriso->di_array[i] == node) {
*idx= i;
break;
}
return(*idx >= 0 || (flag & 1));
}
/*
@param flag bit0= iso_rr_path is freshly added and up to date
bit2= -follow: this is not a command parameter
@return -1= severe error
0= not applicable for hard links
1= go on with processing
2= iso_rr_path is fully updated
*/
int Xorriso_hardlink_update(struct XorrisO *xorriso, int *compare_result,
char *disk_path, char *iso_rr_path, int flag)
{
int ret, hret, idx, low, high, i, do_overwrite= 0, did_fake_di= 0;
int follow_links, node_result, old_idx= -1;
char node_path[SfileadrL];
IsoNode *node;
struct stat stbuf;
dev_t old_dev;
ino_t old_ino;
if(xorriso->di_array == NULL)
return(1);
follow_links= xorriso->do_follow_links ||
(xorriso->do_follow_param && !(flag & 4));
ret= Xorriso_node_from_path(xorriso, NULL, iso_rr_path, &node, 0);
if(ret <= 0)
return(ret);
if(LIBISO_ISDIR(node))
return(1);
/* Handle eventual hardlink split : */
/* This is achieved by setting the content change bit. Reason:
The node needs to be removed from di_array because its di is
not matching it array index any more. So it becomes invisible for
the join check of eventual later hardlink siblings. Therefore
it must be updated now, even if it has currently no siblings
which it leaves or which it joins.
*/
if(!(flag & 1))
do_overwrite= 1;
Xorriso__get_di(node, &old_dev, &old_ino, 0);
ret= Xorriso__search_node(xorriso->di_array, xorriso->di_count,
Xorriso__di_cmp, node, &idx, 0);
if(ret < 0)
{ret= 0; goto ex;}
if(ret > 0)
old_idx= idx;
/* Handle eventual hardlink joining : */
if(follow_links)
ret= stat(disk_path, &stbuf);
else
ret= lstat(disk_path, &stbuf);
if(ret==-1)
{ret= 0; goto ex;}
/* Are there new dev-ino-siblings in the image ? */
/* Fake isofs.di */
if(!(flag & 1)) {
ret= Xorriso_record_dev_inode(xorriso, disk_path, stbuf.st_dev,
stbuf.st_ino, node, iso_rr_path, 1);
if(ret <= 0)
{ret= -1; goto ex;}
did_fake_di= 1;
/* temporarily remove node from di_array so it does not disturb
search by its fake di info */;
if(old_idx >= 0)
xorriso->di_array[old_idx]= NULL;
}
ret= Xorriso_search_di_range(xorriso, node, &idx, &low, &high, 1);
if(did_fake_di) {
/* Revoke fake of isofs.di */
hret= Xorriso_record_dev_inode(xorriso, disk_path, old_dev, old_ino,
node, iso_rr_path, 1);
if(hret <= 0)
{ret= -1; goto ex;}
if(old_idx >= 0)
xorriso->di_array[old_idx]= node;
}
if(ret == 0)
{ret= 1; goto ex;}
if(ret < 0)
{ret= 0; goto ex;}
#ifdef NIX
/* <<< */
if(low < high || idx < 0) {
fprintf(stderr,
"xorriso_DEBUG: old_idx= %d , low= %d , high= %d , iso= '%s' , disk='%s'\n",
old_idx, low, high, iso_rr_path, disk_path);
fprintf(stderr,
"xorriso_DEBUG: old_dev= %lu , old_ino= %lu , dev= %lu , ino= %lu\n",
(unsigned long) old_dev, (unsigned long) old_ino,
(unsigned long) stbuf.st_dev, (unsigned long) stbuf.st_ino);
if(idx >= 0 && idx != old_idx)
fprintf(stderr, "xorriso_DEBUG: idx= %d , old_idx = %d\n", idx, old_idx);
}
#endif /* NIX */
/* Overwrite all valid siblings : */
for(i= low; i <= high; i++) {
if(i == idx || xorriso->di_array[i] == NULL)
continue;
/* Is the alleged sibling still a valid mirror of disk_path ? */
ret= Xorriso_path_from_node(xorriso, xorriso->di_array[i], node_path, 0);
if(ret < 0)
goto ex;
if(ret == 0)
continue; /* Node is deleted from tree */
#ifdef NIX
/* <<< */
{
ino_t ino;
dev_t dev;
Xorriso__get_di(xorriso->di_array[i], &dev, &ino, 0);
fprintf(stderr, "xorriso_DEBUG: iso_sibling= '%s' , dev= %lu , ino= %lu\n",
node_path, (unsigned long) dev, (unsigned long) ino);
}
#endif /* NIX */
node_result= 0;
ret= Xorriso_compare_2_files(xorriso, disk_path, node_path, "",
&node_result, 2 | follow_links | (7 << 29));
if(ret >= 0) {
/* Overwrite sibling if it would *not* be overwritten by itself.
(If it would be overwritten then it might be not a valid hardlink
sibling.) */
ret= Xorriso_update_interpreter(xorriso, NULL, node_result, disk_path,
node_path, 1 | 4);
if(ret < 0)
goto ex;
}
}
ret= 1;
ex:;
if(do_overwrite)
*compare_result|= (1<<15);
if(old_idx >= 0 && (*compare_result & (3 << 21))) {
/* The old di info is obsolete */
if(xorriso->di_array[old_idx] != NULL)
iso_node_unref(xorriso->di_array[old_idx]);
xorriso->di_array[old_idx]= NULL;
}
return(ret);
}

View File

@ -306,6 +306,8 @@ int Xorriso_set_local_charset(struct XorrisO *xorriso, char *name, int flag);
int Xorriso_destroy_node_array(struct XorrisO *xorriso, int flag);
int Xorriso_destroy_di_array(struct XorrisO *xorriso, int flag);
int Xorriso_new_node_array(struct XorrisO *xorriso, off_t mem_limit, int flag);
int Xorriso_sort_node_array(struct XorrisO *xorriso, int flag);
@ -458,6 +460,20 @@ int Xorriso_set_zisofs_params(struct XorrisO *xorriso, int flag);
int Xorriso_status_zisofs(struct XorrisO *xorriso, char *filter, FILE *fp,
int flag);
/* @param flag bit0= overwrite existing di_array (else return 2)
*/
int Xorriso_make_di_array(struct XorrisO *xorriso, int flag);
/*
@param flag bit2= -follow: this is not a command parameter
@return -1= severe error
0= not applicable for hard links
1= go on with processing
2= iso_rr_path is fully updated
*/
int Xorriso_hardlink_update(struct XorrisO *xorriso, int *compare_result,
char *disk_path, char *iso_rr_path, int flag);
/* A pseudo file type for El-Torito bootsectors as in man 2 stat :
For now take the highest possible value.