From bf702dc38ee0f86fa7c8b436ecc18b213c39f44b Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Mon, 15 Jun 2009 12:15:12 +0000 Subject: [PATCH] With -update_r : detecting hardlink splits and fusions on disk --- libisoburn/trunk/xorriso/xorriso.1 | 25 +- libisoburn/trunk/xorriso/xorriso.c | 140 +++++- libisoburn/trunk/xorriso/xorriso_private.h | 15 + libisoburn/trunk/xorriso/xorriso_timestamp.h | 2 +- libisoburn/trunk/xorriso/xorrisoburn.c | 488 ++++++++++++++++++- libisoburn/trunk/xorriso/xorrisoburn.h | 16 + 6 files changed, 634 insertions(+), 52 deletions(-) diff --git a/libisoburn/trunk/xorriso/xorriso.1 b/libisoburn/trunk/xorriso/xorriso.1 index b33b849f..c8aa35b7 100644 --- a/libisoburn/trunk/xorriso/xorriso.1 +++ b/libisoburn/trunk/xorriso/xorriso.1 @@ -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. diff --git a/libisoburn/trunk/xorriso/xorriso.c b/libisoburn/trunk/xorriso/xorriso.c index 1cfa8eb8..02e5f4b2 100644 --- a/libisoburn/trunk/xorriso/xorriso.c +++ b/libisoburn/trunk/xorriso/xorriso.c @@ -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; idi_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); } diff --git a/libisoburn/trunk/xorriso/xorriso_private.h b/libisoburn/trunk/xorriso/xorriso_private.h index b4206336..e6ddc8fd 100644 --- a/libisoburn/trunk/xorriso/xorriso_private.h +++ b/libisoburn/trunk/xorriso/xorriso_private.h @@ -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, diff --git a/libisoburn/trunk/xorriso/xorriso_timestamp.h b/libisoburn/trunk/xorriso/xorriso_timestamp.h index 5d26bf78..364a1b92 100644 --- a/libisoburn/trunk/xorriso/xorriso_timestamp.h +++ b/libisoburn/trunk/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2009.06.03.082041" +#define Xorriso_timestamP "2009.06.15.121525" diff --git a/libisoburn/trunk/xorriso/xorrisoburn.c b/libisoburn/trunk/xorriso/xorrisoburn.c index d62f1c00..eb3ae8c6 100644 --- a/libisoburn/trunk/xorriso/xorrisoburn.c +++ b/libisoburn/trunk/xorriso/xorrisoburn.c @@ -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); +} + diff --git a/libisoburn/trunk/xorriso/xorrisoburn.h b/libisoburn/trunk/xorriso/xorrisoburn.h index 5b092660..91bb01cb 100644 --- a/libisoburn/trunk/xorriso/xorrisoburn.h +++ b/libisoburn/trunk/xorriso/xorrisoburn.h @@ -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.