New options -cpax, -cp_rx, cp_rax to restore files and trees from ISO to disk

This commit is contained in:
2008-06-05 16:51:04 +00:00
parent 6ab1b7cd7d
commit 85eba6610a
4 changed files with 502 additions and 137 deletions

View File

@ -69,6 +69,11 @@ int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume,
off_t offset, off_t cut_size,
IsoNode **node, int flag);
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);
#define LIBISO_ISDIR(node) (iso_node_get_type(node) == LIBISO_DIR)
#define LIBISO_ISREG(node) (iso_node_get_type(node) == LIBISO_FILE)
@ -2433,11 +2438,12 @@ unsupported_type:;
/* @param flag bit0= minimal transfer: access permissions only
bit1= keep directory open: keep owner, allow rwx for owner
and push directory onto xorriso->perm_stack
*/
int Xorriso_restore_properties(struct XorrisO *xorriso, char *disk_path,
IsoNode *node, int flag)
{
int ret;
int ret, is_dir= 0;
mode_t mode;
uid_t uid;
gid_t gid;
@ -2455,9 +2461,22 @@ int Xorriso_restore_properties(struct XorrisO *xorriso, char *disk_path,
}
uid= stbuf.st_uid;
is_dir= S_ISDIR(stbuf.st_mode);
mode= iso_node_get_permissions(node);
if(S_ISDIR(stbuf.st_mode) && (flag&2))
if(is_dir && (flag&2)) {
ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
if(ret<=0)
return(0);
ret= Permstack_push(&(xorriso->perm_stack), disk_path, &stbuf, 0);
if(ret<=0) {
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
strcpy(xorriso->info_text,
"Cannot memorize permissions for disk directory");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
return(-1);
}
mode|= S_IRUSR|S_IWUSR|S_IXUSR;
}
ret= chmod(disk_path, mode);
if(ret==-1) {
sprintf(xorriso->info_text,
@ -2531,17 +2550,7 @@ int Xorriso_restore_implicit_properties(struct XorrisO *xorriso,
ret= Xorriso_fake_stbuf(xorriso, nfi, &stbuf, &node, 0);
if(ret<=0)
return(0);
if(flag&4) {
ret= Permstack_push(&(xorriso->perm_stack), nd, &stbuf, 0);
if(ret<=0) {
Xorriso_msgs_submit(xorriso, 0, nfd, 0, "ERRFILE", 0);
strcpy(xorriso->info_text,
"Cannot memorize permissions for disk directory");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
return(-1);
}
}
ret= Xorriso_restore_properties(xorriso, nd, node, !!(flag&2));
ret= Xorriso_restore_properties(xorriso, nd, node, ((flag>>1)&3));
if(ret<=0)
return(ret);
sprintf(xorriso->info_text,
@ -2731,6 +2740,394 @@ ex:;
}
/* Handle overwrite situation in disk filesystem.
@param flag
bit4= return 3 on rejection by exclusion or user
*/
int Xorriso_restore_overwrite(struct XorrisO *xorriso, char *img_path,
char *path, char *nominal_path,
struct stat *stbuf, int flag)
{
int ret;
char sfe[5*SfileadrL], sfe2[5*SfileadrL];
Xorriso_process_msg_queues(xorriso,0);
if(xorriso->do_overwrite==1 ||
(xorriso->do_overwrite==2 && !S_ISDIR(stbuf->st_mode))) {
ret= Xorriso_rmx(xorriso, (off_t) 0, path, 1|8);
if(ret<=0)
return(ret);
if(ret==3) {
sprintf(xorriso->info_text, "User revoked restoring of (ISO) file: %s",
Text_shellsafe(img_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
return(3*!!(flag&16));
}
return(1);
}
Xorriso_msgs_submit(xorriso, 0, nominal_path, 0, "ERRFILE", 0);
sprintf(xorriso->info_text,
"While restoring %s : %s exists and may not be overwritten",
Text_shellsafe(nominal_path, sfe, 0), strcmp(nominal_path, path)==0 ?
"file object" : Text_shellsafe(path, sfe2, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
/*
@param flag
bit1= do not report copied files
bit2= -follow, -not_*: this is not a command parameter
bit3= keep directory open: keep owner, allow rwx for owner
bit6= this is a copy action: do not fake times and ownership
@return <=0 = error , 1 = added leaf file object , 2 = added directory ,
*/
int Xorriso_restore_disk_object(struct XorrisO *xorriso,
char *img_path, IsoNode *node,
char *disk_path,
int flag)
{
int ret, i, split_count= 0, partno, total_parts, leaf_is_split= 0;
off_t offset, bytes, total_bytes;
char *part_name, part_path[SfileadrL], *img_path_pt;
char sfe[5*SfileadrL], sfe2[5*SfileadrL];
IsoImage *volume;
IsoNode *part_node, *first_part_node= NULL;
struct SplitparT *split_parts= NULL;
struct stat stbuf;
ret= Xorriso_get_volume(xorriso, &volume, 0);
if(ret<=0)
goto ex;
if(LIBISO_ISDIR(node) && xorriso->do_concat_split)
leaf_is_split= Xorriso_identify_split(xorriso, img_path, node,
&split_parts, &split_count, &stbuf, 1|2);
if(leaf_is_split) {
/* map all files in directory img_path into regular file disk_path */
for(i=0 ; i<split_count; i++) {
Splitparts_get(split_parts, i, &part_name, &partno, &total_parts,
&offset, &bytes, &total_bytes, 0);
strcpy(part_path, img_path);
if(Sfile_add_to_path(part_path, part_name, 0)<=0) {
Xorriso_much_too_long(xorriso, strlen(img_path)+strlen(part_name)+1, 2);
goto restoring_failed;
}
ret= Xorriso_node_from_path(xorriso, volume, part_path, &part_node, 0);
if(ret<=0)
goto restoring_failed;
if(i==0)
first_part_node= part_node;
if(offset+bytes>total_bytes)
bytes= total_bytes-offset;
ret= Xorriso_tree_restore_node(xorriso, part_node, part_path, disk_path,
offset, bytes,
(!!(flag&64)) | 2 | (flag&4) | 8);
if(ret<=0)
goto restoring_failed;
}
if(first_part_node!=NULL)
Xorriso_restore_properties(xorriso, disk_path, first_part_node,
!!(flag&64));
goto went_well;
}
#ifdef Osirrox_not_yeT
if(resolve_link) {
ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0);
if(ret<=0)
goto ex;
disk_path_pt= resolved_disk_path;
} else
#endif /* Osirrox_not_yeT */
img_path_pt= img_path;
ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, disk_path,
(off_t) 0, (off_t) 0,
(flag&(4|8)) | !!(flag&64));
if(ret>0 && (flag&8))
ret= Xorriso_restore_properties(xorriso, disk_path, node, 2 | !!(flag&64));
if(ret<=0) {
restoring_failed:;
sprintf(xorriso->info_text, "Restoring 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);
{ret= 0; goto ex;}
}
if(ret==2)
{ret= 3; goto ex;}
went_well:;
xorriso->pacifier_count++;
if(xorriso->pacifier_count%100 && !(flag&2))
Xorriso_pacifier_callback(xorriso, "files restored",
xorriso->pacifier_count,
xorriso->pacifier_total, "", 0);
ret= 1;
ex:;
if(split_parts!=NULL)
Splitparts_destroy(&split_parts, split_count, 0);
return(ret);
}
/* @param flag bit0= recursion is active
bit1= do not report restored files
bit6= this is a copy action: do not fake times and ownership
*/
int Xorriso_restore_tree(struct XorrisO *xorriso, IsoDir *dir,
char *img_dir_path, char *disk_dir_path,
off_t boss_mem,
struct LinkiteM *link_stack, int flag)
{
IsoImage *volume;
IsoNode *node;
IsoDirIter *iter= NULL;
IsoNode **node_array= NULL;
int node_count, node_idx;
int ret, target_is_dir, source_is_dir, source_is_link, fret, was_failure= 0;
int do_not_dive, source_is_split= 0, len_dp, len_ip, stbuf_ret, hflag, hret;
char *name, *disk_name, *leaf_name, *srcpt, *stbuf_src= "";
struct stat stbuf, target_stbuf;
struct LinkiteM *own_link_stack;
char *sfe= NULL, *sfe2= NULL;
char *disk_path= NULL, *img_path= NULL, *link_target= NULL;
off_t mem;
struct PermiteM *perm_stack_mem;
perm_stack_mem= xorriso->perm_stack;
/* Avoiding large local memory objects in order to save stack space */
sfe= malloc(5*SfileadrL);
sfe2= malloc(5*SfileadrL);
disk_path= malloc(2*SfileadrL);
img_path= malloc(2*SfileadrL);
link_target= malloc(SfileadrL);
if(sfe==NULL || sfe2==NULL || disk_path==NULL || img_path==NULL ||
link_target==NULL) {
Xorriso_no_malloc_memory(xorriso, &sfe, 0);
{ret= -1; goto ex;}
}
own_link_stack= link_stack;
ret= Xorriso_get_volume(xorriso, &volume, 0);
if(ret<=0)
goto ex;
stbuf_src= img_dir_path;
node= (IsoNode *) dir;
ret= Xorriso_fake_stbuf(xorriso, stbuf_src, &stbuf, &node, 1);
if(ret<=0) {
Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0);
sprintf(xorriso->info_text,"Cannot open as (ISO) source directory: %s",
Text_shellsafe(img_dir_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
{ret= 0; goto ex;}
}
#ifdef Osirrox_not_yeT
dev_t dir_dev;
dir_dev= stbuf.st_dev;
if(S_ISLNK(stbuf.st_mode)) {
if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
{ret= 2; goto ex;}
stbuf_src= disk_dir_path;
if(stat(disk_dir_path, &stbuf)==-1)
goto cannot_open_dir;
if(dir_dev != stbuf.st_dev &&
!(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1))))
{ret= 2; goto ex;}
}
#endif /* Osirrox_not_yeT */
if(!S_ISDIR(stbuf.st_mode)) {
Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0);
sprintf(xorriso->info_text,"Is not a directory in ISO image: %s",
Text_shellsafe(img_dir_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
{ret= 0; goto ex;}
}
mem= boss_mem;
ret= Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count,
&node_idx, &node, 1|4);
if(ret<=0)
goto ex;
if(Sfile_str(img_path, img_dir_path,0)<=0) {
much_too_long:;
Xorriso_much_too_long(xorriso, SfileadrL, 2);
{ret= 0; goto ex;}
}
if(img_path[0]==0 || img_path[strlen(img_path)-1]!='/')
strcat(img_path,"/");
name= img_path+strlen(img_path);
if(Sfile_str(disk_path, disk_dir_path, 0)<=0)
goto much_too_long;
if(disk_path[0] || disk_path[strlen(disk_path)-1]!='/')
strcat(disk_path,"/");
disk_name= disk_path+strlen(disk_path);
len_dp= strlen(disk_path);
len_ip= strlen(img_path);
while(1) { /* loop over ISO directory content */
stbuf_src= "";
#ifdef Osirrox_not_yeT
Linkitem_reset_stack(&own_link_stack, link_stack, 0);
#endif
srcpt= img_path;
Xorriso_process_msg_queues(xorriso,0);
ret= Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count,
&node_idx, &node, 0);
if(ret<0)
goto ex;
if(ret==0 || xorriso->request_to_abort)
break;
leaf_name= (char *) iso_node_get_name(node);
if(Xorriso_much_too_long(xorriso, len_dp + strlen(leaf_name)+1, 0)<=0)
{ret= 0; goto was_problem;}
if(Xorriso_much_too_long(xorriso, len_ip + strlen(leaf_name)+1, 0)<=0)
{ret= 0; goto was_problem;}
/* name is a pointer into img_path */
strcpy(name, leaf_name);
strcpy(disk_name, leaf_name);
stbuf_src= srcpt;
ret= Xorriso_fake_stbuf(xorriso, img_path, &stbuf, &node, 1);
if(ret<=0)
goto was_problem;
source_is_dir= 0;
source_is_link= S_ISLNK(stbuf.st_mode);
#ifdef Osirrox_not_yeT
if(xorriso->do_follow_links && source_is_link) {
/* Xorriso_hop_link checks for wide link loops */
ret= Xorriso_hop_link(xorriso, srcpt, &own_link_stack, &hstbuf, 0);
if(ret<0)
goto was_problem;
if(ret==1) {
ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 0);
if(ret<=0)
goto was_problem;
srcpt= link_target;
stbuf_src= srcpt;
if(lstat(srcpt, &stbuf)==-1)
goto cannot_lstat;
} else {
if(Xorriso_eval_problem_status(xorriso, 0, 1|2)<0)
{ret= 0; goto was_problem;}
}
} else if (S_ISLNK(stbuf.st_mode)) {
ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1);
if(ret<=0)
goto was_problem;
}
#endif /* Osirrox_not_yeT */
do_not_dive= 0;
if(S_ISDIR(stbuf.st_mode))
source_is_dir= 1;
source_is_split= 0;
if(source_is_dir)
source_is_split= Xorriso_is_split(xorriso, img_path, node, 1|2);
if(source_is_split)
do_not_dive= 1;
/* does a disk file exist with this name ? */
stbuf_ret= lstat(disk_path, &target_stbuf);
if(stbuf_ret!=-1) {
target_is_dir= S_ISDIR(target_stbuf.st_mode);
if(!(target_is_dir && (source_is_dir && !source_is_split))) {
Xorriso_process_msg_queues(xorriso,0);
ret= Xorriso_restore_overwrite(xorriso, img_path, disk_path, disk_path,
&target_stbuf, 0);
if(ret<=0)
goto was_problem;
stbuf_ret= -1;
}
}
if(stbuf_ret!=-1) { /* (Can only happen with directory) */
/* ??? >>> eventually open access to existing directory ? */;
} else {
hflag= 4 | (flag & (2|64));
if(source_is_dir && !do_not_dive)
hflag|= 8; /* keep directory open for user */
ret= Xorriso_restore_disk_object(xorriso, img_path, node, disk_path,
hflag);
if(ret<=0)
goto was_problem;
}
if(source_is_dir && !do_not_dive) {
ret= Xorriso_restore_tree(xorriso, (IsoDir *) node,
img_path, disk_path, mem,
own_link_stack, 1|(flag&2));
/* eventually restore exact access permissions of directory */
hret= Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso,
!!(flag&64));
if(hret<=0 && hret<ret)
ret= hret;
if(ret<=0)
goto was_problem;
}
continue; /* regular bottom of loop */
was_problem:;
was_failure= 1;
fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
if(fret<0)
goto ex;
Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, !!(flag&64));
}
ret= 1;
ex:
Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, !!(flag&64));
if(sfe!=NULL)
free(sfe);
if(sfe2!=NULL)
free(sfe2);
if(disk_path!=NULL)
free(disk_path);
if(img_path!=NULL)
free(img_path);
if(link_target!=NULL)
free(link_target);
Xorriso_findi_iter(xorriso, dir, &mem, &iter, &node_array, &node_count,
&node_idx, &node, (1<<31));
Xorriso_process_msg_queues(xorriso,0);
#ifdef Osirrox_not_yeT
Linkitem_reset_stack(&own_link_stack, link_stack, 0);
#endif
if(ret<=0)
return(ret);
return(!was_failure);
}
/*
@param flag
>>> bit0= mkdir: graft in as empty directory, not as copy from iso
@ -2747,15 +3144,12 @@ int Xorriso_restore(struct XorrisO *xorriso,
char *img_path, char *disk_path, int flag)
{
IsoImage *volume;
char path[SfileadrL], *apt, *npt, sfe[5*SfileadrL], sfe2[5*SfileadrL];
char *img_path_pt, *part_name;
IsoNode *node= NULL, *part_node, *first_part_node= NULL;
char path[SfileadrL], *apt, *npt, sfe[5*SfileadrL];
IsoNode *node= NULL;
int done= 0, is_dir= 0, ret, target_is_dir, source_is_dir, stbuf_ret, hret;
int leaf_is_split= 0, source_is_split= 0, split_count, partno, total_parts, i;
off_t offset, bytes, total_bytes;
int leaf_is_split= 0, source_is_split= 0;
struct stat stbuf, target_stbuf;
struct PermiteM *perm_stack_mem;
struct SplitparT *split_parts= NULL;
perm_stack_mem= xorriso->perm_stack;
@ -2802,8 +3196,7 @@ int Xorriso_restore(struct XorrisO *xorriso,
ret= 0; goto ex;
}
if(is_dir && xorriso->do_concat_split)
leaf_is_split= Xorriso_identify_split(xorriso, img_path, node,
&split_parts, &split_count, &stbuf, 1|2);
leaf_is_split= Xorriso_is_split(xorriso, img_path, node, 1|2);
}
for(npt= apt; !done; apt= npt+1) {
npt= strchr(apt, '/');
@ -2825,32 +3218,13 @@ int Xorriso_restore(struct XorrisO *xorriso,
if(stbuf_ret!=-1) {
target_is_dir= S_ISDIR(target_stbuf.st_mode);
if(!(target_is_dir && (source_is_dir && !source_is_split))) {
Xorriso_process_msg_queues(xorriso,0);
/* handle overwrite situation */
if(xorriso->do_overwrite==1 ||
(xorriso->do_overwrite==2 && !target_is_dir)) {
ret= Xorriso_rmx(xorriso, (off_t) 0, path, 1|8);
if(ret<=0)
goto ex;
if(ret==3) {
sprintf(xorriso->info_text, "User revoked restoring of: %s",
Text_shellsafe(disk_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
{ret= 3*!!(flag&16); goto ex;}
}
stbuf_ret= -1;
goto handle_path_node;
}
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
sprintf(xorriso->info_text,
"While restoring '%s' : '%s' exists and may not be overwritten",
disk_path, path);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
{ret= 0; goto ex;}
ret= Xorriso_restore_overwrite(xorriso, img_path, path, disk_path,
&target_stbuf, flag&16);
if(ret<=0 || ret==3)
goto ex;
stbuf_ret= -1; /* now it is removed */
}
}
handle_path_node:;
if(stbuf_ret==-1 && (source_is_dir && !source_is_split)) {
/* make a directory */
ret= mkdir(path, 0777);
@ -2881,81 +3255,20 @@ attach_source:;
/* directory was created above */;
} else if(is_dir && !source_is_split) {
Xorriso_restore_properties(xorriso, disk_path, node, !!(flag&64));
#ifdef Osirrox_not_yeT
/* >>> */
Xorriso_restore_properties(xorriso, disk_path, node, 2 | !!(flag&64));
if(!(flag&32)) {
ret= Xorriso_add_tree(xorriso, dir, img_path, path, NULL,
flag&2);
ret= Xorriso_restore_tree(xorriso, (IsoDir *) node, img_path, path,
(off_t) 0, NULL, flag&(2|64));
if(ret<=0)
goto ex;
if(!(flag&64)) /* set timestamps which Permstack_pop() will not set */
Xorriso_restore_properties(xorriso, disk_path, node, 2);
}
#endif
} else {
if(source_is_split) {
/* map all files in directory img_path into regular file disk_path */
for(i=0 ; i<split_count; i++) {
Splitparts_get(split_parts, i, &part_name, &partno, &total_parts,
&offset, &bytes, &total_bytes, 0);
strcpy(sfe2, img_path);
if(Sfile_add_to_path(sfe2, part_name, 0)<=0) {
Xorriso_much_too_long(xorriso,
strlen(img_path)+strlen(part_name)+1, 2);
goto restoring_failed;
}
ret= Xorriso_node_from_path(xorriso, volume, sfe2, &part_node, 0);
if(ret<=0)
goto restoring_failed;
if(i==0)
first_part_node= part_node;
if(offset+bytes>total_bytes)
bytes= total_bytes-offset;
ret= Xorriso_tree_restore_node(xorriso, part_node, sfe2, path,
offset, bytes,
(!!(flag&64)) | 2 | (flag&4) | 8);
if(ret<=0)
goto restoring_failed;
}
if(first_part_node!=NULL)
Xorriso_restore_properties(xorriso, path, first_part_node,
!!(flag&64));
break;
#ifdef Osirrox_not_yeT
} else if(resolve_link) {
ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0);
if(ret<=0)
goto ex;
disk_path_pt= resolved_disk_path;
#endif /* Osirrox_not_yeT */
} else
img_path_pt= img_path;
ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, path,
(off_t) 0, (off_t) 0,
(flag&4) | !!(flag&64));
if(ret<=0) {
restoring_failed:;
sprintf(xorriso->info_text, "Restoring 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);
{ret= 0; goto ex;}
}
if(ret==2)
{ret= 3; goto ex;}
xorriso->pacifier_count++;
if(xorriso->pacifier_count%100 && !(flag&2))
Xorriso_pacifier_callback(xorriso, "files restored",
xorriso->pacifier_count,
xorriso->pacifier_total, "", 0);
ret= Xorriso_restore_disk_object(xorriso, img_path, node, path,
flag & (2|4|64));
if(ret<=0)
goto ex;
}
} else
*npt= '/';
@ -2965,11 +3278,9 @@ restoring_failed:;
ex:;
/* restore exact access permissions of stacked paths */
hret= Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso,
!!(flag&64));
2 | !!(flag&64));
if(hret<=0 && hret<ret)
ret= hret;
if(split_parts!=NULL)
Splitparts_destroy(&split_parts, split_count, 0);
return(ret);
}
@ -6058,7 +6369,7 @@ int Xorriso_is_split(struct XorrisO *xorriso, char *path, void *node,
struct stat stbuf;
ret= Xorriso_identify_split(xorriso, path, node, &split_parts,
&split_count, &stbuf, flag&1);
&split_count, &stbuf, flag & 3);
if(split_parts!=NULL)
Splitparts_destroy(&split_parts, split_count, 0);
return(ret>0);