Gave up risky direct update of hardlink siblings

This commit is contained in:
2009-06-22 11:28:34 +00:00
parent 40e0333edb
commit 67d7e8821b
6 changed files with 276 additions and 93 deletions

View File

@ -187,6 +187,12 @@ int Xorriso_destroy_di_array(struct XorrisO *xorriso, int flag)
free(xorriso->di_array);
xorriso->di_array= NULL;
}
if(xorriso->di_do_widen != NULL) {
free(xorriso->di_do_widen);
xorriso->di_do_widen= NULL;
}
Xorriso_lst_destroy_all(&(xorriso->di_disk_paths), 0);
Xorriso_lst_destroy_all(&(xorriso->di_iso_paths), 0);
xorriso->di_count= 0;
#ifdef NIX
@ -253,8 +259,8 @@ int Xorriso_new_hln_array(struct XorrisO *xorriso, off_t mem_limit, int flag)
xorriso->node_targets_availmem= mem_limit
- xorriso->hln_count * sizeof(void *)
- xorriso->hln_count * sizeof(char *);
if(xorriso->node_targets_availmem < 0)
xorriso->node_targets_availmem= 0;
if(xorriso->node_targets_availmem < 0)
xorriso->node_targets_availmem= 0;
return(1);
}
@ -471,6 +477,46 @@ int Xorriso_invalidate_di_item(struct XorrisO *xorriso, IsoNode *node,
}
/* @param flag bit0= return 1 even if matching nodes were found but node is
not among them
bit1= use Xorriso__di_cmp() rather than Xorriso__di_ino_cmp()
*/
int Xorriso_search_di_range(struct XorrisO *xorriso, IsoNode *node,
int *idx, int *low, int *high, int flag)
{
int ret, i, found;
int (*cmp)(const void *p1, const void *p2)= Xorriso__di_ino_cmp;
if(flag & 2)
cmp= Xorriso__di_cmp;
*high= *low= *idx= -1;
ret= Xorriso__search_node(xorriso->di_array, xorriso->di_count,
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((*cmp)(&node, &(xorriso->di_array[i])) != 0)
break;
*high= i;
}
for(i= found - 1; i >= 0; i--)
if(xorriso->di_array[i] != NULL) {
if((*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));
}
/* ------------------------------------------------------------------------ */
@ -606,6 +652,7 @@ int Xorriso_detach_libraries(struct XorrisO *xorriso, int flag)
xorriso->in_volset_handle= NULL;
Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
Xorriso_destroy_di_array(xorriso, 0);
Xorriso_destroy_hln_array(xorriso, 0);
}
if(flag&1) {
if(xorriso->libs_are_started==0)
@ -764,6 +811,7 @@ int Xorriso_create_empty_iso(struct XorrisO *xorriso, int flag)
xorriso->in_volset_handle= NULL;
Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
Xorriso_destroy_di_array(xorriso, 0);
Xorriso_destroy_hln_array(xorriso, 0);
xorriso->loaded_volid[0]= 0;
xorriso->volset_change_pending= 0;
xorriso->no_volset_present= 0;
@ -1041,6 +1089,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_hln_array(xorriso, 0);
Xorriso_destroy_di_array(xorriso, 0);
/* check for invalid state */
@ -1233,6 +1282,7 @@ int Xorriso_give_up_drive(struct XorrisO *xorriso, int flag)
xorriso->in_volset_handle= NULL;
Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
Xorriso_destroy_di_array(xorriso, 0);
Xorriso_destroy_hln_array(xorriso, 0);
xorriso->loaded_volid[0]= 0;
xorriso->isofs_st_out= time(0) - 1;
xorriso->isofs_st_in= 0;
@ -1505,6 +1555,10 @@ int Xorriso_write_session(struct XorrisO *xorriso, int flag)
int profile_number;
char profile_name[80];
ret= Xorriso_finish_hl_update(xorriso, 0);
if(ret <= 0)
return(ret);
out_cs= xorriso->out_charset;
if(out_cs == NULL)
Xorriso_get_local_charset(xorriso, &out_cs, 0);
@ -7373,6 +7427,46 @@ int Xorriso_report_damage(struct XorrisO *xorriso, char *show_path,
}
int Xorriso_widen_hardlink(struct XorrisO *xorriso, void * boss_iter,
IsoNode *node,
char *abs_path, char *iso_prefix, char *disk_prefix,
int flag)
{
int ret= 0, idx, low, high, i, do_widen= 0, compare_result= 0;
char disk_path[SfileadrL];
/* Lookup all di_array instances of node */
if(LIBISO_ISDIR(node))
return(1);
ret= Xorriso_search_di_range(xorriso, node, &idx, &low, &high, 2);
if(ret <= 0)
return(1);
/* Check and reset di_do_widen bits */
for(i= low; i <= high; i++) {
if(node != xorriso->di_array[i]) /* might be NULL */
continue;
if(xorriso->di_do_widen[i / 8] & (1 << (i % 8)))
do_widen= 1;
xorriso->di_do_widen[i / 8]&= ~(1 << (i % 8));
}
if(idx < 0 || !do_widen)
return(1);
ret= Xorriso_pfx_disk_path(xorriso, abs_path, iso_prefix, disk_prefix,
disk_path, 0);
if(ret <= 0)
return(ret);
/* >>> compare_result bit17 = is_split */;
ret= Xorriso_update_interpreter(xorriso, boss_iter, compare_result, disk_path,
abs_path, 1);
if(ret <= 0)
return(ret);
return 1;
}
/* @param flag bit0= not a command parameter (directory iteration or recursion)
bit1= do not count deleted files with rm and rm_r
@return <=0 error,
@ -7470,6 +7564,11 @@ int Xorriso_findi_action(struct XorrisO *xorriso, struct FindjoB *job,
iso_node_ref(node); /* In case node gets deleted from tree during
the lifetime of xorriso->node_array */
}
} else if(action == 32) { /* internal: widen_hardlinks disk_equiv */
Findjob_get_start_path(job, &iso_prefix, 0);
ret= Xorriso_widen_hardlink(xorriso, (void *) boss_iter, node, abs_path,
iso_prefix, target, 0);
} else { /* includes : 15 in_iso */
sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0));
Xorriso_result(xorriso, 0);
@ -7926,7 +8025,8 @@ int Xorriso_findi(struct XorrisO *xorriso, struct FindjoB *job,
mem= boss_mem;
hflag= 1;
if(action==1 || action==2 || action==3 || action==17 || action == 28)
if(action==1 || action==2 || action==3 || action==17 || action == 28 ||
action == 32)
hflag|= 2; /* need freedom to manipulate image */
if(action==14 || action==17 || action == 28)
hflag|= 4; /* need LBA sorted iteration for good data reading performance */
@ -11689,6 +11789,7 @@ int Xorriso_make_hln_array(struct XorrisO *xorriso, int flag)
ret= Xorriso_new_hln_array(xorriso, xorriso->temp_mem_limit, 1);
if(ret<=0)
goto ex;
xorriso->node_targets_availmem= xorriso->temp_mem_limit;
ret= 1;
ex:;
@ -11701,7 +11802,7 @@ ex:;
*/
int Xorriso_make_di_array(struct XorrisO *xorriso, int flag)
{
int ret;
int ret, bytes;
#ifdef NIX
/* <<< */
@ -11713,11 +11814,17 @@ int Xorriso_make_di_array(struct XorrisO *xorriso, int flag)
return(2);
if(xorriso->di_array != NULL && !(flag & 1))
return(2);
Xorriso_destroy_di_array(xorriso, 0);
Xorriso_finish_hl_update(xorriso, 0);
ret= Xorriso_all_node_array(xorriso, 0);
if(ret <= 0)
goto ex;
bytes= xorriso->node_array_size / 8 + 1;
xorriso->di_do_widen= calloc(bytes, 1);
if(xorriso->di_do_widen == NULL) {
Xorriso_no_malloc_memory(xorriso, NULL, 0);
ret= -1; goto ex;
}
/* Transfer node_array to di_array without unrefering nodes */
xorriso->di_count= xorriso->node_counter;
@ -11741,41 +11848,6 @@ ex:;
}
/* @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
@ -11788,13 +11860,18 @@ 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];
int follow_links, old_idx= -1;
IsoNode *node;
struct stat stbuf;
dev_t old_dev;
ino_t old_ino;
#ifdef Xorriso_hardlink_update_direcT
/* <<< */
int node_result;
char node_path[SfileadrL];
#endif
if(xorriso->di_array == NULL)
return(1);
follow_links= xorriso->do_follow_links ||
@ -11862,7 +11939,7 @@ int Xorriso_hardlink_update(struct XorrisO *xorriso, int *compare_result,
{ret= 0; goto ex;}
#ifdef NIX
#ifdef Xorriso_hardlink_update_debuG
/* <<< */
if(low < high || idx < 0) {
fprintf(stderr,
@ -11876,20 +11953,14 @@ int Xorriso_hardlink_update(struct XorrisO *xorriso, int *compare_result,
if(idx >= 0 && idx != old_idx)
fprintf(stderr, "xorriso_DEBUG: idx= %d , old_idx = %d\n", idx, old_idx);
}
#endif /* NIX */
#endif /* Xorriso_hardlink_update_debuG */
/* 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
#ifdef Xorriso_hardlink_update_debuG
/* <<< */
{
ino_t ino;
@ -11899,7 +11970,17 @@ int Xorriso_hardlink_update(struct XorrisO *xorriso, int *compare_result,
fprintf(stderr, "xorriso_DEBUG: iso_sibling= '%s' , dev= %lu , ino= %lu\n",
node_path, (unsigned long) dev, (unsigned long) ino);
}
#endif /* NIX */
#endif /* Xorriso_hardlink_update_debuG */
#ifdef Xorriso_hardlink_update_direcT
/* <<< */
/* 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 */
node_result= 0;
ret= Xorriso_compare_2_files(xorriso, disk_path, node_path, "",
@ -11913,6 +11994,13 @@ int Xorriso_hardlink_update(struct XorrisO *xorriso, int *compare_result,
if(ret < 0)
goto ex;
}
#else /* Xorriso_hardlink_update_direcT */
xorriso->di_do_widen[i / 8]|= 1 << (i % 8);
#endif /* ! Xorriso_hardlink_update_direcT */
}
ret= 1;
@ -11928,3 +12016,33 @@ ex:;
return(ret);
}
int Xorriso_finish_hl_update(struct XorrisO *xorriso, int flag)
{
int ret, zero= 0;
char *argv[4];
struct Xorriso_lsT *disk_lst, *iso_lst;
if(xorriso->di_array == NULL)
{ret= 1; goto ex;}
disk_lst= xorriso->di_disk_paths;
iso_lst= xorriso->di_iso_paths;
while(disk_lst != 0 && iso_lst != NULL) {
argv[0]= Xorriso_lst_get_text(iso_lst, 0);
argv[1]= "-exec";
argv[2]= "widen_hardlinks";
argv[3]= Xorriso_lst_get_text(disk_lst, 0);
zero= 0;
ret= Xorriso_option_find(xorriso, 4, argv, &zero, 0); /* -findi */
if(ret < 0)
goto ex;
disk_lst= Xorriso_lst_get_next(disk_lst, 0);
iso_lst= Xorriso_lst_get_next(iso_lst, 0);
}
ret= 1;
ex:;
Xorriso_destroy_di_array(xorriso, 0);
return(ret);
}