You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4038 lines
124 KiB
4038 lines
124 KiB
|
|
/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images. |
|
|
|
Copyright 2007-2013 Thomas Schmitt, <scdbackup@gmx.net> |
|
|
|
Provided under GPL version 2 or later. |
|
|
|
This file contains functions which manipulate the libisofs tree model. |
|
*/ |
|
|
|
#ifdef HAVE_CONFIG_H |
|
#include "../config.h" |
|
#endif |
|
|
|
#include <ctype.h> |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <sys/stat.h> |
|
#include <sys/time.h> |
|
#include <time.h> |
|
#include <errno.h> |
|
|
|
|
|
#include "xorriso.h" |
|
#include "xorriso_private.h" |
|
#include "xorrisoburn.h" |
|
|
|
#include "lib_mgt.h" |
|
#include "iso_img.h" |
|
#include "iso_tree.h" |
|
#include "iso_manip.h" |
|
#include "sort_cmp.h" |
|
#include "parse_exec.h" |
|
|
|
|
|
|
|
/* @param flag bit0= give directory x-permission where is r-permission |
|
bit1= do not transfer ACL or xattr |
|
bit2= record dev,inode (only if enabled by xorriso) |
|
bit5= transfer ACL or xattr from eventual link target |
|
*/ |
|
int Xorriso_transfer_properties(struct XorrisO *xorriso, struct stat *stbuf, |
|
char *disk_path, IsoNode *node, int flag) |
|
{ |
|
mode_t mode; |
|
int ret= 1; |
|
size_t num_attrs= 0, *value_lengths= NULL; |
|
char **names= NULL, **values= NULL; |
|
|
|
mode= stbuf->st_mode; |
|
|
|
if((!(flag & 2)) && !(xorriso->do_aaip & 1)) |
|
/* Will drop ACL. Update mode S_IRWXG by eventual group:: ACL entry */ |
|
iso_local_get_perms_wo_acl(disk_path, &mode, flag & 32); |
|
|
|
if((flag&1) && S_ISDIR(mode)) { |
|
if(mode&S_IRUSR) |
|
mode|= S_IXUSR; |
|
if(mode&S_IRGRP) |
|
mode|= S_IXGRP; |
|
if(mode&S_IROTH) |
|
mode|= S_IXOTH; |
|
} |
|
iso_node_set_permissions(node, mode & 07777); |
|
iso_node_set_uid(node, stbuf->st_uid); |
|
iso_node_set_gid(node, stbuf->st_gid); |
|
iso_node_set_atime(node, stbuf->st_atime); |
|
iso_node_set_mtime(node, stbuf->st_mtime); |
|
iso_node_set_ctime(node, stbuf->st_ctime); |
|
|
|
if((xorriso->do_aaip & 5) && !(flag & 2)) { |
|
ret= iso_local_get_attrs(disk_path, &num_attrs, &names, &value_lengths, |
|
&values, ((xorriso->do_aaip & 1) && !(flag & 2)) |
|
| ((!(xorriso->do_aaip & 4)) << 2) |
|
| (flag & 32)); |
|
if(ret < 0) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
Xorriso_report_iso_error(xorriso, disk_path, ret, |
|
"Error when obtaining local ACL and xattr", 0, |
|
"FAILURE", 1 | 2); |
|
ret= 0; goto ex; |
|
} |
|
|
|
/* Preserve namespace isofs, but not ACL or system xattr */ |
|
ret= iso_node_set_attrs(node, num_attrs, names, value_lengths, values, |
|
1 | 8 | 16); |
|
if(ret < 0) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
Xorriso_report_iso_error(xorriso, "", ret, |
|
"Error when setting ACL and xattr to image node", |
|
0, "FAILURE", 1); |
|
ret= 0; goto ex; |
|
} |
|
} |
|
|
|
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) |
|
goto ex; |
|
} |
|
|
|
ret= 1; |
|
ex:; |
|
Xorriso_process_msg_queues(xorriso,0); |
|
iso_local_get_attrs(disk_path, &num_attrs, &names, &value_lengths, |
|
&values, 1 << 15); /* free memory */ |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_graft_split(struct XorrisO *xorriso, IsoImage *volume, |
|
IsoDir *dir, char *disk_path, char *img_name, |
|
char *nominal_source, char *nominal_target, |
|
off_t size, IsoNode **node, int flag) |
|
{ |
|
int ret; |
|
IsoDir *new_dir= NULL; |
|
IsoNode *part_node; |
|
int partno, total_parts; |
|
off_t offset; |
|
char *part_name= NULL; |
|
|
|
Xorriso_alloc_meM(part_name, char, SfileadrL); |
|
|
|
ret= iso_tree_add_new_dir(dir, img_name, &new_dir); |
|
if(ret<0) |
|
goto ex; |
|
*node= (IsoNode *) new_dir; |
|
if(xorriso->update_flags & 1) { |
|
ret= Xorriso_mark_update_merge(xorriso, img_name, node, 1); |
|
if(ret <= 0) |
|
{ret= 0; goto ex;} |
|
} |
|
total_parts= size / xorriso->split_size; |
|
if(size % xorriso->split_size) |
|
total_parts++; |
|
for(partno= 1; partno<=total_parts; partno++) { |
|
offset = xorriso->split_size * (off_t) (partno-1); |
|
Splitpart__compose(part_name, partno, total_parts, offset, |
|
xorriso->split_size, size, 0); |
|
ret= Xorriso_tree_graft_node(xorriso, volume, |
|
new_dir, disk_path, part_name, |
|
nominal_source, nominal_target, |
|
offset, xorriso->split_size, |
|
&part_node, 8); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
sprintf(xorriso->info_text, "Split into %d parts: ", total_parts); |
|
Text_shellsafe(nominal_target, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(part_name); |
|
return(ret); |
|
} |
|
|
|
|
|
/* |
|
@param flag bit0= ISO_NODE_NAME_NOT_UNIQUE exception mode: |
|
Do not issue message. Return existing node into *node. |
|
bit3= cut_out_node: offset and size are valid |
|
bit8= hide in iso_rr |
|
bit9= hide in joliet |
|
bit10= hide in hfsplus |
|
*/ |
|
int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume, |
|
IsoDir *dir, char *disk_path, char *img_name, |
|
char *nominal_source, char *nominal_target, |
|
off_t offset, off_t cut_size, |
|
IsoNode **node, int flag) |
|
{ |
|
int ret, stbuf_valid= 0; |
|
struct stat stbuf; |
|
char *namept; |
|
off_t size= 0; |
|
|
|
if(lstat(disk_path, &stbuf) != -1) { |
|
stbuf_valid= 1; |
|
if(S_ISREG(stbuf.st_mode)) |
|
size= stbuf.st_size; |
|
} |
|
if(flag&8) { |
|
if(cut_size > xorriso->file_size_limit && xorriso->file_size_limit > 0) { |
|
sprintf(xorriso->info_text, |
|
"File piece exceeds size limit of %.f bytes: %.f from ", |
|
(double) xorriso->file_size_limit, (double) cut_size); |
|
Text_shellsafe(disk_path, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, "\n"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(0); |
|
} |
|
ret= iso_tree_add_new_cut_out_node(volume, dir, img_name, disk_path, |
|
offset, cut_size, node); |
|
if(ret<0) |
|
goto ex; |
|
} else { |
|
if(xorriso->split_size > 0 && size > xorriso->split_size) { |
|
ret= Xorriso_graft_split(xorriso, volume, dir, disk_path, img_name, |
|
nominal_source, nominal_target, size, |
|
node, 0); |
|
if(ret<=0) |
|
goto ex; |
|
} else if(size > xorriso->file_size_limit && xorriso->file_size_limit > 0) { |
|
sprintf(xorriso->info_text, |
|
"File exceeds size limit of %.f bytes: ", |
|
(double) xorriso->file_size_limit); |
|
Text_shellsafe(disk_path, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, "\n"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(0); |
|
} else { |
|
ret= iso_tree_add_new_node(volume, dir, img_name, disk_path, node); |
|
if(ret<0) |
|
goto ex; |
|
} |
|
} |
|
if(flag & (256 | 512 | 1024)) { |
|
ret= Xorriso_set_hidden(xorriso, (void *) *node, "", (flag >> 8) & 7, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
} |
|
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) |
|
goto ex; |
|
} |
|
if(xorriso->update_flags & 1) { |
|
ret= Xorriso_mark_update_merge(xorriso, img_name, *node, 1); |
|
if(ret <= 0) |
|
goto ex; |
|
} |
|
|
|
ex:; |
|
if(ret<0) { |
|
if(ret == (int) ISO_NODE_NAME_NOT_UNIQUE && (flag & 1)) { |
|
iso_dir_get_node(dir, img_name, node); |
|
} else { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(ret == (int) ISO_RR_NAME_TOO_LONG || |
|
ret == (int) ISO_RR_NAME_RESERVED || |
|
ret == (int) ISO_RR_PATH_TOO_LONG) |
|
namept= nominal_target; |
|
else |
|
namept= nominal_source; |
|
Xorriso_report_iso_error(xorriso, namept, ret, |
|
"Cannot add node to tree", 0, "FAILURE", 1|2); |
|
} |
|
return(ret); |
|
} |
|
if(LIBISO_ISREG(*node)) |
|
xorriso->pacifier_byte_count+= iso_file_get_size((IsoFile *) *node); |
|
return(1); |
|
} |
|
|
|
|
|
/* |
|
@param boss_iter Opaque handle to be forwarded to actions in ISO image |
|
Set to NULL if calling this function without having |
|
a boss iterator objetc. |
|
@param node Pointer to pointer to existing node, |
|
*node is set to NULL, if the node gets removed. |
|
@param flag bit0= source is directory |
|
bit4= return 3 on rejection by exclusion or user |
|
bit6= do not delete eventually existing node from di_array |
|
bit7= no special handling of split file directories |
|
@return 1= no action was needed, 2= target removed, |
|
3= rejected with bit4, <=0 means error |
|
*/ |
|
int Xoriso_handle_collision(struct XorrisO *xorriso, void *boss_iter, |
|
IsoNode **node, char *img_path, |
|
char *full_img_path, char *disk_path, |
|
char *show_path, int flag) |
|
{ |
|
int ret, target_is_dir, target_is_split, source_is_dir; |
|
|
|
source_is_dir= flag & 1; |
|
target_is_dir= LIBISO_ISDIR(*node); |
|
|
|
target_is_split= 0; |
|
if(target_is_dir && !(flag & 128)) |
|
target_is_split= Xorriso_is_split(xorriso, "", (void *) *node, 1 | 2); |
|
|
|
if(!((target_is_dir && !target_is_split) && source_is_dir)) { |
|
Xorriso_process_msg_queues(xorriso, 0); |
|
|
|
/* 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, img_path, |
|
1 | 8 | (flag & 64)); |
|
if(ret <= 0) |
|
return(ret); |
|
if(ret == 3) { |
|
sprintf(xorriso->info_text, "User revoked adding of: "); |
|
Text_shellsafe(show_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
return(3 * !!(flag & 16)); |
|
} |
|
*node= NULL; |
|
return(2); |
|
} |
|
|
|
if (disk_path[0]) |
|
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); |
|
if(strcmp(full_img_path, img_path) == 0) |
|
sprintf(xorriso->info_text, |
|
"While grafting '%s' : file object exists and may not be overwritten", |
|
img_path); |
|
else |
|
sprintf(xorriso->info_text, |
|
"While grafting '%s' : '%s' exists and may not be overwritten", |
|
full_img_path, img_path); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(0); |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
/* @param flag bit0= recursion is active |
|
bit1= do not report added files |
|
bit6= do not delete eventually existing node from di_array |
|
bit7= no special handling of split file directories |
|
bit8= hide in iso_rr |
|
bit9= hide in joliet |
|
*/ |
|
int Xorriso_add_tree(struct XorrisO *xorriso, IsoDir *dir, |
|
char *img_dir_path, char *disk_dir_path, |
|
struct LinkiteM *link_stack, int flag) |
|
{ |
|
IsoImage *volume; |
|
IsoNode *node; |
|
int ret, source_is_dir, source_is_link, fret, was_failure= 0; |
|
int do_not_dive, hide_attrs; |
|
struct DirseQ *dirseq= NULL; |
|
char *name, *img_name, *srcpt, *stbuf_src= ""; |
|
struct stat stbuf, hstbuf; |
|
dev_t dir_dev; |
|
struct LinkiteM *own_link_stack; |
|
char *sfe= NULL, *sfe2= NULL; |
|
char *disk_path= NULL, *img_path= NULL, *link_target= NULL; |
|
|
|
#define Xorriso_add_handle_collisioN 1 |
|
#define Xorriso_optimistic_add_treE 1 |
|
|
|
#ifndef Xorriso_optimistic_add_treE |
|
#ifndef Xorriso_add_handle_collisioN |
|
int target_is_split= 0, target_is_dir; |
|
#endif |
|
#endif |
|
|
|
/* 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= calloc(SfileadrL, 1); |
|
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= disk_dir_path; |
|
if(lstat(disk_dir_path, &stbuf)==-1) |
|
goto cannot_open_dir; |
|
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;} |
|
} |
|
ret= Dirseq_new(&dirseq, disk_dir_path, 1); |
|
if(ret<0) { |
|
sprintf(xorriso->info_text,"Failed to create source filesystem iterator"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
{ret= -1; goto ex;} |
|
} |
|
if(ret==0) { |
|
cannot_open_dir:; |
|
Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text,"Cannot open as source directory: %s", |
|
Text_shellsafe(disk_dir_path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
if(Sfile_str(disk_path, disk_dir_path,0)<=0) |
|
{ret= -1; goto ex;} |
|
if(disk_path[0]==0 || disk_path[strlen(disk_path)-1]!='/') |
|
strcat(disk_path,"/"); |
|
name= disk_path+strlen(disk_path); |
|
if(Sfile_str(img_path, img_dir_path, 0)<=0) |
|
{ret= -1; goto ex;} |
|
if(img_path[0] == 0) |
|
strcat(img_path, "/"); |
|
else if(img_path[strlen(img_path) - 1] != '/') |
|
strcat(img_path, "/"); |
|
img_name= img_path+strlen(img_path); |
|
|
|
while(1) { /* loop over directory content */ |
|
stbuf_src= ""; |
|
Linkitem_reset_stack(&own_link_stack, link_stack, 0); |
|
srcpt= disk_path; |
|
Xorriso_process_msg_queues(xorriso,0); |
|
ret= Dirseq_next_adr(dirseq,name,0); /* name is a pointer into disk_path */ |
|
if(ret==0) |
|
break; |
|
if(ret<0) { |
|
sprintf(xorriso->info_text,"Failed to obtain next directory entry"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
{ret= -1; goto ex;} |
|
} |
|
|
|
/* Compare exclusions against disk_path resp. name */ |
|
ret= Xorriso_path_is_excluded(xorriso, disk_path, 0); /* (is never param) */ |
|
if(ret<0) |
|
{ret= -1; goto ex;} |
|
if(ret>0) |
|
continue; |
|
/* Check for mkisofs-style hidings */ |
|
hide_attrs= (flag >> 8) & 3; |
|
if(hide_attrs != 3) { |
|
ret= Xorriso_path_is_hidden(xorriso, disk_path, 0); |
|
if(ret<0) |
|
return(ret); |
|
if(ret>=0) |
|
hide_attrs|= ret; |
|
} |
|
|
|
strcpy(img_name, name); |
|
if(Xorriso_much_too_long(xorriso, strlen(img_path), 0)<=0) |
|
{ret= 0; goto was_problem;} |
|
if(Xorriso_much_too_long(xorriso, strlen(srcpt), 0)<=0) |
|
{ret= 0; goto was_problem;} |
|
stbuf_src= srcpt; |
|
if(lstat(srcpt, &stbuf)==-1) { |
|
cannot_lstat:; |
|
Xorriso_msgs_submit(xorriso, 0, srcpt, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, |
|
"Cannot determine attributes of source file %s", |
|
Text_shellsafe(srcpt, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
ret= 0; goto was_problem; |
|
} |
|
source_is_dir= 0; |
|
source_is_link= S_ISLNK(stbuf.st_mode); |
|
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;} |
|
ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1); |
|
if(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; |
|
} |
|
do_not_dive= 0; |
|
if(S_ISDIR(stbuf.st_mode)) { |
|
source_is_dir= 1; |
|
if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount) |
|
do_not_dive= 1; |
|
} |
|
|
|
#ifdef Xorriso_optimistic_add_treE |
|
|
|
ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name, |
|
"", img_path, (off_t) 0, (off_t) 0, |
|
&node, 1 | (hide_attrs << 8)); |
|
if(ret == (int) ISO_NODE_NAME_NOT_UNIQUE) { |
|
ret= Xoriso_handle_collision(xorriso, NULL, &node, img_path, img_path, |
|
srcpt, img_path, |
|
(!!source_is_dir) | (flag & (64 | 128))); |
|
if(ret <= 0) |
|
goto was_problem; |
|
if(node == NULL) { |
|
ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name, |
|
"", img_path, (off_t) 0, (off_t) 0, |
|
&node, (hide_attrs << 8)); |
|
if(ret <= 0) |
|
node= NULL; |
|
} |
|
} |
|
|
|
#else /* Xorriso_optimistic_add_treE */ |
|
|
|
/* does a node exist with this name ? */ |
|
node= NULL; |
|
if(dir != NULL) { |
|
ret= iso_dir_get_node(dir, img_name, &node); |
|
} else { |
|
ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1); |
|
} |
|
if(ret>0) { |
|
target_is_dir= LIBISO_ISDIR(node); |
|
target_is_split= 0; |
|
if(target_is_dir && !(flag & 128)) |
|
target_is_split= Xorriso_is_split(xorriso, "", (void *) node, 1 | 2); |
|
|
|
if(!((target_is_dir && !target_is_split) && source_is_dir)) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
|
|
/* 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 | (flag & 64)); |
|
if(ret<=0) |
|
goto was_problem; |
|
if(ret==3) { |
|
sprintf(xorriso->info_text, "User revoked adding of: %s", |
|
Text_shellsafe(img_path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
ret= 0; goto was_problem; |
|
} |
|
node= NULL; |
|
} else { |
|
Xorriso_msgs_submit(xorriso, 0, srcpt, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, |
|
"While grafting %s : file object exists and may not be overwritten by %s", |
|
Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto was_problem; |
|
} |
|
} |
|
} |
|
|
|
if(node==NULL) { |
|
ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name, |
|
"", img_path, (off_t) 0, (off_t) 0, |
|
&node, (hide_attrs << 8)); |
|
} |
|
|
|
#endif /* Xorriso_optimistic_add_treE */ |
|
|
|
if(node==NULL) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
Xorriso_msgs_submit(xorriso, 0, stbuf_src, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, "Grafting failed: %s = %s", |
|
Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto was_problem; |
|
} |
|
|
|
xorriso->pacifier_count++; |
|
if((xorriso->pacifier_count%100)==0) |
|
Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count, |
|
xorriso->pacifier_total, "", 0); |
|
|
|
Xorriso_set_change_pending(xorriso, 0); |
|
if(source_is_dir) { |
|
if(do_not_dive) { |
|
sprintf(xorriso->info_text, "Did not follow mount point : %s", |
|
Text_shellsafe(disk_path, sfe, 0)); |
|
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 | 64 | 128))); |
|
} |
|
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; |
|
} |
|
|
|
ret= 1; |
|
ex: |
|
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_process_msg_queues(xorriso,0); |
|
Linkitem_reset_stack(&own_link_stack, link_stack, 0); |
|
Dirseq_destroy(&dirseq, 0); |
|
if(ret<=0) |
|
return(ret); |
|
return(!was_failure); |
|
} |
|
|
|
|
|
/* @param flag bit0= cut_out mode : base on leaf parent directory |
|
bit1= do not check and perform hidings |
|
*/ |
|
int Xorriso_copy_implicit_properties(struct XorrisO *xorriso, IsoDir *dir, |
|
char *full_img_path, char *img_path, char *full_disk_path, int flag) |
|
{ |
|
int ret, nfic, nic, nfdc, d, i; |
|
char *nfi= NULL, *ni= NULL, *nfd= NULL, *cpt; |
|
struct stat stbuf; |
|
|
|
Xorriso_alloc_meM(nfi, char, SfileadrL); |
|
Xorriso_alloc_meM(ni, char, SfileadrL); |
|
Xorriso_alloc_meM(nfd, char, SfileadrL); |
|
|
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, full_img_path, nfi, |
|
1|2); |
|
if(ret<=0) |
|
goto ex; |
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, img_path, ni, 1|2); |
|
if(ret<=0) |
|
goto ex; |
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, full_disk_path, nfd, |
|
1|2|4); |
|
if(ret<=0) |
|
goto ex; |
|
nfic= Sfile_count_components(nfi, 0); |
|
nic= Sfile_count_components(ni, 0); |
|
nfdc= Sfile_count_components(nfd, 0); |
|
d= nfic-(flag&1)-nic; |
|
if(d<0) |
|
{ret= -1; goto ex;} |
|
if(d>nfdc) |
|
{ret= 0; goto ex;} |
|
for(i= 0; i<d; i++) { |
|
cpt= strrchr(nfd, '/'); |
|
if(cpt==NULL) |
|
{ret= -1; goto ex;} /* should not happen */ |
|
*cpt= 0; |
|
} |
|
if(nfd[0]==0) |
|
strcpy(nfd, "/"); |
|
if(stat(nfd, &stbuf)==-1) |
|
{ret= 0; goto ex;} |
|
Xorriso_transfer_properties(xorriso, &stbuf, nfd, (IsoNode *) dir, |
|
((flag&1) && d==0) | 4 | 32); |
|
sprintf(xorriso->info_text, "Copied properties for "); |
|
Text_shellsafe(ni, xorriso->info_text, 1); |
|
sprintf(xorriso->info_text+strlen(xorriso->info_text), " from "); |
|
Text_shellsafe(nfd, xorriso->info_text, 1); |
|
if(!((flag&1) && d==0)) |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); |
|
|
|
if(!(flag & 2)) { |
|
/* Check for mkisofs-style hidings */ |
|
ret= Xorriso_path_is_hidden(xorriso, nfd, 0); |
|
if(ret<0) |
|
goto ex; |
|
if(ret>=0) { |
|
/* Hide dir */ |
|
ret= Xorriso_set_hidden(xorriso, (void *) dir, "", ret, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
} |
|
} |
|
ret= 1; |
|
ex: |
|
Xorriso_free_meM(nfi); |
|
Xorriso_free_meM(ni); |
|
Xorriso_free_meM(nfd); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param bit0= copy link target properties rather than link properties |
|
bit1= give directory x-permission where is r-permission |
|
bit2= record dev,inode (only if enabled by xorriso) |
|
*/ |
|
int Xorriso_copy_properties(struct XorrisO *xorriso, |
|
char *disk_path, char *img_path, int flag) |
|
{ |
|
int ret; |
|
IsoNode *node; |
|
struct stat stbuf; |
|
|
|
ret= Xorriso_get_node_by_path(xorriso, img_path, NULL, &node, 0); |
|
if(ret<=0) |
|
return(ret); |
|
if(flag & 1) { |
|
if(stat(disk_path, &stbuf)==-1) |
|
return(0); |
|
} else { |
|
if(lstat(disk_path, &stbuf)==-1) |
|
return(0); |
|
} |
|
Xorriso_transfer_properties(xorriso, &stbuf, disk_path, node, |
|
((flag & 2) >> 1) | ((flag & 1) << 5) | (flag & 4)); |
|
Xorriso_set_change_pending(xorriso, 0); |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_add_symlink(struct XorrisO *xorriso, IsoDir *parent, |
|
char *link_target, char *leaf_name, |
|
char *nominal_path, int flag) |
|
{ |
|
int ret= 0; |
|
IsoSymlink *link= NULL; |
|
|
|
ret= iso_tree_add_new_symlink(parent, leaf_name, link_target, &link); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(ret < 0) { |
|
Xorriso_report_iso_error(xorriso, nominal_path, ret, |
|
"Cannot create symbolic link", 0, "FATAL", 1); |
|
ret= 0; |
|
} |
|
return(ret); |
|
} |
|
|
|
|
|
/* @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 bit0= mkdir: graft in as empty directory, not as copy from disk |
|
bit1= do not report added files |
|
bit2= -follow, -not_*: this is not a command parameter |
|
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 |
|
bit8= hide in iso_rr |
|
bit9= hide in joliet |
|
bit10= ln -s: graft in as symbolic link. |
|
Link target is handed over in parameter disk_path. |
|
@return <=0 = error , 1 = added simple node , 2 = added directory , |
|
3 = rejected |
|
*/ |
|
int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter, |
|
char *disk_path, char *img_path, |
|
off_t offset, off_t cut_size, int flag) |
|
{ |
|
IsoImage *volume; |
|
char *path= NULL, *apt, *npt, *cpt; |
|
char *disk_path_pt, *resolved_disk_path= NULL; |
|
IsoDir *dir= NULL, *hdir; |
|
IsoNode *node; |
|
int done= 0, is_dir= 0, l, ret, source_is_dir, resolve_link= 0; |
|
int hide_attrs; |
|
struct stat stbuf; |
|
|
|
#define Xorriso_graft_handle_collisioN 1 |
|
#define Xorriso_optimistic_graft_iN 1 |
|
|
|
#ifndef Xorriso_optimistic_graft_iN |
|
#ifndef Xorriso_graft_handle_collisioN |
|
int target_is_split, target_is_dir; |
|
#endif |
|
#endif |
|
|
|
Xorriso_alloc_meM(path, char, SfileadrL); |
|
Xorriso_alloc_meM(resolved_disk_path, char, SfileadrL); |
|
|
|
hide_attrs= (flag >> 8) & 3; |
|
if (disk_path == NULL && !(flag & 1)) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Program error: Xorriso_graft_in(): disk_path == NULL && !(flag & 1)", |
|
0, "ABORT", 0); |
|
{ret= -1; goto ex;} |
|
} |
|
if (disk_path == NULL) { |
|
disk_path= ""; |
|
} else { |
|
ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&4)); |
|
if(ret<0) |
|
goto ex; |
|
if(ret>0) |
|
{ret= 3*!!(flag&16); goto ex;} |
|
|
|
/* Check for mkisofs-style hidings */ |
|
if(hide_attrs != 3) { |
|
ret= Xorriso_path_is_hidden(xorriso, disk_path, 0); |
|
if(ret<0) |
|
goto ex; |
|
if(ret>=0) |
|
hide_attrs|= ret; |
|
} |
|
} |
|
|
|
for(cpt= img_path; 1; cpt++) { |
|
cpt= strstr(cpt,"/."); |
|
if(cpt==NULL) |
|
break; |
|
if(cpt[2]=='.') { |
|
if(cpt[3]=='/' || cpt[3]==0) |
|
break; |
|
} else if(cpt[2]=='/' || cpt[2]==0) |
|
break; |
|
} |
|
if(cpt!=NULL) { |
|
if(disk_path[0]) |
|
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, |
|
"Unsupported relative addressing in iso_rr_path "); |
|
Text_shellsafe(img_path, xorriso->info_text, 1); |
|
if(disk_path[0]) { |
|
strcat(xorriso->info_text, " (disk: "); |
|
Text_shellsafe(disk_path, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, ")"); |
|
} |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
ret= Xorriso_get_volume(xorriso, &volume, 0); |
|
if(ret<=0) |
|
goto ex; |
|
|
|
strncpy(path, img_path, SfileadrL - 1); |
|
path[SfileadrL - 1]= 0; |
|
apt= npt= path; |
|
|
|
if(!(flag & (1 | 1024))) { |
|
ret= lstat(disk_path, &stbuf); |
|
if(ret!=-1) { |
|
if(S_ISDIR(stbuf.st_mode)) |
|
is_dir= 1; |
|
else if((stbuf.st_mode&S_IFMT)==S_IFLNK && |
|
(xorriso->do_follow_links || |
|
(xorriso->do_follow_param && !(flag&4)))) { |
|
resolve_link= 1; |
|
ret= stat(disk_path, &stbuf); |
|
if(ret!=-1) { |
|
if(S_ISDIR(stbuf.st_mode)) |
|
is_dir= 1; |
|
} |
|
} |
|
} |
|
if(ret == -1) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, |
|
"Cannot determine attributes of source file "); |
|
Text_shellsafe(disk_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
if(S_ISDIR(stbuf.st_mode)) { |
|
is_dir= 1; |
|
} else { |
|
l= strlen(img_path); |
|
if(l>0) |
|
if(img_path[l-1]=='/') |
|
l= 0; |
|
if(l==0) { |
|
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, "Source "); |
|
Text_shellsafe(disk_path, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, " is not a directory. Target "); |
|
Text_shellsafe(img_path, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, " would be."); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
} |
|
|
|
dir= iso_image_get_root(volume); |
|
if(dir==NULL) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
sprintf(xorriso->info_text, |
|
"While grafting '%s' : no root node available", img_path); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
for(npt= apt; !done; apt= npt+1) { |
|
npt= strchr(apt, '/'); |
|
if(npt==NULL) { |
|
npt= apt+strlen(apt); |
|
done= 1; |
|
} else |
|
*npt= 0; |
|
if(*apt==0) { |
|
*apt= '/'; |
|
apt++; |
|
if(done) |
|
goto attach_source; |
|
continue; |
|
} |
|
source_is_dir= (is_dir || (flag&1) || !done); |
|
|
|
#ifdef Xorriso_optimistic_graft_iN |
|
|
|
/* Directories of the source path are likely to exist already as directory |
|
in the image. |
|
That will cause two lookups with optimistic, and only one with |
|
pessimistic. |
|
So optimism will pay off only with the leaf. I.e. if(done). |
|
*/ |
|
if(source_is_dir) { /* eventually create directory */ |
|
ret= iso_dir_get_node(dir, apt, &node); |
|
if(ret > 0) { |
|
ret= Xoriso_handle_collision(xorriso, boss_iter, &node, path, |
|
img_path, disk_path, |
|
disk_path[0] ? disk_path : img_path, |
|
(!!source_is_dir) | (flag & (16 | 64 | 128))); |
|
if(ret <= 0 || ret == 3) |
|
goto ex; |
|
if(ret == 1 && node != NULL) |
|
dir= (IsoDir *) node; |
|
} else |
|
node= NULL; |
|
if(node == NULL) { |
|
ret= iso_tree_add_new_dir(dir, apt, &hdir); |
|
if(ret < 0) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(disk_path[0]) |
|
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); |
|
Xorriso_report_iso_error(xorriso, img_path, ret, |
|
"Cannot create directory", 0, "FAILURE", 1); |
|
sprintf(xorriso->info_text, |
|
"While grafting '%s' : could not insert '%s'", img_path, path); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
if(xorriso->update_flags & 1) { |
|
ret= Xorriso_mark_update_merge(xorriso, path, (IsoNode *) hdir, 1); |
|
if(ret <= 0) |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
dir= hdir; |
|
Xorriso_set_change_pending(xorriso, 0); |
|
iso_node_set_ctime((IsoNode *) dir, time(NULL)); |
|
iso_node_set_uid((IsoNode *) dir, geteuid()); |
|
iso_node_set_gid((IsoNode *) dir, getegid()); |
|
|
|
if(disk_path[0] && !done) { |
|
/* This not only copies disk directory properties |
|
but also sets eventual hide_attrs */ |
|
Xorriso_copy_implicit_properties(xorriso, dir, img_path, path, |
|
disk_path, !!(flag&8)); |
|
} |
|
} |
|
} |
|
|
|
if(done) { |
|
attach_source:; |
|
if(flag&1) { |
|
/* directory node was created above */; |
|
|
|
} else if(flag & 1024) { |
|
ret= Xorriso_add_symlink(xorriso, dir, disk_path, apt, img_path, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
Xorriso_set_change_pending(xorriso, 0); |
|
|
|
} else if(is_dir) { |
|
Xorriso_transfer_properties(xorriso, &stbuf, disk_path, |
|
(IsoNode *) dir, 4 | 32); |
|
if(!(flag&32)) { |
|
ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL, |
|
flag & (2 | 64 | 128)); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
} 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; |
|
} else |
|
disk_path_pt= disk_path; |
|
|
|
ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt, |
|
disk_path, img_path, offset, cut_size, |
|
&node, 1 | (flag & 8) | (hide_attrs << 8)); |
|
if(ret == (int) ISO_NODE_NAME_NOT_UNIQUE) { |
|
ret= Xoriso_handle_collision(xorriso, boss_iter, &node, img_path, |
|
img_path, disk_path, |
|
disk_path[0] ? disk_path : img_path, |
|
(flag & (16 | 64 | 128))); |
|
if(ret <= 0 || ret == 3) |
|
goto ex; |
|
ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt, |
|
disk_path, img_path, offset, cut_size, |
|
&node, (flag & 8) | (hide_attrs << 8)); |
|
} |
|
if(ret<=0) { |
|
sprintf(xorriso->info_text, "Grafting failed: "); |
|
Text_shellsafe(img_path, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, " = "); |
|
Text_shellsafe(disk_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
Xorriso_set_change_pending(xorriso, 0); |
|
iso_node_set_name(node, apt); |
|
|
|
xorriso->pacifier_count++; |
|
if(xorriso->pacifier_count%100 && !(flag&2)) |
|
Xorriso_pacifier_callback(xorriso, "files added", |
|
xorriso->pacifier_count, |
|
xorriso->pacifier_total, "", 0); |
|
} |
|
} else |
|
*npt= '/'; |
|
|
|
#else /* Xorriso_optimistic_graft_iN */ |
|
|
|
node= NULL; |
|
ret= iso_dir_get_node(dir, apt, &node); |
|
if(ret>0) { |
|
|
|
#ifdef Xorriso_graft_handle_collisioN |
|
|
|
ret= Xoriso_handle_collision(xorriso, boss_iter, &node, path, img_path, |
|
disk_path, |
|
disk_path[0] ? disk_path : img_path, |
|
(!!source_is_dir) | (flag & (16 | 64 | 128))); |
|
if(ret <= 0 || ret == 3) |
|
goto ex; |
|
if(ret == 2) |
|
goto handle_path_node; |
|
|
|
#else /* Xorriso_graft_handle_collisioN */ |
|
|
|
target_is_dir= LIBISO_ISDIR(node); |
|
|
|
target_is_split= 0; |
|
if(target_is_dir && !(flag & 128)) |
|
target_is_split= Xorriso_is_split(xorriso, "", (void *) node, 1 | 2); |
|
|
|
if(!((target_is_dir && !target_is_split) && source_is_dir)) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
|
|
/* 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 | (flag & 64)); |
|
if(ret<=0) |
|
goto ex; |
|
if(ret==3) { |
|
sprintf(xorriso->info_text, "User revoked adding of: "); |
|
if(disk_path[0]) |
|
Text_shellsafe(disk_path, xorriso->info_text, 1); |
|
else |
|
Text_shellsafe(img_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
{ret= 3*!!(flag&16); goto ex;} |
|
} |
|
node= NULL; |
|
goto handle_path_node; |
|
} |
|
|
|
if (disk_path[0]) |
|
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, |
|
"While grafting '%s' : '%s' exists and may not be overwritten", |
|
img_path, path); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
#endif /* ! Xorriso_graft_handle_collisioN */ |
|
|
|
dir= (IsoDir *) node; |
|
} |
|
|
|
handle_path_node:; |
|
if(node==NULL && source_is_dir) { /* make a directory */ |
|
ret= iso_tree_add_new_dir(dir, apt, &hdir); |
|
if(ret<0) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(disk_path[0]) |
|
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); |
|
Xorriso_report_iso_error(xorriso, img_path, ret, |
|
"Cannot create directory", 0, "FAILURE", 1); |
|
sprintf(xorriso->info_text, |
|
"While grafting '%s' : could not insert '%s'", img_path, path); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
if(xorriso->update_flags & 1) { |
|
ret= Xorriso_mark_update_merge(xorriso, path, (IsoNode *) hdir, 1); |
|
if(ret <= 0) |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
dir= hdir; |
|
Xorriso_set_change_pending(xorriso, 0); |
|
iso_node_set_ctime((IsoNode *) dir, time(NULL)); |
|
iso_node_set_uid((IsoNode *) dir, geteuid()); |
|
iso_node_set_gid((IsoNode *) dir, getegid()); |
|
|
|
if(disk_path[0] && !done) |
|
/* This not only copies disk directory properties |
|
but also sets eventual hide_attrs */ |
|
Xorriso_copy_implicit_properties(xorriso, dir, img_path, path, disk_path, |
|
!!(flag&8)); |
|
} |
|
if(done) { |
|
attach_source:; |
|
if(flag&1) { |
|
/* directory node was created above */; |
|
|
|
} else if(flag & 1024) { |
|
ret= Xorriso_add_symlink(xorriso, dir, disk_path, apt, img_path, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
|
|
} else if(is_dir) { |
|
Xorriso_transfer_properties(xorriso, &stbuf, disk_path, |
|
(IsoNode *) dir, 4 | 32); |
|
if(!(flag&32)) { |
|
ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL, |
|
flag & (2 | 64 | 128)); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
} 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; |
|
} else |
|
disk_path_pt= disk_path; |
|
|
|
ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt, |
|
disk_path, img_path, offset, cut_size, |
|
&node, (flag&8) | (hide_attrs << 8)); |
|
if(ret<=0) { |
|
sprintf(xorriso->info_text, "Grafting failed: "); |
|
Text_shellsafe(img_path, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, " = "); |
|
Text_shellsafe(disk_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
Xorriso_set_change_pending(xorriso, 0); |
|
iso_node_set_name(node, apt); |
|
|
|
xorriso->pacifier_count++; |
|
if(xorriso->pacifier_count%100 && !(flag&2)) |
|
Xorriso_pacifier_callback(xorriso, "files added", |
|
xorriso->pacifier_count, |
|
xorriso->pacifier_total, "", 0); |
|
} |
|
} else |
|
*npt= '/'; |
|
|
|
#endif /* ! Xorriso_optimistic_graft_iN */ |
|
|
|
} |
|
|
|
Xorriso_process_msg_queues(xorriso,0); |
|
ret= 1+!!is_dir; |
|
ex:; |
|
Xorriso_free_meM(path); |
|
Xorriso_free_meM(resolved_disk_path); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= -follow: disk_path is not a command parameter |
|
*/ |
|
int Xorriso_cut_out(struct XorrisO *xorriso, char *disk_path, |
|
off_t startbyte, off_t bytecount, char *iso_rr_path, int flag) |
|
{ |
|
int ret; |
|
char *eff_source= NULL, *eff_dest= NULL; |
|
struct stat stbuf; |
|
|
|
Xorriso_alloc_meM(eff_source, char, SfileadrL); |
|
Xorriso_alloc_meM(eff_dest, char, SfileadrL); |
|
|
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_source, |
|
2|4); |
|
if(ret<=0) |
|
goto ex; |
|
ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&1)); |
|
if(ret!=0) |
|
{ret= 0; goto ex;} |
|
|
|
if(lstat(eff_source, &stbuf)==-1) { |
|
Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, "-cut_out: Cannot determine type of "); |
|
Text_shellsafe(eff_source, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
if((stbuf.st_mode&S_IFMT) == S_IFLNK) { |
|
if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1)))) |
|
goto unsupported_type; |
|
if(stat(eff_source, &stbuf)==-1) { |
|
Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, |
|
"-cut_out: Cannot determine link target type of "); |
|
Text_shellsafe(eff_source, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
if(S_ISREG(stbuf.st_mode)) { |
|
if(stbuf.st_size<startbyte) { |
|
Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, |
|
"-cut_out: Byte offset %.f larger than file size %.f", |
|
(double) startbyte, (double) stbuf.st_size); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
} else { |
|
unsupported_type:; |
|
Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, "-cut_out: Unsupported file type (%s) with ", |
|
Ftypetxt(stbuf.st_mode, 0)); |
|
Text_shellsafe(eff_source, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, iso_rr_path, eff_dest, |
|
2); |
|
if(ret<=0) |
|
goto ex; |
|
|
|
ret= Xorriso_graft_in(xorriso, NULL, eff_source, eff_dest, |
|
startbyte, bytecount, 8); |
|
ex:; |
|
Xorriso_free_meM(eff_source); |
|
Xorriso_free_meM(eff_dest); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= do not produce info message on success |
|
bit1= do not raise protest if directory already exists |
|
@return 1=success, |
|
0=was already directory, -1=was other type, -2=other error |
|
*/ |
|
int Xorriso_mkdir(struct XorrisO *xorriso, char *path, int flag) |
|
{ |
|
int ret; |
|
char *eff_path= NULL; |
|
|
|
Xorriso_alloc_meM(eff_path, char, SfileadrL); |
|
|
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 1); |
|
if(ret<0) |
|
{ret= -2; goto ex;} |
|
if(ret>0) { |
|
if(ret == 2 && (flag & 2)) |
|
{ret= 0; goto ex;} |
|
sprintf(xorriso->info_text,"-mkdir: Address already existing "); |
|
Text_shellsafe(eff_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, |
|
(ret==2 ? "WARNING" : "FAILURE"), 0); |
|
{ret= -1 + (ret == 2); goto ex;} |
|
} |
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 2); |
|
if(ret<0) |
|
{ret= -2; goto ex;} |
|
ret= Xorriso_graft_in(xorriso, NULL, NULL, eff_path, (off_t) 0, (off_t) 0, 1); |
|
if(ret<=0) |
|
{ret= -2; goto ex;} |
|
if(!(flag&1)) { |
|
sprintf(xorriso->info_text, "Created directory in ISO image: "); |
|
Text_shellsafe(eff_path, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, "\n"); |
|
Xorriso_info(xorriso, 0); |
|
} |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(eff_path); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @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(). |
|
@param flag bit0= remove whole sub tree: rm -r |
|
bit1= remove empty directory: rmdir |
|
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 |
|
bit6= do not delete eventually existing node from di_array |
|
@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, off_t boss_mem, |
|
char *path, int flag) |
|
{ |
|
int ret, is_dir= 0, pl, not_removed= 0, fret; |
|
IsoNode *victim_node, *node; |
|
IsoDir *boss_node, *root_dir; |
|
IsoDirIter *iter= NULL; |
|
IsoImage *volume; |
|
char *sub_name, *name; |
|
char *sfe= NULL, *sub_path= NULL; |
|
off_t mem; |
|
IsoNode **node_array= NULL; |
|
int node_count= 0, node_idx; |
|
|
|
/* Avoiding large local memory objects in order to save stack space */ |
|
sfe= malloc(5*SfileadrL); |
|
sub_path= malloc(2*SfileadrL); |
|
if(sfe==NULL || sub_path==NULL) { |
|
Xorriso_no_malloc_memory(xorriso, &sfe, 0); |
|
{ret= -1; goto ex;} |
|
} |
|
|
|
#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_rmi() was requested to delete iterated node %s", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
ret= -1; goto ex; |
|
} |
|
#endif /* Libisofs_iso_dir_iter_sufficienT */ |
|
|
|
ret= Xorriso_get_volume(xorriso, &volume, 0); |
|
if(ret<=0) |
|
goto ex; |
|
|
|
if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0) |
|
{ret= 0; goto ex;} |
|
ret= Xorriso_node_from_path(xorriso, volume, path, &victim_node, 0); |
|
if(ret<=0) |
|
goto ex; |
|
root_dir= iso_image_get_root(volume); |
|
if(((void *) root_dir) == ((void *) victim_node) && !(flag & 1)) { |
|
sprintf(xorriso->info_text, "May not delete root directory"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
if(LIBISO_ISDIR(victim_node)) |
|
is_dir= 1; |
|
if(!is_dir) { |
|
if(flag&2) { /* rmdir */ |
|
sprintf(xorriso->info_text, "%s in loaded ISO image is not a directory", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
} else { |
|
if(flag&1) { /* rm -r */ |
|
if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) || |
|
(flag&32) || ((void *) root_dir) == ((void *) victim_node)) { |
|
/* Iterate over subordinates and delete them */ |
|
mem= boss_mem; |
|
|
|
ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, |
|
&iter, &node_array, &node_count, &node_idx, |
|
&node, 1|2); |
|
if(ret<=0) { |
|
cannot_create_iter:; |
|
Xorriso_cannot_create_iter(xorriso, ret, 0); |
|
ret= -1; goto ex; |
|
} |
|
pl= strlen(path); |
|
strcpy(sub_path, path); |
|
if(pl==0 || sub_path[pl-1]!='/') { |
|
sub_path[pl++]= '/'; |
|
sub_path[pl]= 0; |
|
} |
|
sub_name= sub_path+pl; |
|
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; |
|
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, 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; |
|
fret= Xorriso_eval_problem_status(xorriso, ret, 1|2); |
|
if(fret<0) |
|
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", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
if(ret>0) |
|
ret= 3; |
|
goto ex; |
|
} |
|
} |
|
} else { |
|
if(!(flag&2)) { /* not rmdir */ |
|
sprintf(xorriso->info_text, "%s in loaded ISO image is a directory", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
|
|
ret= iso_dir_get_children((IsoDir *) victim_node, &iter); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(ret<0) |
|
goto cannot_create_iter; |
|
if(ret>0) { |
|
if(iso_dir_iter_next(iter, &node) == 1) { |
|
sprintf(xorriso->info_text, |
|
"Directory not empty on attempt to delete: %s", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
} |
|
} |
|
} |
|
|
|
if(((void *) root_dir) == ((void *) victim_node)) |
|
{ret= 2; goto ex;} |
|
|
|
if(xorriso->request_to_abort) |
|
{ret= 3; goto ex;} |
|
boss_node= iso_node_get_parent(victim_node); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(boss_node==NULL) { |
|
sprintf(xorriso->info_text, |
|
"Cannot find parent node of %s in loaded ISO image", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
|
|
while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4))) |
|
&& !xorriso->request_not_to_ask) { |
|
/* ls -ld */ |
|
Xorriso_ls_filev(xorriso, xorriso->wdi, 1, &path, (off_t) 0, 1|2|8); |
|
if(is_dir) /* du -s */ |
|
Xorriso_ls_filev(xorriso, xorriso->wdi, 1, &path, (off_t) 0, 2|4); |
|
if(flag&8) |
|
sprintf(xorriso->info_text, |
|
"File exists. Remove ? n= keep old, y= remove, x= abort, @= stop asking\n"); |
|
else |
|
sprintf(xorriso->info_text, |
|
"Remove above file ? n= keep it, y= remove it, x= abort, @= stop asking\n"); |
|
Xorriso_info(xorriso, 4); |
|
ret= Xorriso_request_confirmation(xorriso, 1|2|4|16); |
|
if(ret<=0) |
|
goto ex; |
|
if(xorriso->request_to_abort) { |
|
sprintf(xorriso->info_text, |
|
"Removal operation aborted by user before file: %s", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
ret= 3; goto ex; |
|
} |
|
if(ret==3) |
|
continue; |
|
if(ret==6) /* yes */ |
|
break; |
|
if(ret==4) { /* yes, do not ask again */ |
|
xorriso->request_not_to_ask= 1; |
|
break; |
|
} |
|
if(ret==1) { /* no */ |
|
sprintf(xorriso->info_text, "Kept in existing state: %s", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
ret= 3; goto ex; |
|
} |
|
} |
|
|
|
if(!(flag & 64)) |
|
Xorriso_invalidate_di_item(xorriso, victim_node, 0); |
|
|
|
#ifdef Libisofs_iso_dir_iter_sufficienT |
|
|
|
if(boss_iter!=NULL) { |
|
ret= iso_dir_iter_remove((IsoDirIter *) boss_iter); |
|
if(ret<0) |
|
ret= -1; |
|
} else |
|
ret= iso_node_remove(victim_node); |
|
|
|
#else /* ! Libisofs_iso_dir_iter_sufficienT */ |
|
|
|
ret= iso_node_remove(victim_node); |
|
|
|
#endif /* Libisofs_iso_dir_iter_sufficienT */ |
|
|
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(ret<0) { |
|
Xorriso_report_iso_error(xorriso, path, ret, "Cannot remove node", 0, |
|
"FATAL", 1); |
|
sprintf(xorriso->info_text, |
|
"Internal failure to remove %s from loaded ISO image", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
ret= -1; goto ex; |
|
} |
|
|
|
if(flag&16) |
|
xorriso->pacifier_count++; |
|
Xorriso_set_change_pending(xorriso, 0); |
|
ret= 1+!!is_dir; |
|
ex:; |
|
if(sfe!=NULL) |
|
free(sfe); |
|
if(sub_path!=NULL) |
|
free(sub_path); |
|
Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter, |
|
&node_array, &node_count, &node_idx, &node, (1<<31)); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_overwrite_dest(struct XorrisO *xorriso, void *boss_iter, |
|
char *eff_dest, int dest_ret, char *activity, |
|
int flag) |
|
{ |
|
int ret; |
|
|
|
if(dest_ret==2 && xorriso->do_overwrite!=1) { |
|
sprintf(xorriso->info_text, "%s: May not overwrite directory: ", activity); |
|
Text_shellsafe(eff_dest, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(0); |
|
} else if (dest_ret==1 && !xorriso->do_overwrite) { |
|
sprintf(xorriso->info_text, "%s: May not overwite: ", activity); |
|
Text_shellsafe(eff_dest, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(0); |
|
} else if(dest_ret>0) { |
|
ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, eff_dest, 1|8); |
|
if(ret<=0) |
|
return(0); |
|
if(ret==3) { |
|
sprintf(xorriso->info_text, "%s: User revoked removal of: ", activity); |
|
Text_shellsafe(eff_dest, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
return(0); |
|
} |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
/* @param boss_iter Opaque handle to be forwarded to actions in ISO image |
|
Set to NULL if calling this function from outside ISO world |
|
*/ |
|
int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter, |
|
char *origin, char *dest, int flag) |
|
{ |
|
int ret, ol, dest_ret; |
|
char *eff_dest= NULL, *dir_adr= NULL, *cpt; |
|
char *leafname, *eff_origin= NULL, *old_leafname; |
|
IsoImage *volume; |
|
IsoDir *origin_dir, *dest_dir; |
|
IsoNode *node, *iso_node; |
|
|
|
Xorriso_alloc_meM(eff_dest, char, SfileadrL); |
|
Xorriso_alloc_meM(dir_adr, char, SfileadrL); |
|
Xorriso_alloc_meM(eff_origin, char, SfileadrL); |
|
|
|
#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 "); |
|
Text_shellsafe(origin, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
{ret= -1; goto ex;} |
|
} |
|
#endif /* Libisofs_iso_dir_iter_sufficienT */ |
|
|
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, origin, eff_origin, 0); |
|
if(ret<=0) |
|
goto ex; |
|
dest_ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest,1); |
|
if(dest_ret<0) |
|
{ret= dest_ret; goto ex;} |
|
if(dest_ret==0) { /* obtain eff_dest address despite it does not exist */ |
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest, 2); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
|
|
/* Prevent that destination is a subordinate of origin |
|
(that would be a black hole plopping out of the universe) */ |
|
ol= strlen(eff_origin); |
|
if(ol==0) { |
|
sprintf(xorriso->info_text, "May not rename root directory"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} else if(strcmp(eff_origin, eff_dest)==0) { |
|
sprintf(xorriso->info_text, "Ignored attempt to rename "); |
|
Text_shellsafe(eff_origin, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, " to itself"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); |
|
{ret= 0; goto ex;} |
|
} else if(strncmp(eff_origin, eff_dest, ol)==0 && |
|
(eff_dest[ol]==0 || eff_dest[ol]=='/')) { |
|
sprintf(xorriso->info_text, "May not rename "); |
|
Text_shellsafe(eff_origin, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, " to its own sub address "); |
|
Text_shellsafe(eff_dest, xorriso->info_text, 1 | 2); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
/* Check whether destination exists and may be not overwriteable */ |
|
ret= Xorriso_overwrite_dest(xorriso, boss_iter, |
|
eff_dest, dest_ret, "Renaming", 0); |
|
if(ret <= 0) |
|
goto ex; |
|
|
|
/* Ensure existence of destination directory */ |
|
strcpy(dir_adr, eff_dest); |
|
cpt= strrchr(dir_adr, '/'); |
|
if(cpt==NULL) |
|
cpt= dir_adr+strlen(dir_adr); |
|
*cpt= 0; |
|
if(dir_adr[0]!=0) { |
|
ret= Xorriso_graft_in(xorriso, boss_iter, NULL, dir_adr, |
|
(off_t) 0, (off_t) 0, 1); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
|
|
/* Move node */ |
|
ret= Xorriso_get_volume(xorriso, &volume, 0); |
|
if(ret<=0) |
|
goto ex; |
|
Xorriso_node_from_path(xorriso, volume, dir_adr, &iso_node, 0); |
|
dest_dir= (IsoDir *) iso_node; |
|
strcpy(dir_adr, eff_origin); |
|
cpt= strrchr(dir_adr, '/'); |
|
if(cpt==NULL) |
|
cpt= dir_adr+strlen(dir_adr); |
|
*cpt= 0; |
|
Xorriso_node_from_path(xorriso, volume, dir_adr, &iso_node, 0); |
|
origin_dir= (IsoDir *) iso_node; |
|
Xorriso_node_from_path(xorriso, volume, eff_origin, &node, 0); |
|
if(dest_dir==NULL || origin_dir==NULL || node==NULL) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
sprintf(xorriso->info_text, |
|
"Internal error on rename: confirmed node turns out as NULL"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
{ret= -1; goto ex;} |
|
} |
|
ret= iso_node_take(node); |
|
if(ret<0) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot take", 0, "FATAL",1); |
|
sprintf(xorriso->info_text, |
|
"Internal error on rename: failed to take node"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
{ret= -1; goto ex;} |
|
} |
|
leafname= strrchr(eff_dest, '/'); |
|
if(leafname==NULL) |
|
leafname= eff_dest; |
|
else |
|
leafname++; |
|
|
|
old_leafname= (char *) iso_node_get_name(node); |
|
if(strcmp(leafname, old_leafname)!=0) |
|
ret= iso_node_set_name(node, leafname); |
|
else |
|
ret= 1; |
|
if(ret<0) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot set name", 0, |
|
"FAILURE", 1); |
|
{ret= -1; goto ex;} |
|
} |
|
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); |
|
{ret= -1; goto ex;} |
|
} |
|
Xorriso_set_change_pending(xorriso, 0); |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(eff_dest); |
|
Xorriso_free_meM(dir_adr); |
|
Xorriso_free_meM(eff_origin); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_cannot_clone(struct XorrisO *xorriso, char *eff_origin, |
|
char *eff_dest, int iso_error, int flag) |
|
{ |
|
Xorriso_report_iso_error(xorriso, eff_dest, iso_error, "Cannot clone", |
|
0, "FAILURE", 1); |
|
sprintf(xorriso->info_text, "Failed to clone "); |
|
Text_shellsafe(eff_origin, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(0); |
|
} |
|
|
|
|
|
/* @param flag bit0= for iso_tree_clone() : merge directories |
|
bit1= do not issue NOTE message |
|
*/ |
|
int Xorriso_clone_tree(struct XorrisO *xorriso, void *boss_iter, |
|
char *origin, char *dest, int flag) |
|
{ |
|
int ret, dest_ret, l; |
|
char *eff_dest= NULL, *eff_origin= NULL, *dir_adr= NULL; |
|
char *leafname; |
|
IsoImage *volume; |
|
IsoDir *new_parent; |
|
IsoNode *origin_node, *dir_node, *new_node; |
|
|
|
Xorriso_alloc_meM(eff_dest, char, SfileadrL); |
|
Xorriso_alloc_meM(eff_origin, char, SfileadrL); |
|
Xorriso_alloc_meM(dir_adr, char, SfileadrL); |
|
|
|
ret= Xorriso_get_volume(xorriso, &volume, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
|
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, origin, eff_origin, 0); |
|
if(ret<=0) |
|
goto ex; |
|
ret= Xorriso_node_from_path(xorriso, volume, eff_origin, &origin_node, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
|
|
dest_ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest,1); |
|
if(dest_ret<0) |
|
{ret= dest_ret; goto ex;} |
|
if(dest_ret > 0) { |
|
if(eff_dest[0] == 0) |
|
strcpy(eff_dest, "/"); |
|
sprintf(xorriso->info_text, |
|
"Cloning: Copy address already exists: "); |
|
Text_shellsafe(eff_dest, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} else { |
|
/* obtain eff_dest address despite it does not exist */ |
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest, 2); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
|
|
/* Obtain parent path and leaf name */ |
|
strcpy(dir_adr, eff_dest); |
|
for(l= strlen(dir_adr); l > 0; ) { |
|
if(dir_adr[l - 1] == '/') |
|
dir_adr[--l]= 0; |
|
else |
|
break; |
|
} |
|
leafname= strrchr(dir_adr, '/'); |
|
if(leafname == NULL) { |
|
leafname= dir_adr; |
|
if (leafname[0] == 0) { |
|
Xorriso_msgs_submit(xorriso, 0, "Empty file name as clone destination", |
|
0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
} else { |
|
*leafname= 0; |
|
leafname++; |
|
if(dir_adr[0] != 0) { |
|
/* Ensure existence of destination directory */ |
|
ret= Xorriso_graft_in(xorriso, boss_iter, NULL, dir_adr, |
|
(off_t) 0, (off_t) 0, 1); |
|
if(ret <= 0) |
|
goto ex; |
|
} |
|
} |
|
|
|
ret= Xorriso_node_from_path(xorriso, volume, dir_adr, &dir_node, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
new_parent= (IsoDir *) dir_node; |
|
|
|
ret = iso_tree_clone(origin_node, new_parent, leafname, &new_node, flag & 1); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(ret < 0) { |
|
Xorriso_cannot_clone(xorriso, eff_origin, eff_dest, ret, 0); |
|
{ret= 0; goto ex;} |
|
} |
|
Xorriso_set_change_pending(xorriso, 0); |
|
if(!(flag & 2)) { |
|
strcpy(xorriso->info_text, "Cloned in ISO image: "); |
|
Text_shellsafe(eff_origin, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, " to "); |
|
Text_shellsafe(eff_dest, xorriso->info_text, 1 | 2); |
|
strcat(xorriso->info_text, "\n"); |
|
Xorriso_info(xorriso, 0); |
|
} |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(eff_dest); |
|
Xorriso_free_meM(eff_origin); |
|
Xorriso_free_meM(dir_adr); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_clone_under(struct XorrisO *xorriso, char *origin, char *dest, |
|
int flag) |
|
{ |
|
int ret, pass; |
|
char *eff_dest= NULL, *eff_origin= NULL, *namept; |
|
IsoDir *origin_dir, *dest_dir; |
|
IsoDirIter *iter= NULL; |
|
IsoNode *origin_node, *new_node; |
|
IsoImage *volume; |
|
|
|
Xorriso_alloc_meM(eff_dest, char, SfileadrL); |
|
Xorriso_alloc_meM(eff_origin, char, SfileadrL); |
|
|
|
ret= Xorriso_get_volume(xorriso, &volume, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
ret= Xorriso_dir_from_path(xorriso, "Copy source", origin, &origin_dir, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
ret= Xorriso_dir_from_path(xorriso, "Copy destination", dest, &dest_dir, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
|
|
for(pass= 0; pass < 2; pass++) { |
|
ret= iso_dir_get_children(origin_dir, &iter); |
|
if(ret < 0) { |
|
Xorriso_cannot_create_iter(xorriso, ret, 0); |
|
{ret= -1; goto ex;} |
|
} |
|
Xorriso_process_msg_queues(xorriso,0); |
|
|
|
while(iso_dir_iter_next(iter, &origin_node) == 1) { |
|
namept= (char *) iso_node_get_name(origin_node); |
|
sprintf(eff_origin, "%s/%s", origin, namept); |
|
sprintf(eff_dest, "%s/%s", dest, namept); |
|
if(pass == 0) { |
|
ret= Xorriso_node_from_path(xorriso, volume, eff_dest, &new_node, 1); |
|
if(ret < 0) |
|
goto ex; |
|
if(ret > 0) { |
|
sprintf(xorriso->info_text, "Cloning: Copy address already exists: "); |
|
Text_shellsafe(eff_dest, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
} else { |
|
ret = iso_tree_clone(origin_node, dest_dir, namept, &new_node, 1); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(ret < 0) { |
|
Xorriso_cannot_clone(xorriso, eff_origin, eff_dest, ret, 0); |
|
ret= 0; goto ex; |
|
} |
|
} |
|
} |
|
iso_dir_iter_free(iter); |
|
iter= NULL; |
|
} |
|
Xorriso_set_change_pending(xorriso, 0); |
|
ret= 1; |
|
ex:; |
|
if(iter != NULL) |
|
iso_dir_iter_free(iter); |
|
Xorriso_free_meM(eff_dest); |
|
Xorriso_free_meM(eff_origin); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_set_st_mode(struct XorrisO *xorriso, char *in_path, |
|
mode_t mode_and, mode_t mode_or, int flag) |
|
{ |
|
mode_t mode= 0; |
|
int ret; |
|
IsoNode *node; |
|
char *path= NULL; |
|
|
|
Xorriso_alloc_meM(path, char, SfileadrL); |
|
ret= Xorriso_get_node_by_path(xorriso, in_path, path, &node, 0); |
|
if(ret<=0) |
|
goto ex; |
|
mode= iso_node_get_permissions(node); |
|
mode= (mode & mode_and) | mode_or; |
|
iso_node_set_permissions(node, mode); |
|
iso_node_set_ctime(node, time(NULL)); |
|
sprintf(xorriso->info_text,"Permissions now: %-5.5o ", |
|
(unsigned int) (mode & 0xffff)); |
|
Text_shellsafe(path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); |
|
Xorriso_set_change_pending(xorriso, 0); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(path); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_set_uid(struct XorrisO *xorriso, char *in_path, uid_t uid, |
|
int flag) |
|
{ |
|
int ret; |
|
IsoNode *node; |
|
|
|
ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0); |
|
if(ret<=0) |
|
return(ret); |
|
iso_node_set_uid(node, uid); |
|
iso_node_set_ctime(node, time(NULL)); |
|
Xorriso_set_change_pending(xorriso, 0); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_set_gid(struct XorrisO *xorriso, char *in_path, gid_t gid, |
|
int flag) |
|
{ |
|
int ret; |
|
IsoNode *node; |
|
|
|
ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0); |
|
if(ret<=0) |
|
return(ret); |
|
iso_node_set_gid(node, gid); |
|
iso_node_set_ctime(node, time(NULL)); |
|
Xorriso_set_change_pending(xorriso, 0); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
return(1); |
|
} |
|
|
|
|
|
/* @parm flag bit0= atime, bit1= ctime, bit2= mtime, bit8=no auto ctime */ |
|
int Xorriso_set_time(struct XorrisO *xorriso, char *in_path, time_t t, |
|
int flag) |
|
{ |
|
int ret; |
|
IsoNode *node; |
|
|
|
ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0); |
|
if(ret<=0) |
|
return(ret); |
|
if(flag&1) |
|
iso_node_set_atime(node, t); |
|
if(flag&2) |
|
iso_node_set_ctime(node, t); |
|
if(flag&4) |
|
iso_node_set_mtime(node, t); |
|
if(!(flag&(2|256))) |
|
iso_node_set_ctime(node, time(NULL)); |
|
Xorriso_set_change_pending(xorriso, 0); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
return(1); |
|
} |
|
|
|
|
|
/* |
|
Apply the effect of mkisofs -r to a single node |
|
*/ |
|
int Xorriso_mkisofs_lower_r(struct XorrisO *xorriso, IsoNode *node, int flag) |
|
{ |
|
mode_t perms; |
|
|
|
perms= iso_node_get_permissions(node); |
|
iso_node_set_uid(node, (uid_t) 0); |
|
iso_node_set_gid(node, (gid_t) 0); |
|
perms|= S_IRUSR | S_IRGRP | S_IROTH; |
|
perms&= ~(S_IWUSR | S_IWGRP | S_IWOTH); |
|
if(perms & (S_IXUSR | S_IXGRP | S_IXOTH)) |
|
perms|= (S_IXUSR | S_IXGRP | S_IXOTH); |
|
perms&= ~(S_ISUID | S_ISGID | S_ISVTX); |
|
iso_node_set_permissions(node, perms); |
|
return(1); |
|
} |
|
|
|
|
|
/* @param node Opaque handle to IsoNode which is to be manipulated |
|
instead of path if it is not NULL. |
|
@param path is used as address if node is NULL. |
|
@param access_text "access" ACL in long text form |
|
@param default_text "default" ACL in long text form |
|
@param flag bit0= do not warn of root directory if not capable of AAIP |
|
@return >0 success , <=0 failure |
|
*/ |
|
int Xorriso_setfacl(struct XorrisO *xorriso, void *in_node, char *path, |
|
char *access_text, char *default_text, int flag) |
|
{ |
|
int ret; |
|
IsoNode *node; |
|
|
|
node= (IsoNode *) in_node; |
|
if(node == NULL) { |
|
ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
ret= iso_node_set_acl_text(node, access_text, default_text, 0); |
|
if(ret <= 0) { |
|
Xorriso_report_iso_error(xorriso, "", ret, |
|
"Error when setting ACL to image node", |
|
0, "FAILURE", 1); |
|
if(path != NULL && path[0] != 0) { |
|
strcpy(xorriso->info_text, "Error with setting ACL of "); |
|
Text_shellsafe(path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
} |
|
ret= 0; goto ex; |
|
} |
|
Xorriso_set_change_pending(xorriso, 0); |
|
ret= 1; |
|
ex:; |
|
Xorriso_process_msg_queues(xorriso,0); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param in_node Opaque handle to IsoNode which is to be manipulated |
|
instead of path if it is not NULL. |
|
@param path is used as address if node is NULL. |
|
@param num_attrs Number of attributes |
|
@param names Array of pointers to 0 terminated name strings |
|
@param value_lengths Array of byte lengths for each attribute payload |
|
@param values Array of pointers to the attribute payload bytes |
|
@param flag bit0= Do not maintain eventual existing ACL of the node |
|
bit1= Do not clear the existing attribute list |
|
bit2= Delete the attributes with the given names |
|
bit3= Allow non-user attributes. |
|
bit4= do not warn of root if incapable of AAIP |
|
@return >0 success , <=0 failure |
|
*/ |
|
int Xorriso_setfattr(struct XorrisO *xorriso, void *in_node, char *path, |
|
size_t num_attrs, char **names, |
|
size_t *value_lengths, char **values, int flag) |
|
{ |
|
int ret; |
|
IsoNode *node; |
|
|
|
node= (IsoNode *) in_node; |
|
if(node == NULL) { |
|
ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
ret= iso_node_set_attrs(node, num_attrs, names, value_lengths, values, |
|
flag & (1 | 2 | 4 | 8)); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(ret <= 0) { |
|
Xorriso_report_iso_error(xorriso, "", ret, |
|
"Error when setting ACL and xattr to image node", |
|
0, "FAILURE", 1); |
|
if(path != NULL && path[0] != 0) { |
|
strcpy(xorriso->info_text, "Error with setting xattr of "); |
|
Text_shellsafe(path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
} |
|
ret= 0; goto ex; |
|
} |
|
Xorriso_set_change_pending(xorriso, 0); |
|
ret= 1; |
|
ex:; |
|
Xorriso_process_msg_queues(xorriso,0); |
|
return(ret); |
|
} |
|
|
|
|
|
/* |
|
@param flag bit0= use parameters dev,ino rather than disk_path |
|
bit1= compare attribute rather than setting it |
|
return: 0=dev,ino match, 1=mismatch, 2=no node attribute |
|
-1=error |
|
bit5= if not bit0: |
|
transfer dev,inode from eventual link target |
|
bit7= omit dev check mit bit1 |
|
*/ |
|
int Xorriso_record_dev_inode(struct XorrisO *xorriso, char *disk_path, |
|
dev_t dev, ino_t ino, |
|
void *in_node, char *iso_path, int flag) |
|
{ |
|
size_t l, di_l= 0; |
|
int i, ret; |
|
dev_t hdev; |
|
ino_t hino; |
|
char buf[66], *bufpt, *wpt, *di= NULL; |
|
static char *name= "isofs.di"; |
|
struct stat stbuf; |
|
|
|
if(!(flag & 1)) { |
|
if(flag & 32) { |
|
if(stat(disk_path, &stbuf) == -1) |
|
return(-1); |
|
} else { |
|
if(lstat(disk_path, &stbuf) == -1) |
|
return(-1); |
|
} |
|
dev= stbuf.st_dev; |
|
ino= stbuf.st_ino; |
|
} |
|
|
|
wpt= buf; |
|
hdev= dev; |
|
for(i= 0; hdev != 0; i++) |
|
hdev= hdev >> 8; |
|
l= i; |
|
*(wpt++)= l; |
|
for(i= 0; i < (int) l; i++) |
|
*(wpt++)= dev >> (8 * (l - i - 1)); |
|
hino= ino; |
|
for(i= 0; hino != 0; i++) |
|
hino= hino >> 8; |
|
l= i; |
|
*(wpt++)= l; |
|
for(i= 0; i < (int) l; i++) |
|
*(wpt++)= ino >> (8 * (l - i - 1)); |
|
l= wpt - buf; |
|
bufpt= buf; |
|
|
|
if(flag & 2) { |
|
/* Compare node attribute with bufpt,l */ |
|
ret= Xorriso_get_attr_value(xorriso, in_node, iso_path, |
|
"isofs.di", &di_l, &di, 0); |
|
if(ret < 0) |
|
goto ex; |
|
if(ret == 0) |
|
{ret= 2; goto ex;} |
|
if(flag & 128) { |
|
if(di_l <= 0) |
|