New -findx -exec action "empty_iso_dir", workaround for ticket 132
This commit is contained in:
parent
a5ea9f79a0
commit
955d08c735
@ -684,8 +684,8 @@ the particular file names of the eventual directory tree underneath
|
|||||||
iso_rr_path. If no -name pattern is given, then any file name matches.
|
iso_rr_path. If no -name pattern is given, then any file name matches.
|
||||||
.br
|
.br
|
||||||
The optional -type test restricts matching to files of the given type:
|
The optional -type test restricts matching to files of the given type:
|
||||||
"block", "char", "dir", "pipe", "file", "link", "socket", "Xotic",
|
"block", "char", "dir", "pipe", "file", "link", "socket",
|
||||||
where "X" eventually matches what is not matched by the other types.
|
"Xotic" which eventually matches what is not matched by the other types.
|
||||||
.br
|
.br
|
||||||
Only the first letter is interpreted. E.g.: -find / -type d
|
Only the first letter is interpreted. E.g.: -find / -type d
|
||||||
.br
|
.br
|
||||||
@ -1299,6 +1299,11 @@ Similar to shell command du -sk.
|
|||||||
Like -find but operating on local filesystem and not on the ISO image.
|
Like -find but operating on local filesystem and not on the ISO image.
|
||||||
This is subject to the settings of -follow.
|
This is subject to the settings of -follow.
|
||||||
.br
|
.br
|
||||||
|
Find accepts the same -type arguments as -find. Additionally it recognizes
|
||||||
|
type "mountpoint" (or "m"). It matches subdirectories which reside on a
|
||||||
|
different device than their parent. It never matches the disk_path
|
||||||
|
given as start address for -findx.
|
||||||
|
.br
|
||||||
-findx accepts the -exec actions as does -find. But except the following few
|
-findx accepts the -exec actions as does -find. But except the following few
|
||||||
actions it will allways perform action "echo".
|
actions it will allways perform action "echo".
|
||||||
.br
|
.br
|
||||||
|
@ -2379,7 +2379,7 @@ struct FindjoB {
|
|||||||
f = reg
|
f = reg
|
||||||
- = reg
|
- = reg
|
||||||
s = socket
|
s = socket
|
||||||
>>> m = subordinate mountpoint (does never match find start directory)
|
m = subordinate mountpoint (does never match find start directory)
|
||||||
X = other
|
X = other
|
||||||
0x0 = test inactive
|
0x0 = test inactive
|
||||||
*/
|
*/
|
||||||
@ -2387,8 +2387,8 @@ struct FindjoB {
|
|||||||
|
|
||||||
|
|
||||||
/* 0= echo
|
/* 0= echo
|
||||||
>>> 1= rm (also rmdir)
|
1= rm (also rmdir)
|
||||||
>>> 2= rm_r
|
2= rm_r
|
||||||
>>> 3= mv target
|
>>> 3= mv target
|
||||||
4= chown user
|
4= chown user
|
||||||
5= chgrp group
|
5= chgrp group
|
||||||
@ -2405,6 +2405,7 @@ struct FindjoB {
|
|||||||
16= not_in_iso
|
16= not_in_iso
|
||||||
17= update
|
17= update
|
||||||
18= add_missing
|
18= add_missing
|
||||||
|
>>>19= empty_iso_dir
|
||||||
*/
|
*/
|
||||||
int action;
|
int action;
|
||||||
char *target;
|
char *target;
|
||||||
@ -6142,7 +6143,7 @@ int Xorriso_findx_action(struct XorrisO *xorriso, struct FindjoB *job,
|
|||||||
action= 0;
|
action= 0;
|
||||||
if(action<0)
|
if(action<0)
|
||||||
action= 0;
|
action= 0;
|
||||||
if(action==15 || action==16 || action==18) {
|
if(action==15 || action==16 || action==18 || action==19) {
|
||||||
/* in_iso , not_in_iso, add_missing */
|
/* in_iso , not_in_iso, add_missing */
|
||||||
Findjob_get_start_path(job, &disk_prefix, 0);
|
Findjob_get_start_path(job, &disk_prefix, 0);
|
||||||
if(strncmp(abs_path, disk_prefix, strlen(disk_prefix))!=0)
|
if(strncmp(abs_path, disk_prefix, strlen(disk_prefix))!=0)
|
||||||
@ -6184,6 +6185,18 @@ int Xorriso_findx_action(struct XorrisO *xorriso, struct FindjoB *job,
|
|||||||
}
|
}
|
||||||
if(ret>=0)
|
if(ret>=0)
|
||||||
ret= 1;
|
ret= 1;
|
||||||
|
} else if(action==19) { /* empty_iso_dir */
|
||||||
|
ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
|
||||||
|
if(ret==-1)
|
||||||
|
return(1);
|
||||||
|
if(!S_ISDIR(stbuf.st_mode))
|
||||||
|
return(1);
|
||||||
|
ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, iso_path, 1|32);
|
||||||
|
if(ret>0) {
|
||||||
|
sprintf(xorriso->info_text, "Emptied directory %s",
|
||||||
|
Text_shellsafe(iso_path, sfe, 0));
|
||||||
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0));
|
sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0));
|
||||||
Xorriso_result(xorriso, 0);
|
Xorriso_result(xorriso, 0);
|
||||||
@ -7124,7 +7137,7 @@ int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter,
|
|||||||
|
|
||||||
if(compare_result&(8|64)) {
|
if(compare_result&(8|64)) {
|
||||||
/* file type, minor+major with device file */
|
/* file type, minor+major with device file */
|
||||||
ret= Xorriso_rmi(xorriso, boss_iter, iso_rr_path, 1); /* rm_r */
|
ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1); /* rm_r */
|
||||||
if(ret>0) {
|
if(ret>0) {
|
||||||
deleted= 1;
|
deleted= 1;
|
||||||
ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, iso_rr_path,
|
ret= Xorriso_graft_in(xorriso, boss_iter, disk_path, iso_rr_path,
|
||||||
@ -7134,7 +7147,7 @@ int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter,
|
|||||||
|
|
||||||
} else if(compare_result&(1)) {
|
} else if(compare_result&(1)) {
|
||||||
/* disk_adr not existing */
|
/* disk_adr not existing */
|
||||||
ret= Xorriso_rmi(xorriso, boss_iter, iso_rr_path, 1);
|
ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, iso_rr_path, 1);
|
||||||
deleted= 1;
|
deleted= 1;
|
||||||
sprintf(xorriso->info_text, "Deleted ");
|
sprintf(xorriso->info_text, "Deleted ");
|
||||||
|
|
||||||
@ -8545,8 +8558,10 @@ not_enough_arguments:;
|
|||||||
Xorriso_pacifier_reset(xorriso, 0);
|
Xorriso_pacifier_reset(xorriso, 0);
|
||||||
mem_lut= xorriso->last_update_time;
|
mem_lut= xorriso->last_update_time;
|
||||||
}
|
}
|
||||||
} else if(strcmp(cpt, "in_iso")==0 || strcmp(cpt, "not_in_iso")==0 ||
|
} else if(strcmp(cpt, "in_iso")==0 ||
|
||||||
strcmp(cpt, "add_missing")==0) {
|
strcmp(cpt, "not_in_iso")==0 ||
|
||||||
|
strcmp(cpt, "add_missing")==0 ||
|
||||||
|
strcmp(cpt, "empty_iso_dir")==0) {
|
||||||
if(i+1>=end_idx)
|
if(i+1>=end_idx)
|
||||||
goto not_enough_arguments;
|
goto not_enough_arguments;
|
||||||
i++;
|
i++;
|
||||||
@ -8558,6 +8573,8 @@ not_enough_arguments:;
|
|||||||
action= 15;
|
action= 15;
|
||||||
else if(strcmp(cpt, "add_missing")==0)
|
else if(strcmp(cpt, "add_missing")==0)
|
||||||
action= 18;
|
action= 18;
|
||||||
|
else if(strcmp(cpt, "empty_iso_dir")==0)
|
||||||
|
action= 19;
|
||||||
else
|
else
|
||||||
action= 16;
|
action= 16;
|
||||||
Findjob_set_action_target(job, action, other_path_start, 0);
|
Findjob_set_action_target(job, action, other_path_start, 0);
|
||||||
@ -9797,7 +9814,7 @@ int Xorriso_option_rmi(struct XorrisO *xorriso, int argc, char **argv,
|
|||||||
}
|
}
|
||||||
strcpy(path, eff_path);
|
strcpy(path, eff_path);
|
||||||
|
|
||||||
ret= Xorriso_rmi(xorriso, NULL, path, flag&(1|2));
|
ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, path, flag&(1|2));
|
||||||
if(ret<=0 || xorriso->request_to_abort)
|
if(ret<=0 || xorriso->request_to_abort)
|
||||||
goto problem_handler;
|
goto problem_handler;
|
||||||
if(ret<3) {
|
if(ret<3) {
|
||||||
|
@ -1 +1 @@
|
|||||||
#define Xorriso_timestamP "2008.03.07.075325"
|
#define Xorriso_timestamP "2008.03.07.182411"
|
||||||
|
@ -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
|
/* @param flag bit0= recursion is active
|
||||||
bit1= do not report added files
|
bit1= do not report added files
|
||||||
*/
|
*/
|
||||||
@ -1576,17 +1619,6 @@ cannot_lstat:;
|
|||||||
source_is_dir= 1;
|
source_is_dir= 1;
|
||||||
if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
|
if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
|
||||||
do_not_dive= 1;
|
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 ? */
|
/* does a node exist with this name ? */
|
||||||
@ -1600,7 +1632,7 @@ cannot_lstat:;
|
|||||||
/* handle overwrite situation */;
|
/* handle overwrite situation */;
|
||||||
if(xorriso->do_overwrite==1 ||
|
if(xorriso->do_overwrite==1 ||
|
||||||
(xorriso->do_overwrite==2 && !target_is_dir)) {
|
(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)
|
if(ret<=0)
|
||||||
goto was_problem;
|
goto was_problem;
|
||||||
if(ret==3) {
|
if(ret==3) {
|
||||||
@ -1640,7 +1672,13 @@ cannot_lstat:;
|
|||||||
{ret= 0; goto was_problem;}
|
{ret= 0; goto was_problem;}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef NIX
|
||||||
ret= iso_tree_add_node(volume, dir, srcpt, &node);
|
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) {
|
if(ret<0) {
|
||||||
Xorriso_report_iso_error(xorriso, stbuf_src, ret,
|
Xorriso_report_iso_error(xorriso, stbuf_src, ret,
|
||||||
"Cannot add node to tree", 0, "FAILURE", 1|2);
|
"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 */;
|
/* handle overwrite situation */;
|
||||||
if(xorriso->do_overwrite==1 ||
|
if(xorriso->do_overwrite==1 ||
|
||||||
(xorriso->do_overwrite==2 && !target_is_dir)) {
|
(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)
|
if(ret<=0)
|
||||||
return(ret);
|
return(ret);
|
||||||
if(ret==3) {
|
if(ret==3) {
|
||||||
@ -1953,7 +1991,7 @@ handle_path_node:;
|
|||||||
iso_node_set_uid((IsoNode *) dir, geteuid());
|
iso_node_set_uid((IsoNode *) dir, geteuid());
|
||||||
iso_node_set_gid((IsoNode *) dir, getegid());
|
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,
|
Xorriso_copy_implict_properties(xorriso, dir, img_path, path, disk_path,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
@ -1982,6 +2020,8 @@ attach_source:;
|
|||||||
disk_path_pt= resolved_disk_path;
|
disk_path_pt= resolved_disk_path;
|
||||||
} else
|
} else
|
||||||
disk_path_pt= disk_path;
|
disk_path_pt= disk_path;
|
||||||
|
|
||||||
|
#ifdef NIX
|
||||||
ret= iso_tree_add_node(volume, dir, disk_path_pt, &node);
|
ret= iso_tree_add_node(volume, dir, disk_path_pt, &node);
|
||||||
if(ret<0) {
|
if(ret<0) {
|
||||||
Xorriso_process_msg_queues(xorriso,0);
|
Xorriso_process_msg_queues(xorriso,0);
|
||||||
@ -1993,6 +2033,16 @@ attach_source:;
|
|||||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
||||||
return(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;
|
xorriso->volset_change_pending= 1;
|
||||||
iso_node_set_name(node, apt);
|
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
|
/* @param boss_iter If not NULL then this is an iterator suitable for
|
||||||
iso_dir_iter_remove() which is then to be used instead
|
iso_dir_iter_remove() which is then to be used instead
|
||||||
of iso_node_remove().
|
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"
|
bit2= recursion: do not reassure in mode 2 "tree"
|
||||||
bit3= this is for overwriting and not for plain removal
|
bit3= this is for overwriting and not for plain removal
|
||||||
bit4= count deleted files in xorriso->pacifier_count
|
bit4= count deleted files in xorriso->pacifier_count
|
||||||
|
bit5= with bit0 only remove directory content, not the directory
|
||||||
@return <=0 = error
|
@return <=0 = error
|
||||||
1 = removed simple node
|
1 = removed simple node
|
||||||
2 = removed directory or tree
|
2 = removed directory or tree
|
||||||
3 = did not remove on user revocation
|
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)
|
char *path, int flag)
|
||||||
{
|
{
|
||||||
int ret, is_dir= 0, pl, not_removed= 0, fret;
|
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
|
#ifdef Xorriso_fat_local_meM
|
||||||
char sfe[5*SfileadrL], sub_path[2*SfileadrL];
|
char sfe[5*SfileadrL], sub_path[2*SfileadrL];
|
||||||
#else
|
#else
|
||||||
|
|
||||||
char *sfe= NULL, *sub_path= NULL;
|
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 */
|
/* Avoiding large local memory objects in order to save stack space */
|
||||||
sfe= malloc(5*SfileadrL);
|
sfe= malloc(5*SfileadrL);
|
||||||
@ -2550,12 +2733,22 @@ int Xorriso_rmi(struct XorrisO *xorriso, void *boss_iter,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(flag&1) { /* rm -r */
|
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 */
|
/* 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);
|
ret= iso_dir_get_children((IsoDir *) victim_node, &iter);
|
||||||
Xorriso_process_msg_queues(xorriso,0);
|
Xorriso_process_msg_queues(xorriso,0);
|
||||||
if(ret<0) {
|
if(ret<0) {
|
||||||
|
#endif /* ! Xorriso_rmi_findi_iteR */
|
||||||
|
|
||||||
cannot_create_iter:;
|
cannot_create_iter:;
|
||||||
Xorriso_cannot_create_iter(xorriso, ret, 0);
|
Xorriso_cannot_create_iter(xorriso, ret, 0);
|
||||||
ret= -1; goto ex;
|
ret= -1; goto ex;
|
||||||
@ -2567,13 +2760,25 @@ cannot_create_iter:;
|
|||||||
sub_path[pl]= 0;
|
sub_path[pl]= 0;
|
||||||
}
|
}
|
||||||
sub_name= sub_path+pl;
|
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
|
while(iso_dir_iter_next(iter, &node) == 1
|
||||||
&& !xorriso->request_to_abort) {
|
&& !xorriso->request_to_abort) {
|
||||||
|
#endif
|
||||||
|
|
||||||
name= (char *) iso_node_get_name(node);
|
name= (char *) iso_node_get_name(node);
|
||||||
if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0)
|
if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0)
|
||||||
{ret= 0; goto rm_r_problem_handler;}
|
{ret= 0; goto rm_r_problem_handler;}
|
||||||
strcpy(sub_name, name);
|
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) {
|
if(ret==3 || ret<=0 || xorriso->request_to_abort) {
|
||||||
rm_r_problem_handler:;
|
rm_r_problem_handler:;
|
||||||
not_removed= 1;
|
not_removed= 1;
|
||||||
@ -2582,6 +2787,9 @@ rm_r_problem_handler:;
|
|||||||
goto dir_not_removed;
|
goto dir_not_removed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(flag&32)
|
||||||
|
{ret= 2; goto ex;}
|
||||||
|
|
||||||
if(not_removed) {
|
if(not_removed) {
|
||||||
dir_not_removed:;
|
dir_not_removed:;
|
||||||
sprintf(xorriso->info_text, "Directory not removed: %s",
|
sprintf(xorriso->info_text, "Directory not removed: %s",
|
||||||
@ -2705,8 +2913,14 @@ ex:;
|
|||||||
free(sub_path);
|
free(sub_path);
|
||||||
#endif /* ! Xorriso_fat_local_meM */
|
#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)
|
if(iter!=NULL)
|
||||||
iso_dir_iter_free(iter);
|
iso_dir_iter_free(iter);
|
||||||
|
#endif /* ! Xorriso_rmi_findi_iteR */
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3332,6 +3546,21 @@ int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter,
|
|||||||
IsoDir *origin_dir, *dest_dir;
|
IsoDir *origin_dir, *dest_dir;
|
||||||
IsoNode *node, *iso_node;
|
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);
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, origin, eff_origin, 0);
|
||||||
if(ret<=0)
|
if(ret<=0)
|
||||||
return(ret);
|
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);
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
||||||
return(0);
|
return(0);
|
||||||
} else if(dest_ret>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)
|
if(ret<=0)
|
||||||
return(0);
|
return(0);
|
||||||
if(ret==3) {
|
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);
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
|
||||||
return(-1);
|
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, '/');
|
leafname= strrchr(eff_dest, '/');
|
||||||
if(leafname==NULL)
|
if(leafname==NULL)
|
||||||
leafname= eff_dest;
|
leafname= eff_dest;
|
||||||
@ -3453,12 +3673,19 @@ int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter,
|
|||||||
if(ret<0) {
|
if(ret<0) {
|
||||||
Xorriso_process_msg_queues(xorriso,0);
|
Xorriso_process_msg_queues(xorriso,0);
|
||||||
Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot set name", 0,
|
Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot set name", 0,
|
||||||
"FATAL", 1);
|
"FAILURE", 1);
|
||||||
sprintf(xorriso->info_text, "Internal error on rename: failed to set name");
|
|
||||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
|
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
Xorriso_process_msg_queues(xorriso,0);
|
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);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3813,11 +4040,11 @@ int Xorriso_findi_action(struct XorrisO *xorriso, struct FindjoB *job,
|
|||||||
if(ret>0) {
|
if(ret>0) {
|
||||||
if(S_ISDIR(dir_stbuf.st_mode))
|
if(S_ISDIR(dir_stbuf.st_mode))
|
||||||
hflag= 2;
|
hflag= 2;
|
||||||
ret= Xorriso_rmi(xorriso, boss_iter, abs_path, hflag);
|
ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, hflag);
|
||||||
deleted= 1;
|
deleted= 1;
|
||||||
}
|
}
|
||||||
} else if(action==2) { /* rm_r */
|
} 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;
|
deleted= 1;
|
||||||
} else if(action==3) {
|
} 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
|
/* @param flag bit0= recursion
|
||||||
bit1= do not count deleted files with rm and rm_r
|
bit1= do not count deleted files with rm and rm_r
|
||||||
@return <=0 error, 1= ok , 2= dir node and path has been deleted
|
@return <=0 error, 1= ok , 2= dir node and path has been deleted
|
||||||
@ -4131,13 +4235,8 @@ ex:;
|
|||||||
|
|
||||||
Xorriso_process_msg_queues(xorriso,0);
|
Xorriso_process_msg_queues(xorriso,0);
|
||||||
|
|
||||||
#ifdef Xorriso_findi_new_iteR
|
|
||||||
Xorriso_findi_iter(xorriso, dir_node, &mem, &iter, &node_array, &node_count,
|
Xorriso_findi_iter(xorriso, dir_node, &mem, &iter, &node_array, &node_count,
|
||||||
&node_idx, &node, (1<<31));
|
&node_idx, &node, (1<<31));
|
||||||
#else
|
|
||||||
if(iter!=NULL)
|
|
||||||
iso_dir_iter_free(iter);
|
|
||||||
#endif
|
|
||||||
if(ret<=0)
|
if(ret<=0)
|
||||||
return(ret);
|
return(ret);
|
||||||
if(deleted)
|
if(deleted)
|
||||||
|
@ -78,7 +78,7 @@ int Xorriso_format_media(struct XorrisO *xorriso, int flag);
|
|||||||
2 = removed directory or tree
|
2 = removed directory or tree
|
||||||
3 = did not remove on user revocation
|
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);
|
char *path, int flag);
|
||||||
|
|
||||||
/* @param flag bit0= long format
|
/* @param flag bit0= long format
|
||||||
|
Loading…
Reference in New Issue
Block a user