New -findx -exec action "empty_iso_dir", workaround for ticket 132

This commit is contained in:
2008-03-07 18:24:26 +00:00
parent 5982c8e6b3
commit 005a317059
5 changed files with 294 additions and 173 deletions

View File

@ -1433,6 +1433,49 @@ int Xorriso_transfer_properties(struct XorrisO *xorriso, struct stat *stbuf,
}
/* Ticket 132 : Workaround for missing feature */
int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume,
IsoDir *dir, char *disk_path, char *img_name,
char *nominal_source, char *nominal_target,
IsoNode **node, int flag)
{
int ret, wa_ret, i;
char wa_name[256];
IsoDir *hdir;
ret= iso_tree_add_node(volume, dir, disk_path, node);
if(ret==ISO_NODE_NAME_NOT_UNIQUE) {
wa_ret= ISO_NODE_NAME_NOT_UNIQUE;
for(i= 0; wa_ret==ISO_NODE_NAME_NOT_UNIQUE && i<2000000000; i++) {
sprintf(wa_name, "xorriso_works_around_what_is_not_a_bug_try_%d", i);
wa_ret= iso_tree_add_new_dir(dir, wa_name, &hdir);
}
if(wa_ret<0)
goto cannot_add;
ret= iso_tree_add_node(volume, hdir, disk_path, node);
if(ret>0) {
ret= iso_node_set_name(*node, img_name);
if(ret<0) {
Xorriso_process_msg_queues(xorriso,0);
Xorriso_report_iso_error(xorriso, nominal_target, 0,
"Cannot set name", 0, "FAILURE", 1);
return(ret);
}
iso_node_take(*node);
ret= iso_dir_add_node(dir, *node, 0);
}
iso_node_remove((IsoNode *) hdir);
}
if(ret<0) {
cannot_add:;
Xorriso_report_iso_error(xorriso, nominal_source, ret,
"Cannot add node to tree", 0, "FAILURE", 1|2);
return(ret);
}
return(1);
}
/* @param flag bit0= recursion is active
bit1= do not report added files
*/
@ -1576,17 +1619,6 @@ cannot_lstat:;
source_is_dir= 1;
if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
do_not_dive= 1;
#ifdef NIX
} else if(!(S_ISREG(stbuf.st_mode) || S_ISLNK(stbuf.st_mode))) {
Xorriso_msgs_submit(xorriso, 0, stbuf_src, 0, "ERRFILE", 0);
sprintf(xorriso->info_text,"Source file %s %s non-supported file type",
Text_shellsafe(srcpt, sfe, 0),
source_is_link ? "leads to" : "is of");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
ret= 0; goto was_problem;
#endif /* NIX */
}
/* does a node exist with this name ? */
@ -1600,7 +1632,7 @@ cannot_lstat:;
/* handle overwrite situation */;
if(xorriso->do_overwrite==1 ||
(xorriso->do_overwrite==2 && !target_is_dir)) {
ret= Xorriso_rmi(xorriso, NULL, img_path, 1|8);
ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, img_path, 1|8);
if(ret<=0)
goto was_problem;
if(ret==3) {
@ -1640,7 +1672,13 @@ cannot_lstat:;
{ret= 0; goto was_problem;}
}
} else {
#ifdef NIX
ret= iso_tree_add_node(volume, dir, srcpt, &node);
#else
ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name,
stbuf_src, img_path,
&node, 0);
#endif
if(ret<0) {
Xorriso_report_iso_error(xorriso, stbuf_src, ret,
"Cannot add node to tree", 0, "FAILURE", 1|2);
@ -1911,7 +1949,7 @@ 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)) {
ret= Xorriso_rmi(xorriso, boss_iter, path, 1|8);
ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, path, 1|8);
if(ret<=0)
return(ret);
if(ret==3) {
@ -1953,7 +1991,7 @@ handle_path_node:;
iso_node_set_uid((IsoNode *) dir, geteuid());
iso_node_set_gid((IsoNode *) dir, getegid());
if(!done)
if(disk_path!=NULL && !done)
Xorriso_copy_implict_properties(xorriso, dir, img_path, path, disk_path,
0);
@ -1982,6 +2020,8 @@ attach_source:;
disk_path_pt= resolved_disk_path;
} else
disk_path_pt= disk_path;
#ifdef NIX
ret= iso_tree_add_node(volume, dir, disk_path_pt, &node);
if(ret<0) {
Xorriso_process_msg_queues(xorriso,0);
@ -1993,6 +2033,16 @@ attach_source:;
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
#else
ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt,
disk_path, img_path, &node, 0);
if(ret<0) {
sprintf(xorriso->info_text, "Grafting failed: %s = %s",
Text_shellsafe(img_path,sfe,0), Text_shellsafe(disk_path,sfe2,0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
#endif
xorriso->volset_change_pending= 1;
iso_node_set_name(node, apt);
}
@ -2471,6 +2521,131 @@ int Xorriso_cannot_create_iter(struct XorrisO *xorriso, int iso_error,int flag)
}
int Xorriso__node_lba_cmp(const void *node1, const void *node2)
{
uint32_t lba1= 0, lba2= 0;
int ret;
ret = iso_node_get_old_image_lba(*((IsoNode **) node1), &lba1, 0);
if(ret!=1)
lba1= 0;
ret = iso_node_get_old_image_lba(*((IsoNode **) node2), &lba2, 0);
if(ret!=1)
lba1= 0;
return(lba1-lba2);
}
/* The caller shall make no assumptions about the meaning of iter, node_array,
node_count, node_idx ! They are just opaque handles for which the caller
provides the memory of proper type.
@param flag bit0= initialize iteration
bit1= action needs full freedom of object manipulation
bit2= action needs LBA sorted iteration
bit31= end iteration (mandatory !)
*/
int Xorriso_findi_iter(struct XorrisO *xorriso, IsoDir *dir_node, off_t *mem,
IsoDirIter **iter,
IsoNode ***node_array, int *node_count, int *node_idx,
IsoNode **iterated_node, int flag)
{
int ret, i;
IsoNode *node;
off_t new_mem= 0;
char mem_text[80], limit_text[80];
if(flag&1) {
*node_array= NULL;
*node_count= -1;
*node_idx= 0;
*iter= NULL;
ret= iso_dir_get_children(dir_node, iter);
if(ret<0) {
cannot_iter:;
Xorriso_cannot_create_iter(xorriso, ret, 0);
return(-1);
}
if((flag&2)|(flag&4)) {
/* copy list of nodes and prepare soft iterator */
*node_count= 0;
while(iso_dir_iter_next(*iter, &node) == 1)
(*node_count)++;
iso_dir_iter_free(*iter);
*iter= NULL;
new_mem= ((*node_count)+1) * sizeof(IsoNode *);
if(new_mem > xorriso->temp_mem_limit) {
Sfile_scale((double) new_mem, mem_text, 5,1e4, 0);
Sfile_scale((double) xorriso->temp_mem_limit, limit_text, 5,1e4, 0);
sprintf(xorriso->info_text,
"Stacked directory snapshots exceed -temp_mem_limit (%s > %s)",
mem_text, limit_text);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
*node_count= -1;
return(-1);
}
(*node_array)= (IsoNode **) calloc((*node_count)+1, sizeof(IsoNode *));
if(*node_array == NULL) {
sprintf(xorriso->info_text,
"Could not allocate inode list of %.f bytes",
((double) (*node_count)+1) * (double) sizeof(IsoNode *));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
*node_count= -1;
return(-1);
}
*mem= new_mem;
ret= iso_dir_get_children(dir_node, iter);
if(ret<0)
goto cannot_iter;
while(iso_dir_iter_next(*iter, &node) == 1 && *node_idx < *node_count) {
(*node_array)[*node_idx]= node;
iso_node_ref(node);
(*node_idx)++;
}
iso_dir_iter_free(*iter);
*iter= NULL;
*node_count= *node_idx;
*node_idx= 0;
if((flag&4) && *node_count>1)
qsort(*node_array, *node_count, sizeof(IsoNode *),
Xorriso__node_lba_cmp);
}
}
if(flag&(1<<31)) {
if(*node_count>=0 && *node_array!=NULL) {
for(i= 0; i<*node_count; i++)
iso_node_unref((*node_array)[i]);
free(*node_array);
*node_array= NULL;
*node_count= -1;
*node_idx= 0;
} else {
if(*iter!=NULL)
iso_dir_iter_free(*iter);
*iter= NULL;
}
}
if(flag&(1|(1<<31)))
return(1);
if(*node_count>=0) {
/* return next node_array element */
if(*node_idx>=*node_count)
return(0);
*iterated_node= (*node_array)[*node_idx];
(*node_idx)++;
} else {
ret= iso_dir_iter_next(*iter, iterated_node);
return(ret == 1);
}
return(1);
}
/*
*/
#define Xorriso_rmi_findi_iteR yes
/* @param boss_iter If not NULL then this is an iterator suitable for
iso_dir_iter_remove() which is then to be used instead
of iso_node_remove().
@ -2479,12 +2654,13 @@ int Xorriso_cannot_create_iter(struct XorrisO *xorriso, int iso_error,int flag)
bit2= recursion: do not reassure in mode 2 "tree"
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
@return <=0 = error
1 = removed simple node
2 = removed directory or tree
3 = did not remove on user revocation
*/
int Xorriso_rmi(struct XorrisO *xorriso, void *boss_iter,
int Xorriso_rmi(struct XorrisO *xorriso, void *boss_iter, off_t boss_mem,
char *path, int flag)
{
int ret, is_dir= 0, pl, not_removed= 0, fret;
@ -2497,7 +2673,14 @@ int Xorriso_rmi(struct XorrisO *xorriso, void *boss_iter,
#ifdef Xorriso_fat_local_meM
char sfe[5*SfileadrL], sub_path[2*SfileadrL];
#else
char *sfe= NULL, *sub_path= NULL;
off_t mem;
#ifdef Xorriso_rmi_findi_iteR
IsoNode **node_array= NULL;
int node_count, node_idx;
#endif /* ! Xorriso_rmi_findi_iteR */
/* Avoiding large local memory objects in order to save stack space */
sfe= malloc(5*SfileadrL);
@ -2550,12 +2733,22 @@ int Xorriso_rmi(struct XorrisO *xorriso, void *boss_iter,
}
} else {
if(flag&1) { /* rm -r */
if(xorriso->do_reassure==1 && !xorriso->request_not_to_ask) {
if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) ||
(flag&32)) {
/* Iterate over subordinates and delete them */
mem= boss_mem;
#ifdef Xorriso_rmi_findi_iteR
ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem,
&iter, &node_array, &node_count, &node_idx,
&node, 1|2);
if(ret<=0) {
#else
ret= iso_dir_get_children((IsoDir *) victim_node, &iter);
Xorriso_process_msg_queues(xorriso,0);
if(ret<0) {
#endif /* ! Xorriso_rmi_findi_iteR */
cannot_create_iter:;
Xorriso_cannot_create_iter(xorriso, ret, 0);
ret= -1; goto ex;
@ -2567,13 +2760,25 @@ cannot_create_iter:;
sub_path[pl]= 0;
}
sub_name= sub_path+pl;
#ifdef Xorriso_rmi_findi_iteR
while(1) {
ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter,
&node_array, &node_count, &node_idx, &node, 0);
if(ret<0)
goto ex;
if(ret==0 || xorriso->request_to_abort)
break;
#else
while(iso_dir_iter_next(iter, &node) == 1
&& !xorriso->request_to_abort) {
#endif
name= (char *) iso_node_get_name(node);
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, sub_path, (flag&(1|2|8|16))|4);
ret= Xorriso_rmi(xorriso, iter, mem, sub_path, (flag&(1|2|8|16))|4);
if(ret==3 || ret<=0 || xorriso->request_to_abort) {
rm_r_problem_handler:;
not_removed= 1;
@ -2582,6 +2787,9 @@ rm_r_problem_handler:;
goto dir_not_removed;
}
}
if(flag&32)
{ret= 2; goto ex;}
if(not_removed) {
dir_not_removed:;
sprintf(xorriso->info_text, "Directory not removed: %s",
@ -2705,8 +2913,14 @@ ex:;
free(sub_path);
#endif /* ! Xorriso_fat_local_meM */
#ifdef Xorriso_rmi_findi_iteR
Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter,
&node_array, &node_count, &node_idx, &node, (1<<31));
#else
if(iter!=NULL)
iso_dir_iter_free(iter);
#endif /* ! Xorriso_rmi_findi_iteR */
return(ret);
}
@ -3332,6 +3546,21 @@ int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter,
IsoDir *origin_dir, *dest_dir;
IsoNode *node, *iso_node;
#ifndef Libisofs_iso_dir_iter_sufficienT
/* Ticket 127: A80301 - A80302
I do not not deem IsoDirIter safe for node list manipulations.
The parameter boss_iter once was intended to allow such but
has now been downgraded to a mere check for eventual programming bugs.
*/
if(boss_iter!=NULL) {
sprintf(xorriso->info_text,
"Program error: Xorriso_rename() was requested to delete iterated node %s",
Text_shellsafe(origin, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
return(-1);
}
#endif /* Libisofs_iso_dir_iter_sufficienT */
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, origin, eff_origin, 0);
if(ret<=0)
return(ret);
@ -3377,7 +3606,7 @@ int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter,
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
} else if(dest_ret>0) {
ret= Xorriso_rmi(xorriso, boss_iter, eff_dest, 1|8);
ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, eff_dest, 1|8);
if(ret<=0)
return(0);
if(ret==3) {
@ -3430,15 +3659,6 @@ int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter,
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
return(-1);
}
ret= iso_dir_add_node(dest_dir, node, 0);
if(ret<0) {
Xorriso_process_msg_queues(xorriso,0);
Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot add", 0, "FATAL", 1);
sprintf(xorriso->info_text,
"Internal error on rename: failed to insert node");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
return(-1);
}
leafname= strrchr(eff_dest, '/');
if(leafname==NULL)
leafname= eff_dest;
@ -3453,12 +3673,19 @@ int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter,
if(ret<0) {
Xorriso_process_msg_queues(xorriso,0);
Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot set name", 0,
"FATAL", 1);
sprintf(xorriso->info_text, "Internal error on rename: failed to set name");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
"FAILURE", 1);
return(-1);
}
Xorriso_process_msg_queues(xorriso,0);
ret= iso_dir_add_node(dest_dir, node, 0);
if(ret<0) {
Xorriso_process_msg_queues(xorriso,0);
Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot add", 0, "FATAL", 1);
sprintf(xorriso->info_text,
"Internal error on rename: failed to insert node");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
return(-1);
}
return(1);
}
@ -3813,11 +4040,11 @@ int Xorriso_findi_action(struct XorrisO *xorriso, struct FindjoB *job,
if(ret>0) {
if(S_ISDIR(dir_stbuf.st_mode))
hflag= 2;
ret= Xorriso_rmi(xorriso, boss_iter, abs_path, hflag);
ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, hflag);
deleted= 1;
}
} else if(action==2) { /* rm_r */
ret= Xorriso_rmi(xorriso, boss_iter, abs_path, 1|hflag);
ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, 1|hflag);
deleted= 1;
} else if(action==3) {
@ -3860,129 +4087,6 @@ int Xorriso_findi_action(struct XorrisO *xorriso, struct FindjoB *job,
}
int Xorriso__node_lba_cmp(const void *node1, const void *node2)
{
uint32_t lba1= 0, lba2= 0;
int ret;
ret = iso_node_get_old_image_lba(*((IsoNode **) node1), &lba1, 0);
if(ret!=1)
lba1= 0;
ret = iso_node_get_old_image_lba(*((IsoNode **) node2), &lba2, 0);
if(ret!=1)
lba1= 0;
return(lba1-lba2);
}
/* The caller shall make no assumptions about the meaning of iter, node_array,
node_count, node_idx ! They are just opaque handles for which the caller
provides the memory of proper type.
@param flag bit0= initialize iteration
bit1= action needs full freedom of object manipulation
bit2= action needs LBA sorted iteration
bit31= end iteration (mandatory !)
*/
int Xorriso_findi_iter(struct XorrisO *xorriso, IsoDir *dir_node, off_t *mem,
IsoDirIter **iter,
IsoNode ***node_array, int *node_count, int *node_idx,
IsoNode **iterated_node, int flag)
{
int ret, i;
IsoNode *node;
off_t new_mem= 0;
char mem_text[80], limit_text[80];
if(flag&1) {
*node_array= NULL;
*node_count= -1;
*node_idx= 0;
*iter= NULL;
ret= iso_dir_get_children(dir_node, iter);
if(ret<0) {
cannot_iter:;
Xorriso_cannot_create_iter(xorriso, ret, 0);
return(-1);
}
if((flag&2)|(flag&4)) {
/* copy list of nodes and prepare soft iterator */
*node_count= 0;
while(iso_dir_iter_next(*iter, &node) == 1)
(*node_count)++;
iso_dir_iter_free(*iter);
*iter= NULL;
new_mem= ((*node_count)+1) * sizeof(IsoNode *);
if(new_mem > xorriso->temp_mem_limit) {
Sfile_scale((double) new_mem, mem_text, 5,1e4, 0);
Sfile_scale((double) xorriso->temp_mem_limit, limit_text, 5,1e4, 0);
sprintf(xorriso->info_text,
"Stacked directory snapshots exceed -temp_mem_limit (%s > %s)",
mem_text, limit_text);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
*node_count= -1;
return(-1);
}
(*node_array)= (IsoNode **) calloc((*node_count)+1, sizeof(IsoNode *));
if(*node_array == NULL) {
sprintf(xorriso->info_text,
"Could not allocate inode list of %.f bytes",
((double) (*node_count)+1) * (double) sizeof(IsoNode *));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
*node_count= -1;
return(-1);
}
*mem= new_mem;
ret= iso_dir_get_children(dir_node, iter);
if(ret<0)
goto cannot_iter;
while(iso_dir_iter_next(*iter, &node) == 1 && *node_idx < *node_count) {
(*node_array)[*node_idx]= node;
iso_node_ref(node);
(*node_idx)++;
}
iso_dir_iter_free(*iter);
*iter= NULL;
*node_count= *node_idx;
*node_idx= 0;
if((flag&4) && *node_count>1)
qsort(*node_array, *node_count, sizeof(IsoNode *),
Xorriso__node_lba_cmp);
}
}
if(flag&(1<<31)) {
if(*node_count>=0 && *node_array!=NULL) {
for(i= 0; i<*node_count; i++)
iso_node_unref((*node_array)[i]);
free(*node_array);
*node_array= NULL;
*node_count= -1;
*node_idx= 0;
} else {
if(*iter!=NULL)
iso_dir_iter_free(*iter);
*iter= NULL;
}
}
if(flag&(1|(1<<31)))
return(1);
if(*node_count>=0) {
/* return next node_array element */
if(*node_idx>=*node_count)
return(0);
*iterated_node= (*node_array)[*node_idx];
(*node_idx)++;
} else {
ret= iso_dir_iter_next(*iter, iterated_node);
return(ret == 1);
}
return(1);
}
/* @param flag bit0= recursion
bit1= do not count deleted files with rm and rm_r
@return <=0 error, 1= ok , 2= dir node and path has been deleted
@ -4131,13 +4235,8 @@ ex:;
Xorriso_process_msg_queues(xorriso,0);
#ifdef Xorriso_findi_new_iteR
Xorriso_findi_iter(xorriso, dir_node, &mem, &iter, &node_array, &node_count,
&node_idx, &node, (1<<31));
#else
if(iter!=NULL)
iso_dir_iter_free(iter);
#endif
if(ret<=0)
return(ret);
if(deleted)