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.
2176 lines
61 KiB
2176 lines
61 KiB
|
|
/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images. |
|
|
|
Copyright 2007-2014 Thomas Schmitt, <scdbackup@gmx.net> |
|
|
|
Provided under GPL version 2 or later. |
|
|
|
This file contains the implementation of actions on onjects of disk |
|
filesystems. |
|
*/ |
|
|
|
#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 <fcntl.h> |
|
#include <errno.h> |
|
#include <pwd.h> |
|
#include <grp.h> |
|
|
|
/* O_BINARY is needed for Cygwin but undefined elsewhere */ |
|
#ifndef O_BINARY |
|
#define O_BINARY 0 |
|
#endif |
|
|
|
|
|
#include "xorriso.h" |
|
#include "xorriso_private.h" |
|
#include "xorrisoburn.h" |
|
|
|
|
|
|
|
/* @param flag bit0= simple readlink(): no normalization, no multi-hop |
|
bit1= this is potentially a recursion |
|
*/ |
|
int Xorriso_resolve_link(struct XorrisO *xorriso, char *link_path, |
|
char result_path[SfileadrL], int flag) |
|
{ |
|
ssize_t l; |
|
struct stat stbuf; |
|
int link_count= 0, ret, show_errno= 0; |
|
char *buf= NULL, *dirbuf= NULL, *lpt, *spt; |
|
static int link_limit= 100; |
|
|
|
if(flag & 1) { |
|
xorriso->resolve_link_rec_count++; |
|
if(xorriso->resolve_link_rec_count > xorriso->resolve_link_rec_limit) { |
|
Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, "Too many link recursions before : "); |
|
Text_shellsafe(link_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, show_errno, |
|
"FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
} else |
|
xorriso->resolve_link_rec_count= 0; |
|
|
|
Xorriso_alloc_meM(buf, char, SfileadrL); |
|
Xorriso_alloc_meM(dirbuf, char, SfileadrL); |
|
|
|
if(!(flag&1)) |
|
if(stat(link_path, &stbuf)==-1) |
|
if(errno==ELOOP) { |
|
show_errno= errno; |
|
goto too_many_hops; |
|
} |
|
lpt= link_path; |
|
while(1) { |
|
l= readlink(lpt, buf, SfileadrL-1); |
|
if(l==-1) { |
|
handle_error:; |
|
Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, "Cannot obtain link target of : "); |
|
Text_shellsafe(link_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); |
|
handle_abort:; |
|
if(strcmp(lpt, link_path)!=0) { |
|
sprintf(xorriso->info_text, |
|
"Problem occured with intermediate path : "); |
|
Text_shellsafe(lpt, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
} |
|
{ret= 0; goto ex;} |
|
} |
|
buf[l]= 0; |
|
if(l==0) { |
|
Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, "Empty link target with : "); |
|
Text_shellsafe(link_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
goto handle_abort; |
|
} |
|
|
|
if(flag&1) { |
|
strcpy(result_path, buf); |
|
{ret= 1; goto ex;} |
|
} |
|
|
|
/* normalize relative to disk_path */ |
|
if(Sfile_str(dirbuf, lpt, 0)<=0) |
|
{ret= -1; goto ex;} |
|
while(1) { |
|
spt= strrchr(dirbuf,'/'); |
|
if(spt!=NULL) { |
|
*spt= 0; |
|
if(*(spt+1)!=0) |
|
break; |
|
} else |
|
break; |
|
} |
|
ret= Xorriso_normalize_img_path(xorriso, dirbuf, buf, result_path, 2|4); |
|
if(ret<=0) { |
|
goto ex; |
|
} |
|
|
|
if(lstat(result_path, &stbuf)==-1) { |
|
lpt= result_path; |
|
goto handle_error; |
|
} |
|
if(!S_ISLNK(stbuf.st_mode)) |
|
break; |
|
|
|
lpt= result_path; |
|
link_count++; |
|
if(link_count>link_limit) { |
|
too_many_hops:; |
|
Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0); |
|
sprintf(xorriso->info_text, "Too many link hops with : "); |
|
Text_shellsafe(link_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, show_errno, |
|
"FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(buf); |
|
Xorriso_free_meM(dirbuf); |
|
if(xorriso->resolve_link_rec_count > 0) |
|
xorriso->resolve_link_rec_count--; |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_convert_uidstring(struct XorrisO *xorriso, char *uid_string, |
|
uid_t *uid, int flag) |
|
{ |
|
double num= 0.0; |
|
char text[80]; |
|
struct passwd *pwd; |
|
|
|
sscanf(uid_string, "%lf", &num); |
|
sprintf(text,"%.f",num); |
|
if(strcmp(text,uid_string)==0) { |
|
*uid= num; |
|
return(1); |
|
} |
|
pwd= getpwnam(uid_string); |
|
if(pwd==NULL) { |
|
sprintf(xorriso->info_text, "-uid: Not a known user: '%s'", uid_string); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); |
|
return(0); |
|
} |
|
*uid= pwd->pw_uid; |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_convert_gidstring(struct XorrisO *xorriso, char *gid_string, |
|
gid_t *gid, int flag) |
|
{ |
|
double num= 0.0; |
|
char text[80]; |
|
struct group *grp; |
|
|
|
sscanf(gid_string, "%lf", &num); |
|
sprintf(text,"%.f",num); |
|
if(strcmp(text,gid_string)==0) { |
|
*gid= num; |
|
return(1); |
|
} |
|
grp= getgrnam(gid_string); |
|
if(grp==NULL) { |
|
sprintf(xorriso->info_text, "-gid: Not a known group: '%s'", gid_string); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); |
|
return(0); |
|
} |
|
*gid= grp->gr_gid; |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_convert_modstring(struct XorrisO *xorriso, char *cmd, char *mode, |
|
mode_t *mode_and, mode_t *mode_or, int flag) |
|
{ |
|
int who_val= 0; |
|
char *mpt, *vpt, *opt; |
|
unsigned int num= 0; |
|
mode_t mode_val,mask; |
|
|
|
*mode_and= ~0; |
|
*mode_or= 0; |
|
if(mode[0]=='0') { |
|
*mode_and= 0; |
|
sscanf(mode,"%o",&num); |
|
*mode_or= num; |
|
} else if(strchr(mode,'+')!=NULL || strchr(mode,'-')!=NULL |
|
|| strchr(mode,'=')!=NULL) { |
|
/* [ugoa][+-][rwxst] */; |
|
for(mpt= mode; mpt!=NULL; mpt= strchr(mpt, ',')) { |
|
if(*mpt==',') |
|
mpt++; |
|
if(strlen(mpt)<2) |
|
goto unrecognizable; |
|
who_val= 0; |
|
for(vpt= mpt; *vpt!='+' && *vpt!='-' && *vpt!='='; vpt++) { |
|
if(*vpt=='u') |
|
who_val|= 4; |
|
else if(*vpt=='g') |
|
who_val|= 2; |
|
else if(*vpt=='o') |
|
who_val|= 1; |
|
else if(*vpt=='a') |
|
who_val|= 7; |
|
else |
|
goto unrecognizable; |
|
} |
|
opt= vpt; |
|
mode_val= 0; |
|
for(vpt= opt+1; *vpt!=0 && *vpt!=','; vpt++) { |
|
if(*vpt=='r') { |
|
if(who_val&4) |
|
mode_val|= S_IRUSR; |
|
if(who_val&2) |
|
mode_val|= S_IRGRP; |
|
if(who_val&1) |
|
mode_val|= S_IROTH; |
|
} else if(*vpt=='w') { |
|
if(who_val&4) |
|
mode_val|= S_IWUSR; |
|
if(who_val&2) |
|
mode_val|= S_IWGRP; |
|
if(who_val&1) |
|
mode_val|= S_IWOTH; |
|
} else if(*vpt=='x') { |
|
if(who_val&4) |
|
mode_val|= S_IXUSR; |
|
if(who_val&2) |
|
mode_val|= S_IXGRP; |
|
if(who_val&1) |
|
mode_val|= S_IXOTH; |
|
} else if(*vpt=='s') { |
|
if(who_val&4) |
|
mode_val|= S_ISUID; |
|
if(who_val&2) |
|
mode_val|= S_ISGID; |
|
} else if(*vpt=='t') { |
|
if(who_val&1) |
|
mode_val|= S_ISVTX; |
|
} else |
|
goto unrecognizable; |
|
} |
|
if(*opt=='+') { |
|
(*mode_or)|= mode_val; |
|
} else if(*opt=='=') { |
|
mask= 0; |
|
if(who_val&1) |
|
mask|= S_IRWXO|S_ISVTX; |
|
if(who_val&2) |
|
mask|= S_IRWXG|S_ISGID; |
|
if(who_val&4) |
|
mask|= S_IRWXU|S_ISUID; |
|
(*mode_and)&= ~(mask); |
|
(*mode_or)= ((*mode_or) & ~mask) | mode_val; |
|
} else if(*opt=='-') { |
|
(*mode_or)&= ~mode_val; |
|
(*mode_and)&= ~mode_val; |
|
} |
|
} |
|
} else { |
|
unrecognizable:; |
|
sprintf(xorriso->info_text, |
|
"%s: Unrecognizable or faulty permission mode ", cmd); |
|
Text_shellsafe(mode, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); |
|
return(0); |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
/* @param flag bit0= for Xorriso_msgs_submit: use pager |
|
bit1= do not issue warnings |
|
*/ |
|
int Xorriso_hop_link(struct XorrisO *xorriso, char *link_path, |
|
struct LinkiteM **link_stack, struct stat *stbuf, int flag) |
|
{ |
|
int ret; |
|
struct LinkiteM *litm; |
|
|
|
if(*link_stack != NULL) { |
|
if(Linkitem_get_link_count(*link_stack, 0) >= xorriso->follow_link_limit) { |
|
sprintf(xorriso->info_text, |
|
"Too many symbolic links in single tree branch at : "); |
|
Text_shellsafe(link_path, xorriso->info_text, 1); |
|
if(!(flag&2)) |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,"WARNING",flag&1); |
|
return(0); |
|
} |
|
} |
|
ret= stat(link_path, stbuf); |
|
if(ret==-1) |
|
return(0); |
|
ret= Linkitem_find(*link_stack, stbuf->st_dev, stbuf->st_ino, &litm, 0); |
|
if(ret>0) { |
|
sprintf(xorriso->info_text, "Detected symbolic link loop around : "); |
|
Text_shellsafe(link_path, xorriso->info_text, 1); |
|
if(!(flag&2)) |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", flag&1); |
|
return(0); |
|
} |
|
ret= Linkitem_new(&litm, link_path, stbuf->st_dev, stbuf->st_ino, |
|
*link_stack, 0); |
|
if(ret<=0) { |
|
sprintf(xorriso->info_text, |
|
"Cannot add new item to link loop prevention stack"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", flag&1); |
|
return(-1); |
|
} |
|
*link_stack= litm; |
|
return(1); |
|
} |
|
|
|
|
|
/* @param flag bit0= do not only sum up sizes but also print subdirs |
|
bit1= this is a recursion |
|
@return <=0 error , 1 ok , 2 could not open directory |
|
*/ |
|
int Xorriso_show_dux_subs(struct XorrisO *xorriso, |
|
char *abs_path, char *rel_path, off_t *size, |
|
off_t boss_mem, |
|
struct LinkiteM *link_stack, |
|
int flag) |
|
{ |
|
int i, ret, no_sort= 0, filec= 0, l, j, fc, no_dive, is_link; |
|
char **filev= NULL, *namept; |
|
off_t sub_size, report_size, mem= 0; |
|
struct DirseQ *dirseq= NULL; |
|
struct stat stbuf; |
|
dev_t dir_dev; |
|
struct LinkiteM *own_link_stack; |
|
char *path= NULL, *show_path= NULL, *name= NULL, *sfe= NULL; |
|
|
|
sfe= malloc(5*SfileadrL); |
|
path= malloc(SfileadrL); |
|
show_path= malloc(SfileadrL); |
|
name= malloc(SfileadrL); |
|
if(path==NULL || show_path==NULL || name==NULL || sfe==NULL) { |
|
Xorriso_no_malloc_memory(xorriso, &sfe, 0); |
|
{ret= -1; goto ex;} |
|
} |
|
own_link_stack= link_stack; |
|
namept= name; |
|
*size= 0; |
|
|
|
if(lstat(abs_path, &stbuf)==-1) |
|
{ret= 2; goto ex;} |
|
dir_dev= stbuf.st_dev; |
|
if(S_ISLNK(stbuf.st_mode)) { |
|
if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&2)))) |
|
{ret= 2; goto ex;} |
|
if(stat(abs_path, &stbuf)==-1) |
|
{ret= 2; goto ex;} |
|
if(dir_dev != stbuf.st_dev && |
|
!(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&2)))) |
|
{ret= 2; goto ex;} |
|
} |
|
ret= Dirseq_new(&dirseq, abs_path, 1); |
|
if(ret<0) { |
|
sprintf(xorriso->info_text, "Cannot obtain disk directory iterator"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
{ret= -1; goto ex;} |
|
} |
|
if(ret==0) |
|
{ret= 2; goto ex;} |
|
|
|
while(1) { |
|
Linkitem_reset_stack(&own_link_stack, link_stack, 0); |
|
ret= Dirseq_next_adr(dirseq,name,0); |
|
if(ret<0) |
|
goto ex; |
|
if(ret==0) |
|
break; |
|
|
|
sub_size= 0; |
|
strcpy(show_path, rel_path); |
|
if(Sfile_add_to_path(show_path, name, 0)<=0) |
|
goto much_too_long; |
|
|
|
strcpy(path, abs_path); |
|
if(Sfile_add_to_path(path, name, 0)<=0) { |
|
much_too_long:; |
|
Xorriso_much_too_long(xorriso, strlen(path)+strlen(name)+1, 2); |
|
{ret= -1; goto ex;} |
|
} |
|
no_dive= 0; |
|
|
|
ret= lstat(path, &stbuf); |
|
if(ret==-1) |
|
continue; |
|
is_link= S_ISLNK(stbuf.st_mode); |
|
if(is_link && xorriso->do_follow_links) { |
|
ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1); |
|
if(ret<0) |
|
{ret= -1; goto ex;} |
|
if(ret!=1) |
|
no_dive= 1; |
|
} |
|
if(!S_ISDIR(stbuf.st_mode)) |
|
no_dive= 1; |
|
if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount) |
|
no_dive= 1; |
|
if(!no_dive) { |
|
filec++; |
|
l= strlen(rel_path)+1; |
|
mem+= l; |
|
if(l % sizeof(char *)) |
|
mem+= sizeof(char *)-(l % sizeof(char *)); |
|
if(flag&1) /* diving and counting is done further below */ |
|
continue; |
|
ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size, boss_mem, |
|
own_link_stack,2); |
|
if(ret<0) |
|
goto ex; |
|
if(ret==0) |
|
continue; |
|
} |
|
|
|
/* |
|
sub_size+= stbuf.st_size+strlen(name)+1; |
|
*/ |
|
sub_size+= stbuf.st_size+2048; |
|
if(sub_size>0) |
|
(*size)+= sub_size; |
|
} |
|
|
|
if(filec<=0 || !(flag&1)) |
|
{ret= 1; goto ex;} |
|
|
|
/* Try to get a sorted list of directory names */ |
|
mem+= (filec+1)*sizeof(char *); |
|
ret= Xorriso_check_temp_mem_limit(xorriso, mem+boss_mem, 2); |
|
if(ret<0) |
|
goto ex; |
|
Dirseq_rewind(dirseq, 0); |
|
if(ret==0) { |
|
no_sort_possible:; |
|
no_sort= 1; |
|
} else { |
|
filev= (char **) calloc(filec+1, sizeof(char *)); |
|
if(filev==NULL) |
|
goto no_sort_possible; |
|
else { |
|
for(i= 0; i<filec; i++) |
|
filev[i]= NULL; |
|
fc= 0; |
|
while(1) { |
|
ret= Dirseq_next_adr(dirseq,name,0); |
|
if(ret<0) |
|
goto ex; |
|
if(ret==0) |
|
break; |
|
strcpy(path, abs_path); |
|
if(Sfile_add_to_path(path, name, 0)<=0) |
|
goto much_too_long; |
|
|
|
ret= lstat(path,&stbuf); |
|
if(ret==-1) |
|
continue; |
|
is_link= S_ISLNK(stbuf.st_mode); |
|
if(is_link && xorriso->do_follow_links) { |
|
ret= stat(path,&stbuf); |
|
if(ret==-1) |
|
continue; |
|
} |
|
if(!S_ISDIR(stbuf.st_mode)) |
|
continue; |
|
if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount) |
|
continue; |
|
|
|
if(fc>=filec) { /* Number of files changed (or programming error) */ |
|
revoke_sorting:; |
|
for(j=0; j<fc; j++) |
|
free((char *) filev[j]); |
|
free((char *) filev); |
|
filev= NULL; |
|
goto no_sort_possible; |
|
} |
|
|
|
filev[fc]= strdup(name); |
|
if(filev[fc]==NULL) |
|
goto revoke_sorting; |
|
fc++; |
|
} |
|
filec= fc; |
|
if(filec>1) |
|
Sort_argv(filec, filev, 0); |
|
} |
|
} |
|
|
|
for(i= 0; (no_sort || i<filec) && !(xorriso->request_to_abort); i++) { |
|
Linkitem_reset_stack(&own_link_stack, link_stack, 0); |
|
if(no_sort) { |
|
ret= Dirseq_next_adr(dirseq,name,0); |
|
if(ret<0) |
|
goto ex; |
|
if(ret==0) |
|
break; |
|
} else |
|
namept= filev[i]; |
|
|
|
sub_size= 0; |
|
strcpy(show_path, rel_path); |
|
if(Sfile_add_to_path(show_path, namept, 0)<=0) |
|
goto much_too_long; |
|
strcpy(path, abs_path); |
|
if(Sfile_add_to_path(path, namept, 0)<=0) |
|
goto much_too_long; |
|
no_dive= 0; |
|
|
|
ret= lstat(path,&stbuf); |
|
if(ret==-1) |
|
continue; |
|
is_link= S_ISLNK(stbuf.st_mode); |
|
if(is_link && xorriso->do_follow_links) { |
|
ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1); |
|
if(ret<0) |
|
{ret= -1; goto ex;} |
|
if(ret!=1) |
|
continue; |
|
} |
|
if(!S_ISDIR(stbuf.st_mode)) |
|
continue; |
|
if(dir_dev == stbuf.st_dev || xorriso->do_follow_mount) { |
|
ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size, |
|
boss_mem+mem, own_link_stack, 2|(flag&1)); |
|
if(ret<0) |
|
goto ex; |
|
} |
|
|
|
/* |
|
sub_size+= stbuf.st_size+strlen(namept)+1; |
|
*/ |
|
sub_size+= stbuf.st_size+2048; |
|
if(sub_size>0) |
|
(*size)+= sub_size; |
|
report_size= sub_size/1024; |
|
if(report_size*1024<sub_size) |
|
report_size++; |
|
if(xorriso->sh_style_result) |
|
sprintf(xorriso->result_line, "%-7.f ",(double) (report_size)); |
|
else |
|
sprintf(xorriso->result_line, "%7.f ",(double) (report_size)); |
|
sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n", |
|
Xorriso_esc_filepath(xorriso,show_path, sfe, 0)); |
|
Xorriso_result(xorriso, 0); |
|
} |
|
|
|
ret= 1; |
|
ex:; |
|
if(sfe!=NULL) |
|
free(sfe); |
|
if(path!=NULL) |
|
free(path); |
|
if(show_path!=NULL) |
|
free(show_path); |
|
if(name!=NULL) |
|
free(name); |
|
Linkitem_reset_stack(&own_link_stack, link_stack, 0); |
|
Dirseq_destroy(&dirseq, 0); |
|
if(filev!=NULL) { |
|
for(i=0; i<filec; i++) |
|
if(filev[i]!=NULL) |
|
free((char *) filev[i]); |
|
free((char *) filev); |
|
} |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit1= add '+' to perms |
|
bit2-7: hidden_state : |
|
bit2= hide in ISO/RR |
|
bit3= hide in Joliet |
|
bit4= hide in HFS+ |
|
*/ |
|
int Xorriso__mode_to_perms(mode_t st_mode, char perms[11], int flag) |
|
{ |
|
int hidden_state; |
|
|
|
strcpy(perms,"--------- "); |
|
if(st_mode&S_IRUSR) perms[0]= 'r'; |
|
if(st_mode&S_IWUSR) perms[1]= 'w'; |
|
if(st_mode&S_IXUSR) perms[2]= 'x'; |
|
if(st_mode&S_ISUID) { |
|
if(st_mode&S_IXUSR) |
|
perms[2]= 's'; |
|
else |
|
perms[2]= 'S'; |
|
} |
|
if(st_mode&S_IRGRP) perms[3]= 'r'; |
|
if(st_mode&S_IWGRP) perms[4]= 'w'; |
|
if(st_mode&S_IXGRP) perms[5]= 'x'; |
|
if(st_mode&S_ISGID) { |
|
if(st_mode&S_IXGRP) |
|
perms[5]= 's'; |
|
else |
|
perms[5]= 'S'; |
|
} |
|
if(st_mode&S_IROTH) perms[6]= 'r'; |
|
if(st_mode&S_IWOTH) perms[7]= 'w'; |
|
if(st_mode&S_IXOTH) perms[8]= 'x'; |
|
if(st_mode&S_ISVTX) { |
|
if(st_mode&S_IXOTH) |
|
perms[8]= 't'; |
|
else |
|
perms[8]= 'T'; |
|
} |
|
|
|
hidden_state= (flag >> 2) & 63; |
|
if(hidden_state == 1) |
|
perms[9]= 'I'; |
|
else if(hidden_state == 2) |
|
perms[9]= 'J'; |
|
else if(hidden_state == 4) |
|
perms[9]= 'A'; |
|
else if(hidden_state) |
|
perms[9]= 'H'; |
|
if(flag & 2) { |
|
if(hidden_state) |
|
perms[9]= tolower(perms[9]); |
|
else |
|
perms[9]= '+'; |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
/* @param flag bit0= recognize Xorriso_IFBOOT as file type |
|
bit1= add '+' to perms |
|
bit2-7: hidden_state : |
|
bit2= hide in ISO/RR |
|
bit3= hide in Joliet |
|
bit4= hide in HFS+ |
|
*/ |
|
int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag) |
|
{ |
|
int show_major_minor= 0, high_shift= 0, high_mask= 0; |
|
char *rpt, perms[11], mm_text[80]; |
|
mode_t st_mode; |
|
dev_t dev, major, minor; |
|
|
|
rpt= xorriso->result_line; |
|
rpt[0]= 0; |
|
st_mode= stbuf->st_mode; |
|
|
|
if(S_ISDIR(st_mode)) |
|
strcat(rpt, "d"); |
|
else if(S_ISREG(st_mode)) { |
|
strcat(rpt, "-"); |
|
} else if(S_ISLNK(st_mode)) |
|
strcat(rpt, "l"); |
|
else if(S_ISBLK(st_mode)) { |
|
strcat(rpt, "b"); |
|
show_major_minor= 1; |
|
} else if(S_ISCHR(st_mode)) { |
|
strcat(rpt, "c"); |
|
show_major_minor= 1; |
|
} else if(S_ISFIFO(st_mode)) |
|
strcat(rpt, "p"); |
|
else if(S_ISSOCK(st_mode)) |
|
strcat(rpt, "s"); |
|
else if((flag & 1) && (st_mode & S_IFMT) == Xorriso_IFBOOT) |
|
strcat(rpt, "e"); |
|
else |
|
strcat(rpt, "?"); |
|
|
|
Xorriso__mode_to_perms(st_mode, perms, flag & (2 | 252)); |
|
strcat(rpt, perms); |
|
|
|
sprintf(rpt+strlen(rpt)," %3u ",(unsigned int) stbuf->st_nlink); |
|
|
|
sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_uid); |
|
sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_gid); |
|
if(show_major_minor) { |
|
dev= stbuf->st_rdev; |
|
|
|
/* according to /usr/include/sys/sysmacros.h : gnu_dev_major(),_minor() |
|
>>> but this looks as if it should go to some system dependency |
|
>>> in FreeBSD dev_t is 32 bit |
|
*/ |
|
if(sizeof(dev_t) > 4) { |
|
high_shift= 32; |
|
high_mask= ~0xfff; |
|
} |
|
major= (((dev >> 8) & 0xfff) | |
|
((unsigned int) (dev >> high_shift) & high_mask)) |
|
& 0xffffffff; |
|
minor= (((dev & 0xff) | ((unsigned int) (dev >> 12) & ~0xff))) & 0xffffffff; |
|
|
|
sprintf(mm_text, "%u,%u", (unsigned int) major, (unsigned int) minor); |
|
sprintf(rpt+strlen(rpt), "%8s ", mm_text); |
|
} else |
|
sprintf(rpt+strlen(rpt), "%8.f ", (double) stbuf->st_size); |
|
|
|
Ftimetxt(stbuf->st_mtime, rpt+strlen(rpt), 0); |
|
strcat(rpt, " "); |
|
|
|
return(1); |
|
} |
|
|
|
|
|
struct DirentrY { |
|
char *adr; |
|
struct DirentrY *next; |
|
}; |
|
|
|
|
|
int Xorriso_sorted_dir_x(struct XorrisO *xorriso, char *dir_path, |
|
int *filec, char ***filev, off_t boss_mem, int flag) |
|
{ |
|
int count= 0, ret; |
|
char *name= NULL; |
|
struct DirseQ *dirseq= NULL; |
|
off_t mem; |
|
struct DirentrY *last= NULL, *current= NULL; |
|
|
|
Xorriso_alloc_meM(name, char, SfileadrL); |
|
|
|
*filec= 0; |
|
*filev= NULL; |
|
mem= boss_mem; |
|
ret= Dirseq_new(&dirseq, dir_path, 1); |
|
if(ret<=0) |
|
goto ex; |
|
while(1) { /* loop over directory content */ |
|
ret= Dirseq_next_adr(dirseq,name,0); |
|
if(ret==0) |
|
break; |
|
if(ret<0) |
|
goto ex; |
|
mem+= strlen(name)+8+sizeof(struct DirentrY)+sizeof(char *); |
|
if(mem>xorriso->temp_mem_limit) |
|
{ret= 0; goto ex;} |
|
|
|
current= (struct DirentrY *) calloc(1, sizeof(struct DirentrY)); |
|
if(current==NULL) { |
|
Xorriso_no_malloc_memory(xorriso, NULL, 0); |
|
{ret= -1; goto ex;} |
|
} |
|
current->adr= NULL; |
|
current->next= last; |
|
last= current; |
|
last->adr= strdup(name); |
|
if(last->adr==NULL) { |
|
Xorriso_no_malloc_memory(xorriso, NULL, 0); |
|
{ret= -1; goto ex;} |
|
} |
|
count++; |
|
} |
|
*filec= count; |
|
if(count==0) |
|
{ret= 1; goto ex;} |
|
(*filev)= (char **) calloc(count, sizeof(char *)); |
|
if(*filev==NULL) { |
|
Xorriso_no_malloc_memory(xorriso, NULL, 0); |
|
{ret= -1; goto ex; } |
|
} |
|
count= 0; |
|
for(current= last; current!=NULL; current= last) { |
|
last= current->next; |
|
(*filev)[count++]= current->adr; |
|
free((char *) current); |
|
} |
|
Sort_argv(*filec, *filev, 0); |
|
ret= 1; |
|
ex:; |
|
for(current= last; current!=NULL; current= last) { |
|
last= current->next; |
|
free(current->adr); |
|
free((char *) current); |
|
} |
|
Xorriso_free_meM(name); |
|
Dirseq_destroy(&dirseq, 0); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= long format |
|
bit1= do not print count of nodes |
|
bit2= du format |
|
bit3= print directories as themselves (ls -d) |
|
*/ |
|
int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd, |
|
int filec, char **filev, off_t boss_mem, int flag) |
|
{ |
|
int i, ret, was_error= 0, dfilec= 0, pass, passes; |
|
char *path= NULL, *acl_text= NULL; |
|
char *rpt, *link_target= NULL, **dfilev= NULL; |
|
off_t size; |
|
struct stat stbuf; |
|
|
|
Xorriso_alloc_meM(path, char, SfileadrL); |
|
Xorriso_alloc_meM(link_target, char, SfileadrL); |
|
|
|
rpt= xorriso->result_line; |
|
|
|
Sort_argv(filec, filev, 0); |
|
|
|
/* Count valid nodes, warn of invalid ones */ |
|
for(i= 0; i<filec; i++) { |
|
ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4|8); |
|
if(ret<=0) { |
|
was_error++; |
|
continue; |
|
} |
|
ret= lstat(path, &stbuf); |
|
if(ret==-1) { |
|
sprintf(xorriso->info_text, "Not found in local filesystem: "); |
|
Text_shellsafe(path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 1); |
|
was_error++; |
|
continue; |
|
} |
|
} |
|
|
|
if((flag&8) && !(flag&(2|4))) { |
|
sprintf(xorriso->info_text,"Valid local files found: %d\n",filec-was_error); |
|
Xorriso_info(xorriso,1); |
|
if(filec-was_error<=0) |
|
{ret= !was_error; goto ex;} |
|
} |
|
|
|
passes= 1+!(flag&(4|8)); |
|
for(pass= 0; pass<passes; pass++) |
|
for(i= 0; i<filec && !(xorriso->request_to_abort); i++) { |
|
ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4); |
|
if(ret<=0) |
|
continue; |
|
ret= lstat(path, &stbuf); |
|
if(ret==-1) |
|
continue; |
|
if(S_ISLNK(stbuf.st_mode) && |
|
(xorriso->do_follow_links || xorriso->do_follow_param)) { |
|
ret= stat(path, &stbuf); |
|
if(ret==-1) |
|
ret= lstat(path, &stbuf); |
|
if(ret==-1) |
|
continue; |
|
} |
|
if(S_ISDIR(stbuf.st_mode) && !(flag&(4|8))) { |
|
if(pass==0) |
|
continue; |
|
if(filec>1) { |
|
strcpy(xorriso->result_line, "\n"); |
|
Xorriso_result(xorriso,0); |
|
Xorriso_esc_filepath(xorriso,filev[i], xorriso->result_line, 0); |
|
strcat(xorriso->result_line, ":\n"); |
|
Xorriso_result(xorriso,0); |
|
} |
|
ret= Xorriso_sorted_dir_x(xorriso, path, &dfilec, &dfilev, boss_mem, 0); |
|
if(ret<=0) { |
|
|
|
/* >>> DirseQ loop and single item Xorriso_lsx_filev() */; |
|
|
|
} else { |
|
if(flag&1) { |
|
sprintf(xorriso->result_line, "total %d\n", dfilec); |
|
Xorriso_result(xorriso,0); |
|
} |
|
Xorriso_lsx_filev(xorriso, path, |
|
dfilec, dfilev, boss_mem, (flag&1)|2|8); |
|
} |
|
if(dfilec>0) |
|
Sfile_destroy_argv(&dfilec, &dfilev, 0); |
|
continue; |
|
} else |
|
if(pass>0) |
|
continue; |
|
link_target[0]= 0; |
|
rpt[0]= 0; |
|
if((flag&5)==1) { |
|
Xorriso_local_getfacl(xorriso, path, &acl_text, 16); |
|
ret= Xorriso_format_ls_l(xorriso, &stbuf, (acl_text != NULL) << 1); |
|
Xorriso_local_getfacl(xorriso, path, &acl_text, 1 << 15); |
|
if(ret<=0) |
|
continue; |
|
if(S_ISLNK(stbuf.st_mode)) { |
|
ret= Xorriso_resolve_link(xorriso, path, link_target, 1); |
|
if(ret<=0) |
|
link_target[0]= 0; |
|
} |
|
} else if(flag&4) { /* -du or -dus */ |
|
size= stbuf.st_size; |
|
if(S_ISDIR(stbuf.st_mode)) { |
|
ret= Xorriso_show_dux_subs(xorriso, path, filev[i], &size, boss_mem, |
|
NULL, flag&1); |
|
if(ret<0) |
|
{ret= -1; goto ex;} |
|
if(ret==0) |
|
continue; |
|
} |
|
if(xorriso->sh_style_result) |
|
sprintf(rpt, "%-7.f ",(double) (size/1024)); |
|
else |
|
sprintf(rpt, "%7.f ",(double) (size/1024)); |
|
} |
|
if(link_target[0]) { |
|
Xorriso_esc_filepath(xorriso,filev[i], xorriso->result_line, 1); |
|
strcat(xorriso->result_line, " -> "); |
|
Xorriso_esc_filepath(xorriso,link_target, xorriso->result_line, 1 | 2); |
|
} else { |
|
Xorriso_esc_filepath(xorriso,filev[i], xorriso->result_line, 1); |
|
} |
|
strcat(xorriso->result_line, "\n"); |
|
Xorriso_result(xorriso, 0); |
|
} |
|
ret= !was_error; |
|
ex:; |
|
Xorriso_free_meM(path); |
|
Xorriso_free_meM(link_target); |
|
return(ret); |
|
} |
|
|
|
|
|
/* |
|
@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= permission to call Xorriso_make_accessible() |
|
@return <=0 = error |
|
1 = removed leaf file object |
|
2 = removed directory or tree |
|
3 = did not remove on user revocation |
|
*/ |
|
int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag) |
|
{ |
|
int ret, is_dir= 0, made_accessible= 0; |
|
struct stat victim_stbuf; |
|
struct DirseQ *dirseq= NULL; |
|
char *sfe= NULL, *sub_path= NULL; |
|
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); |
|
sub_path= malloc(2*SfileadrL); |
|
if(sfe==NULL || sub_path==NULL) { |
|
Xorriso_no_malloc_memory(xorriso, &sfe, 0); |
|
{ret= -1; goto ex;} |
|
} |
|
|
|
if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0) |
|
{ret= 0; goto ex;} |
|
|
|
ret= lstat(path, &victim_stbuf); |
|
if(ret==-1) { |
|
if((flag & 64) && errno == EACCES) { |
|
ret= Xorriso_make_accessible(xorriso, path, 0); |
|
if(ret < 0) |
|
goto ex; |
|
made_accessible= 1; |
|
ret= lstat(path, &victim_stbuf); |
|
} |
|
if(ret==-1) { |
|
sprintf(xorriso->info_text, "Cannot lstat(%s)", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
if(strcmp(path, "/")==0) { |
|
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(S_ISDIR(victim_stbuf.st_mode)) |
|
is_dir= 1; |
|
if(!is_dir) { |
|
if(flag&2) { /* rmdir */ |
|
sprintf(xorriso->info_text, "%s in disk filesystem 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 */ |
|
|
|
#ifdef Osirrox_not_yeT |
|
/* >>> */ |
|
|
|
struct stat *victim_node= NULL; |
|
|
|
victim_node= &victim_stbuf; |
|
|
|
if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) || |
|
(flag&32)) { |
|
/* 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))|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 /* Osirrox_not_yeT */ |
|
|
|
sprintf(xorriso->info_text, "-rm_rx is not implemented yet"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
|
|
#endif /* !Osirrox_not_yeT */ |
|
|
|
} else { |
|
if(!(flag&2)) { /* not rmdir */ |
|
sprintf(xorriso->info_text, "%s in disk filesystem is a directory", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
ret= Dirseq_new(&dirseq, path, 1); |
|
if(ret>0) { |
|
ret= Dirseq_next_adr(dirseq, sfe, 0); |
|
if(ret>0) { |
|
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(xorriso->request_to_abort) |
|
{ret= 3; goto ex;} |
|
ret= Xorriso_reassure_restore(xorriso, path, (flag&(4|8)) | !!is_dir); |
|
if(ret<=0 || ret==3) |
|
goto ex; |
|
if(is_dir) |
|
ret= rmdir(path); |
|
else |
|
ret= unlink(path); |
|
if(ret == -1) { |
|
if((flag & 64) && errno == EACCES && !made_accessible) { |
|
ret= Xorriso_make_accessible(xorriso, path, 0); |
|
if(ret < 0) |
|
goto ex; |
|
made_accessible= 1; |
|
if(is_dir) |
|
ret= rmdir(path); |
|
else |
|
ret= unlink(path); |
|
} |
|
if(ret == -1) { |
|
sprintf(xorriso->info_text, "Cannot delete from disk filesystem %s", |
|
Text_shellsafe(path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
ret= -1; goto ex; |
|
} |
|
} |
|
if(flag&16) |
|
xorriso->pacifier_count++; |
|
ret= 1+!!is_dir; |
|
ex:; |
|
if(made_accessible) |
|
Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0); |
|
if(sfe!=NULL) |
|
free(sfe); |
|
if(sub_path!=NULL) |
|
free(sub_path); |
|
Dirseq_destroy(&dirseq, 0); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= recursion |
|
*/ |
|
int Xorriso_findx_action(struct XorrisO *xorriso, struct FindjoB *job, |
|
char *abs_path, char *show_path, int depth, int flag) |
|
{ |
|
int ret= 0, type, action= 0, dpl= 0, compare_result, uret; |
|
uid_t user= 0; |
|
gid_t group= 0; |
|
time_t date= 0; |
|
mode_t mode_or= 0, mode_and= ~1; |
|
char *target, *text_2, *wdi_mem= NULL, *disk_prefix, *iso_path= NULL; |
|
char *basename; |
|
struct FindjoB *subjob; |
|
struct stat stbuf; |
|
|
|
Xorriso_alloc_meM(iso_path, char, SfileadrL); |
|
|
|
action= Findjob_get_action_parms(job, &target, &text_2, &user, &group, |
|
&mode_and, &mode_or, &type, &date, &subjob, 0); |
|
if(action<0) |
|
action= 0; |
|
if(action<0) |
|
action= 0; |
|
if(action==15 || action==16 || action==18 || action==19 || action==20) { |
|
/* in_iso , not_in_iso, add_missing , empty_iso_dir , is_full_in_iso */ |
|
Findjob_get_start_path(job, &disk_prefix, 0); |
|
if(strncmp(abs_path, disk_prefix, strlen(disk_prefix))!=0) |
|
{ret= -1; goto ex;} |
|
dpl= strlen(disk_prefix); |
|
if(strlen(target)+strlen(abs_path)-dpl >= SfileadrL) |
|
{ret= -1; goto ex;} |
|
if(abs_path[dpl]=='/') |
|
dpl++; |
|
ret= Xorriso_make_abs_adr(xorriso, target, abs_path+dpl, iso_path, 4); |
|
if(ret<=0) |
|
{goto ex;} |
|
|
|
} |
|
if(action==15) { /* in_iso */ |
|
ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0); |
|
if(ret<0) |
|
{ret= 1; goto ex;} |
|
Text_shellsafe(show_path, xorriso->result_line, 0); |
|
strcat(xorriso->result_line, "\n"); |
|
Xorriso_result(xorriso, 0); |
|
ret= 1; |
|
} else if(action==16) { /* not_in_iso */ |
|
ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl, |
|
&compare_result, 4); |
|
if(ret<xorriso->find_compare_result) |
|
xorriso->find_compare_result= ret; |
|
if(ret>=0) |
|
ret= 1; |
|
} else if(action==18) { /* add_missing */ |
|
ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl, |
|
&compare_result, 4|(1<<31)); |
|
if(ret<xorriso->find_compare_result) |
|
xorriso->find_compare_result= ret; |
|
if(ret==0) { |
|
uret= Xorriso_update_interpreter(xorriso, NULL, NULL, compare_result, |
|
abs_path, iso_path, ((flag&1)<<2) | 2); |
|
if(uret<=0) |
|
ret= 0; |
|
} |
|
if(ret>=0) |
|
ret= 1; |
|
} else if(action==19) { /* empty_iso_dir */ |
|
ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0); |
|
if(ret<0) |
|
{ret= 1; goto ex;} |
|
if(!S_ISDIR(stbuf.st_mode)) |
|
{ret= 1; goto ex;} |
|
ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, iso_path, 1|32); |
|
if(ret>0) { |
|
sprintf(xorriso->info_text, "Emptied directory "); |
|
Text_shellsafe(iso_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); |
|
} |
|
} else if(action==20) { /* is_full_in_iso */ |
|
ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0); |
|
if(ret<0) |
|
{ret= 1; goto ex;} |
|
if(!S_ISDIR(stbuf.st_mode)) |
|
{ret= 1; goto ex;} |
|
wdi_mem= strdup(xorriso->wdi); |
|
if(wdi_mem == NULL) { |
|
Xorriso_no_malloc_memory(xorriso, NULL, 0); |
|
{ret= -1; goto ex;} |
|
} |
|
strcpy(xorriso->wdi, iso_path); |
|
ret= Xorriso_ls(xorriso, 4|8); |
|
strcpy(xorriso->wdi, wdi_mem); |
|
if(ret>0) { |
|
strcpy(xorriso->result_line, "d "); |
|
Text_shellsafe(iso_path, xorriso->result_line, 1); |
|
strcat(xorriso->result_line, |
|
" (ISO) : non-empty directory (would not match mount point)\n"); |
|
Xorriso_result(xorriso,0); |
|
} |
|
{ret= 1; goto ex;} |
|
} else if(action == 40) { /* estimate_size */ |
|
basename= strrchr(abs_path, '/'); |
|
if(basename != NULL) |
|
basename++; |
|
else |
|
basename= abs_path; |
|
ret= lstat(abs_path, &stbuf); |
|
if(ret != -1) |
|
ret= Xorriso_estimate_file_size(xorriso, job, basename, stbuf.st_mode, |
|
stbuf.st_size, 0); |
|
} else if(action == 44) { /* list_extattr */ |
|
ret= Xorriso_list_extattr(xorriso, NULL, abs_path, show_path, target, 2); |
|
} else { |
|
Xorriso_esc_filepath(xorriso,show_path, xorriso->result_line, 0); |
|
strcat(xorriso->result_line, "\n"); |
|
Xorriso_result(xorriso, 0); |
|
ret= 1; |
|
} |
|
ex:; |
|
if(action==15 || action==16 || action==18 || action==19 || action==20) |
|
if(xorriso->no_volset_present) |
|
xorriso->request_to_abort= 1; /* Need an image. No use to try again. */ |
|
if(wdi_mem != NULL) |
|
free(wdi_mem); |
|
Xorriso_free_meM(iso_path); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0=recursion |
|
*/ |
|
int Xorriso_findx(struct XorrisO *xorriso, struct FindjoB *job, |
|
char *abs_dir_parm, char *dir_path, |
|
struct stat *dir_stbuf, int depth, |
|
struct LinkiteM *link_stack, int flag) |
|
{ |
|
int ret,is_link, no_dive; |
|
struct DirseQ *dirseq= NULL; |
|
struct stat stbuf; |
|
struct LinkiteM *own_link_stack; |
|
char *abs_dir_path, *namept; |
|
char *name= NULL, *path= NULL, *sfe= NULL; |
|
char *abs_dir_path_data= NULL, *abs_path= NULL; |
|
|
|
if(xorriso->request_to_abort) |
|
{ret= 0; goto ex;} |
|
|
|
Xorriso_alloc_meM(sfe, char, 5*SfileadrL); |
|
Xorriso_alloc_meM(name, char, SfileadrL); |
|
Xorriso_alloc_meM(path, char, SfileadrL); |
|
Xorriso_alloc_meM(abs_dir_path_data, char, SfileadrL); |
|
Xorriso_alloc_meM(abs_path, char, SfileadrL); |
|
|
|
own_link_stack= link_stack; |
|
abs_dir_path= abs_dir_parm; |
|
if(abs_dir_path[0]==0) { |
|
ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, dir_path, |
|
abs_dir_path_data, 1|2|8); |
|
if(ret<=0) |
|
goto ex; |
|
abs_dir_path= abs_dir_path_data; |
|
ret= Xorriso_path_is_excluded(xorriso, abs_dir_path, !(flag&1)); |
|
if(ret<0) |
|
goto ex; |
|
if(ret>0) |
|
{ret= 0; goto ex;} |
|
ret= lstat(abs_dir_path, dir_stbuf); |
|
if(ret==-1) |
|
{ret= 0; goto ex;} |
|
if(S_ISLNK(dir_stbuf->st_mode) && |
|
(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1)))) |
|
if(stat(abs_dir_path, &stbuf)!=-1) |
|
if(dir_stbuf->st_dev == stbuf.st_dev || |
|
(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1)))) |
|
memcpy(dir_stbuf, &stbuf, sizeof(struct stat)); |
|
|
|
namept= strrchr(dir_path, '/'); |
|
if(namept==NULL) |
|
namept= dir_path; |
|
else |
|
namept++; |
|
|
|
ret= Findjob_test_2(xorriso, job, NULL, namept, dir_path, NULL, dir_stbuf, |
|
0); |
|
if(ret<0) |
|
goto ex; |
|
if(ret>0) { |
|
ret= Xorriso_findx_action(xorriso, job, abs_dir_path, dir_path, depth, |
|
flag&1); |
|
if(xorriso->request_to_abort) |
|
{ret= 0; goto ex;} |
|
if(ret<=0) { |
|
if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0) |
|
goto ex; |
|
} |
|
} |
|
} |
|
if(xorriso->request_to_abort) |
|
{ret= 1; goto ex;} |
|
if(!S_ISDIR(dir_stbuf->st_mode)) |
|
{ret= 2; goto ex;} |
|
|
|
ret= Dirseq_new(&dirseq, abs_dir_path, 1); |
|
if(ret<0) { |
|
sprintf(xorriso->info_text, "Cannot obtain disk directory iterator"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
{ret= -1; goto ex;} |
|
} |
|
if(ret==0) |
|
{ret= 2; goto ex;} |
|
|
|
while(!xorriso->request_to_abort) { |
|
Linkitem_reset_stack(&own_link_stack, link_stack, 0); |
|
ret= Dirseq_next_adr(dirseq,name,0); |
|
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;} |
|
} |
|
ret= Xorriso_make_abs_adr(xorriso, abs_dir_path, name, abs_path, 1); |
|
if(ret<=0) |
|
goto ex; |
|
ret= Xorriso_make_abs_adr(xorriso, dir_path, name, path, 4); |
|
if(ret<=0) |
|
goto ex; |
|
ret= Xorriso_path_is_excluded(xorriso, abs_path, 0); /* (is never param) */ |
|
if(ret<0) |
|
goto ex; |
|
if(ret>0) |
|
continue; |
|
ret= lstat(abs_path, &stbuf); |
|
if(ret==-1) |
|
continue; |
|
no_dive= 0; |
|
|
|
is_link= S_ISLNK(stbuf.st_mode); |
|
if(is_link && xorriso->do_follow_links) { |
|
ret= Xorriso_hop_link(xorriso, abs_path, &own_link_stack, &stbuf, 2); |
|
if(ret<0) |
|
{ret= -1; goto ex;} |
|
if(ret!=1) |
|
no_dive= 1; |
|
} |
|
|
|
ret= Findjob_test_2(xorriso, job, NULL, name, path, dir_stbuf, &stbuf, 0); |
|
if(ret<0) |
|
goto ex; |
|
if(ret>0) { |
|
ret= Xorriso_findx_action(xorriso, job, abs_path, path, depth, flag&1); |
|
if(xorriso->request_to_abort) |
|
{ret= 0; goto ex;} |
|
if(ret<=0) { |
|
if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0) |
|
goto ex; |
|
} |
|
} |
|
if(!S_ISDIR(stbuf.st_mode)) |
|
no_dive= 1; |
|
if(dir_stbuf->st_dev != stbuf.st_dev && !xorriso->do_follow_mount) |
|
no_dive= 1; |
|
if(!no_dive) { |
|
ret= Xorriso_findx(xorriso, job, abs_path, path, &stbuf, depth+1, |
|
own_link_stack, flag|1); |
|
if(ret<0) |
|
goto ex; |
|
} |
|
} |
|
|
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(sfe); |
|
Xorriso_free_meM(name); |
|
Xorriso_free_meM(path); |
|
Xorriso_free_meM(abs_dir_path_data); |
|
Xorriso_free_meM(abs_path); |
|
Dirseq_destroy(&dirseq, 0); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= no hardlink reconstruction |
|
bit1= do not set xorriso->node_*_prefixes |
|
bit5= -extract_single: eventually do not insert directory tree |
|
*/ |
|
int Xorriso_restore_sorted(struct XorrisO *xorriso, int count, |
|
char **src_array, char **tgt_array, |
|
int *problem_count, int flag) |
|
{ |
|
int i, ret, with_node_array= 0, hflag= 0, hret; |
|
|
|
*problem_count= 0; |
|
if(!(((xorriso->ino_behavior & 16) && xorriso->do_restore_sort_lba) || |
|
(xorriso->ino_behavior & 4) || (flag & 1))) { |
|
ret= Xorriso_make_hln_array(xorriso, 0); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
if(xorriso->do_restore_sort_lba) { |
|
/* Count affected nodes */ |
|
Xorriso_destroy_node_array(xorriso, 0); |
|
for(i= 0; i < count; i++) { |
|
if(src_array[i] == NULL || tgt_array[i] == NULL) |
|
continue; |
|
/* sort_lba : Make directories plus node_array and then |
|
run array extractor (with eventual hardlink detection) |
|
*/ |
|
hflag= (1 << 7) | ((!!(flag & 2)) << 9) | (flag & 32); |
|
ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i], |
|
(off_t) 0, (off_t) 0, hflag); |
|
if(ret <= 0) { |
|
(*problem_count)++; |
|
hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2); |
|
if(hret < 0) |
|
goto ex; |
|
} |
|
with_node_array= 1; |
|
} |
|
} |
|
|
|
if(with_node_array) { |
|
/* Allocate and fill node array */ |
|
if(xorriso->node_counter <= 0) |
|
{ret= 2; goto ex;} |
|
ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit, 0, |
|
!xorriso->do_restore_sort_lba); |
|
if(ret<=0) |
|
goto ex; |
|
for(i= 0; i < count; i++) { |
|
if(src_array[i] == NULL || tgt_array[i] == NULL) |
|
continue; |
|
ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i], |
|
(off_t) 0, (off_t) 0, (2 << 7) | (flag & 32)); |
|
if(ret <= 0) { |
|
(*problem_count)++; |
|
hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2); |
|
if(hret < 0) |
|
goto ex; |
|
} |
|
} |
|
} |
|
|
|
/* Perform restore operations */ |
|
if(xorriso->do_restore_sort_lba) { |
|
ret= Xorriso_restore_node_array(xorriso, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
} else { |
|
for(i= 0; i < count; i++) { |
|
if(src_array[i] == NULL || tgt_array[i] == NULL) |
|
continue; |
|
ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i], |
|
(off_t) 0, (off_t) 0, flag & 32); |
|
if(ret <= 0) { |
|
(*problem_count)++; |
|
hret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2); |
|
if(hret < 0) |
|
goto ex; |
|
} |
|
} |
|
} |
|
|
|
ret= 1; |
|
ex:; |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= path is a directory |
|
bit2= recursion: do not reassure in mode 2 "tree" |
|
bit3-7= question text mode |
|
0= plain removal |
|
1= replacing file object |
|
2= overwriting of content, keeping file object |
|
3= appending of content, keeping file object |
|
*/ |
|
int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag) |
|
{ |
|
int ret, mode; |
|
|
|
mode= (flag >> 3) & 31; |
|
while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4))) |
|
&& !xorriso->request_not_to_ask) { |
|
/* ls -ld */ |
|
Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 1|2|8); |
|
if(flag&1) /* du -s */ |
|
Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 2|4); |
|
if(mode == 3) |
|
sprintf(xorriso->info_text, |
|
"File exists. Append content ? n= no, y= yes, x= abort, @= stop asking\n"); |
|
else if(mode == 2) |
|
sprintf(xorriso->info_text, |
|
"File exists. Overwrite content ? n= no, y= yes, x= abort, @= stop asking\n"); |
|
else if(mode == 1) |
|
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, |
|
"File alteration operation aborted by user before file: "); |
|
Text_shellsafe(path, xorriso->info_text, 1); |
|
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: "); |
|
Text_shellsafe(path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
ret= 3; goto ex; |
|
} |
|
} |
|
ret= 1; |
|
ex: |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit7= return 4 if restore fails from denied permission |
|
do not issue error message |
|
@return <=0 failure , 1 success , |
|
4 with bit7: permission to create file was denied |
|
*/ |
|
int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path, |
|
char *tmp_path, int *fd, int flag) |
|
{ |
|
char *cpt; |
|
|
|
cpt= strrchr(orig_path, '/'); |
|
if(cpt==NULL) |
|
tmp_path[0]= 0; |
|
else { |
|
strncpy(tmp_path, orig_path, cpt+1-orig_path); |
|
tmp_path[cpt+1-orig_path]= 0; |
|
} |
|
strcat(tmp_path, "_tmp_xorriso_restore_XXXXXX"); |
|
*fd= mkstemp(tmp_path); |
|
if(*fd==-1) { |
|
if(errno == EACCES && (flag & 128)) |
|
return(4); |
|
strcpy(xorriso->info_text, "Cannot create temporary file : "); |
|
Text_shellsafe(tmp_path, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
return(0); |
|
} |
|
fchmod(*fd, S_IRUSR|S_IWUSR); |
|
return(1); |
|
} |
|
|
|
|
|
/* @param flag bit0= change regardless of xorriso->do_auto_chmod |
|
bit1= desired is only rx |
|
@return -1=severe error , -2= cannot chmod, 0= nothing to do, 1 = chmoded |
|
*/ |
|
int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag) |
|
{ |
|
int ret, is_link= 0; |
|
char *path_pt, *link_target= NULL; |
|
mode_t mode, desired= S_IRUSR | S_IWUSR | S_IXUSR; |
|
struct stat stbuf; |
|
|
|
Xorriso_alloc_meM(link_target, char, SfileadrL); |
|
|
|
if(!(xorriso->do_auto_chmod || (flag & 1))) |
|
{ret= 0; goto ex;} |
|
|
|
if(flag & 2) |
|
desired &= ~S_IWUSR; |
|
path_pt= disk_path; |
|
ret= lstat(path_pt, &stbuf); |
|
if(ret==-1) |
|
{ret= 0; goto ex;} |
|
if(S_ISLNK(stbuf.st_mode)) { |
|
is_link= 1; |
|
ret= stat(path_pt, &stbuf); |
|
if(ret==-1) |
|
{ret= 0; goto ex;} |
|
} |
|
if(!S_ISDIR(stbuf.st_mode)) |
|
{ret= 0; goto ex;} |
|
if(is_link) { |
|
ret= Xorriso_resolve_link(xorriso, path_pt, link_target, 0); |
|
if(ret<=0) |
|
goto ex; |
|
path_pt= link_target; |
|
} |
|
if((stbuf.st_mode & desired) == desired) |
|
{ret= 0; goto ex;} |
|
if(stbuf.st_uid!=geteuid()) |
|
{ret= -2; goto ex;} |
|
|
|
mode= (stbuf.st_mode | desired) & 07777; |
|
ret= chmod(path_pt, mode); |
|
if(ret==-1) { |
|
sprintf(xorriso->info_text, |
|
"Cannot change access permissions of disk directory: chmod %o ", |
|
(unsigned int) (mode & 07777)); |
|
Text_shellsafe(path_pt, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0); |
|
{ret= -2; goto ex;} |
|
} |
|
ret= Permstack_push(&(xorriso->perm_stack), path_pt, &stbuf, 0); |
|
if(ret<=0) |
|
goto ex; |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(link_target); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_make_accessible(struct XorrisO *xorriso, char *disk_path, int flag) |
|
{ |
|
int done= 0, ret, just_rx= 2; |
|
char *npt, *apt, *path, *wpt; |
|
|
|
Xorriso_alloc_meM(path, char, SfileadrL); |
|
|
|
apt= disk_path; |
|
wpt= path; |
|
for(npt= apt; !done; apt= npt + 1) { |
|
npt= strchr(apt, '/'); |
|
if(npt == NULL) |
|
break; |
|
if(strchr(npt + 1, '/') == NULL) |
|
just_rx= 0; |
|
strncpy(wpt, apt, npt + 1 - apt); |
|
wpt+= npt + 1 - apt; |
|
*wpt= 0; |
|
ret= Xorriso_auto_chmod(xorriso, path, just_rx); |
|
if(ret == -1) |
|
{ret= -1; goto ex;} |
|
if(ret == -2) |
|
{ret= 0; goto ex;} |
|
} |
|
ret= 1; |
|
ex: |
|
Xorriso_free_meM(path); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= prefer to find a match after *img_prefixes |
|
(but deliver img_prefixes if no other can be found) |
|
*/ |
|
int Xorriso_make_restore_path(struct XorrisO *xorriso, |
|
struct Xorriso_lsT **img_prefixes, struct Xorriso_lsT **disk_prefixes, |
|
char img_path[SfileadrL], char disk_path[SfileadrL], int flag) |
|
{ |
|
int li; |
|
struct Xorriso_lsT *s, *d, *found_s= NULL, *found_d= NULL; |
|
char *ipfx, *dpfx; |
|
|
|
/* Obtain disk_path by replacing start piece of img_path */ |
|
|
|
d= *disk_prefixes; |
|
for(s= *img_prefixes; s != NULL; |
|
s= Xorriso_lst_get_next(s, 0), d= Xorriso_lst_get_next(d, 0)) { |
|
|
|
ipfx= Xorriso_lst_get_text(s, 0); |
|
li= strlen(ipfx); |
|
dpfx= Xorriso_lst_get_text(d, 0); |
|
if(li == 1 && ipfx[0] == '/') { |
|
li= 0; |
|
if(img_path[0] != '/') |
|
continue; |
|
} else { |
|
if(strncmp(img_path, ipfx, li) != 0) |
|
continue; |
|
if(img_path[li] != 0 && img_path[li] != '/') |
|
continue; |
|
} |
|
if(strlen(dpfx) + strlen(img_path) - li + 1 >= SfileadrL) |
|
return(-1); |
|
if(img_path[li]=='/') { |
|
if(dpfx[0] == '/' && dpfx[1] == 0) |
|
sprintf(disk_path, "/%s", img_path + li + 1); |
|
else |
|
sprintf(disk_path, "%s/%s", dpfx, img_path + li + 1); |
|
} else |
|
strcpy(disk_path, dpfx); /* img_path[li] is 0, img_path equals ipfx */ |
|
found_s= s; |
|
found_d= d; |
|
if(s != *img_prefixes || !(flag & 1)) |
|
break; |
|
} |
|
*img_prefixes= found_s; |
|
*disk_prefixes= found_d; |
|
return(found_s != NULL); |
|
} |
|
|
|
|
|
/* @param flag bit0=permission to run Xorriso_make_accessible |
|
*/ |
|
int Xorriso_restore_make_hl(struct XorrisO *xorriso, |
|
char *old_path, char *new_path, int flag) |
|
{ |
|
int ret; |
|
struct PermiteM *perm_stack_mem; |
|
|
|
ret= link(old_path, new_path); |
|
if(ret == 0) |
|
return(1); |
|
if(errno == EACCES && (flag & 1)) { |
|
perm_stack_mem= xorriso->perm_stack; |
|
ret= Xorriso_make_accessible(xorriso, new_path, 0); |
|
if(ret > 0) { |
|
ret= link(old_path, new_path); |
|
if(ret == 0) { |
|
Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0); |
|
return(1); |
|
} |
|
} |
|
Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0); |
|
} |
|
|
|
sprintf(xorriso->info_text, "Hardlinking failed: "); |
|
Text_shellsafe(new_path, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, " -> "); |
|
Text_shellsafe(old_path, xorriso->info_text, 1 | 2); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "WARNING", 0); |
|
return(0); |
|
} |
|
|
|
|
|
int Xorriso_afile_fopen(struct XorrisO *xorriso, |
|
char *filename, char *mode, FILE **ret_fp, int flag) |
|
/* |
|
bit0= do not print error message on failure |
|
bit1= do not open stdin |
|
*/ |
|
{ |
|
FILE *fp= NULL; |
|
|
|
*ret_fp= NULL; |
|
if(strcmp(filename,"-")==0) { |
|
if(mode[0]=='a' || mode[0]=='w' || |
|
(mode[0]=='r' && mode[1]=='+') || |
|
(mode[0]=='r' && mode[1]=='b' && mode[2]=='+')) |
|
fp= stdout; |
|
else if(flag & 2) { |
|
Xorriso_msgs_submit(xorriso, 0, "Not allowed as input path: '-'", 0, |
|
"FAILURE", 0); |
|
return(0); |
|
} else { |
|
Xorriso_msgs_submit(xorriso, 0, "Ready for data at standard input", 0, |
|
"NOTE", 0); |
|
fp= stdin; |
|
} |
|
} else if(strncmp(filename,"tcp:",4)==0){ |
|
Xorriso_msgs_submit(xorriso, 0, "TCP/IP service isn't implemented yet.", 0, |
|
"FAILURE", 0); |
|
} else if(strncmp(filename,"file:",5)==0){ |
|
fp= fopen(filename+5,mode); |
|
} else { |
|
fp= fopen(filename,mode); |
|
} |
|
if(fp==NULL){ |
|
if(!(flag&1)) { |
|
sprintf(xorriso->info_text, |
|
"Failed to open file '%s' in %s mode", filename, mode); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
} |
|
return(0); |
|
} |
|
*ret_fp= fp; |
|
return(1); |
|
} |
|
|
|
|
|
/* |
|
@param flag bit0= make absolute command paths with known systems |
|
bit1= do not allow prefixes with cmd |
|
bit2= interpret unprefixed cmd as shell: |
|
bit3= do not care for device filetype |
|
*/ |
|
int Xorriso_make_mount_cmd(struct XorrisO *xorriso, char *cmd, |
|
int lba, int track, int session, char *volid, |
|
char *devadr, char result[SfileadrL], int flag) |
|
{ |
|
int ret, reg_file= 0, is_safe= 0, sys_code= 0; |
|
char *form= NULL, session_text[12], track_text[12], lba_text[12]; |
|
char *vars[5][2], *sfe= NULL, *volid_sfe= NULL, *cpt, *sysname; |
|
char *cooked_dev= NULL, *eff_dev; |
|
struct stat stbuf; |
|
|
|
Xorriso_alloc_meM(form, char, 6 * SfileadrL); |
|
Xorriso_alloc_meM(sfe, char, 5 * SfileadrL); |
|
Xorriso_alloc_meM(volid_sfe, char, 5 * 80 + 1); |
|
Xorriso_alloc_meM(cooked_dev, char, SfileadrL); |
|
|
|
if(strlen(cmd) > SfileadrL) { |
|
Xorriso_msgs_submit(xorriso, 0, "Argument much too long", 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
eff_dev= devadr; |
|
ret= stat(devadr, &stbuf); |
|
if(ret != -1 && !(flag & 8)) |
|
if(S_ISREG(stbuf.st_mode)) |
|
reg_file= 1; |
|
if(strncmp(cmd, "linux:", 6) == 0 && !(flag & 2)) { |
|
cpt= cmd + 6; |
|
sys_code= 1; |
|
} else if(strncmp(cmd, "freebsd:", 8) == 0 && !(flag & 2)) { |
|
cpt= cmd + 8; |
|
sys_code= 2; |
|
} else if(strncmp(cmd, "netbsd:", 7) == 0 && !(flag & 2)) { |
|
cpt= cmd + 7; |
|
sys_code= 3; |
|
} else if(strncmp(cmd, "string:", 7) == 0 && !(flag & 2)) { |
|
cpt= cmd + 7; |
|
strcpy(form, cpt); |
|
} else if(flag & 4) { |
|
cpt= cmd; |
|
strcpy(form, cpt); |
|
} else { |
|
cpt= cmd; |
|
ret= System_uname(&sysname, NULL, NULL, NULL, 0); |
|
if(ret <= 0) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"-mount*: Cannot determine current system type", |
|
0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} else if(strcmp(sysname, "FreeBSD") == 0 || |
|
strcmp(sysname, "GNU/kFreeBSD") == 0) { |
|
/* "GNU/kFreeBSD" = Debian kfreebsd */ |
|
sys_code= 2; |
|
} else if(strcmp(sysname, "NetBSD") == 0) { |
|
sys_code= 3; |
|
} else if(strcmp(sysname, "Linux") == 0) { |
|
sys_code= 1; |
|
} else { |
|
sprintf(xorriso->info_text, "-mount*: Unsupported system type %s", |
|
Text_shellsafe(sysname, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
|
|
if(sys_code == 1) { /* GNU/Linux */ |
|
sprintf(form, |
|
"%smount -t iso9660 -o %snodev,noexec,nosuid,ro,sbsector=%%sbsector%% %%device%% %s", |
|
(flag & 1 ? "/bin/" : ""), |
|
(reg_file || (xorriso->mount_opts_flag & 1) ? "loop," : ""), |
|
Text_shellsafe(cpt, sfe, 0)); |
|
is_safe= 1; |
|
} else if(sys_code == 2 || sys_code == 3) { /* FreeBSD , NetBSD */ |
|
if(reg_file) { |
|
|
|
/* <<< Considered to create vnode as of |
|
J.R. Oldroyd <fbsd@opal.com>, 20 Nov 2008 |
|
but for now refraining from creating that persistent file object |
|
|
|
strcpy(form, "n=$(mdconfig -a -t vnode -f %device%)"); |
|
sprintf(form + strlen(form), |
|
" && mount -t cd9660 -o noexec,nosuid -s %%sbsector%% /dev/\"$n\" %s", |
|
Text_shellsafe(cmd+8, sfe, 0)); |
|
*/ |
|
|
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Detected regular file as mount device with BSD style command.", |
|
0, "FAILURE", 0); |
|
if(sys_code == 2) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Command mdconfig -a -t vnode -f can create a device node which uses the file", |
|
0, "HINT", 0); |
|
} else { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Command vnconfig -c vndX can create a device node which uses the file", |
|
0, "HINT", 0); |
|
} |
|
{ret= 0; goto ex;} |
|
} else { |
|
if(sys_code == 3 && strncmp(devadr, "/dev/rcd", 8) == 0) { |
|
sprintf(cooked_dev, "/dev/cd%s", devadr + 8); |
|
eff_dev= cooked_dev; |
|
} |
|
sprintf(form, |
|
"%smount_cd9660 -o noexec,nosuid -s %%sbsector%% %%device%% %s", |
|
(flag & 1 ? "/sbin/" : ""), Text_shellsafe(cpt, sfe, 0)); |
|
} |
|
is_safe= 1; |
|
} |
|
sprintf(session_text, "%d", session); |
|
sprintf(track_text, "%d", track); |
|
sprintf(lba_text, "%d", lba); |
|
vars[0][0]= "sbsector"; |
|
vars[0][1]= lba_text; |
|
vars[1][0]= "track"; |
|
vars[1][1]= track_text; |
|
vars[2][0]= "session"; |
|
vars[2][1]= session_text; |
|
vars[3][0]= "volid"; |
|
vars[3][1]= Text_shellsafe(volid, volid_sfe, 0); |
|
vars[4][0]= "device"; |
|
vars[4][1]= Text_shellsafe(eff_dev, sfe, 0); |
|
ret= Sregex_resolve_var(form, vars, 5, "%", "%", "%", result, SfileadrL, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
ret= 1 + is_safe; |
|
ex:; |
|
Xorriso_free_meM(cooked_dev); |
|
Xorriso_free_meM(volid_sfe); |
|
Xorriso_free_meM(sfe); |
|
Xorriso_free_meM(form); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_append_scdbackup_record(struct XorrisO *xorriso, int flag) |
|
{ |
|
FILE *fp= NULL; |
|
char dummy[81], name[81], timestamp[81], size[81], md5[81]; |
|
|
|
if(xorriso->scdbackup_tag_written[0] == 0) |
|
return(1); |
|
|
|
name[0]= timestamp[0]= size[0]= md5[0]= 0; |
|
sscanf(xorriso->scdbackup_tag_written, "%s %s %s %s %s %s %s", |
|
dummy, dummy, dummy, name, timestamp, size, md5); |
|
sprintf(xorriso->info_text, "scdbackup tag written : %s %s %s %s\n", |
|
name, timestamp, size, md5); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
|
|
if(xorriso->scdbackup_tag_listname[0]) { |
|
fp= fopen(xorriso->scdbackup_tag_listname, "a"); |
|
if(fp==0) { |
|
strcpy(xorriso->info_text, "-scdbackup_tag: Cannot open file "); |
|
Text_shellsafe(xorriso->scdbackup_tag_listname, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(0); |
|
} |
|
fprintf(fp, "%s %s %s %s\n", name, timestamp, size, md5); |
|
fclose(fp); |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
/* @param flag bit0= for append rather than overwrite |
|
*/ |
|
int Xorriso_is_concat_target(struct XorrisO *xorriso, char *target, |
|
int *ftype, int *fd, int flag) |
|
{ |
|
int ret; |
|
char *why= ""; |
|
|
|
*ftype= 0; |
|
*fd = -1; |
|
|
|
if(strcmp(target, "-") == 0) { |
|
*fd= 1; |
|
*ftype= 8; /* character device */ |
|
return(1); |
|
} |
|
|
|
*ftype= Sfile_type(target, 1 | 8 | 16); |
|
if(*ftype == -1) |
|
return(2); /* not yet existing regular */ |
|
|
|
if(*ftype & 1024) { |
|
*fd= Sfile_get_dev_fd_no(target, 0); |
|
*ftype &= ~1024; |
|
} |
|
if(*ftype & 2048) { |
|
why= "fstat(2) returned -1 on file descriptor number."; |
|
goto not_usable; |
|
} |
|
|
|
if(*ftype == 3) { |
|
if(!xorriso->do_follow_concat) { |
|
why= "May not follow symbolic link. No -follow \"...:concat:...\"."; |
|
goto not_usable; |
|
} |
|
*ftype= Sfile_type(target, 1 | 4 | 8); |
|
if(*ftype == -1) |
|
return(2); /* not yet existing regular */ |
|
} |
|
if(*ftype == 2) { |
|
why= "May not write data into a directory."; |
|
goto not_usable; |
|
} |
|
if(*ftype == 0) { |
|
why= "Cannot determine file type."; |
|
goto not_usable; |
|
} |
|
if(*ftype == 7) { |
|
|
|
/* >>> what to do with UNIX socket ? */; |
|
|
|
why= "Cannot yet handle socket file as target."; |
|
goto not_usable; |
|
} |
|
|
|
if(xorriso->do_overwrite != 1 && xorriso->do_overwrite != 2) { |
|
why= "May not alter existing file."; |
|
goto not_usable; |
|
} |
|
ret= Xorriso_reassure_restore(xorriso, target, (2 + (flag & 1)) << 3); |
|
if(ret <= 0 || ret == 0) { |
|
why= "User revoked alteration of existing file."; |
|
goto not_usable; |
|
} |
|
|
|
if(*ftype == 1) |
|
return(2); /* existing regular */ |
|
if(*ftype == 4 || *ftype == 6 || *ftype == 8) |
|
return(1); /* named pipe, block device, character device */ |
|
|
|
not_usable:; |
|
sprintf(xorriso->info_text, |
|
"Unsuitable -concat target: "); |
|
Text_shellsafe(target, xorriso->info_text, 1); |
|
sprintf(xorriso->info_text + strlen(xorriso->info_text), ". %s", why); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(0); |
|
} |
|
|
|
|
|
int Xorriso_concat(struct XorrisO *xorriso, char *mode, char *target, |
|
int progc, char **progv, |
|
int filec, char **filev, int flag) |
|
{ |
|
int ret, i, fd= -1, target_is_regular= 0, fd_opened= 0, ftype, prog_forked= 0; |
|
int status; |
|
int open_mode= O_WRONLY | O_CREAT; |
|
struct stat stbuf; |
|
pid_t forked_pid; |
|
|
|
for(i= 0; i < filec; i++) { |
|
ret= Xorriso_iso_lstat(xorriso, filev[i], &stbuf, 4); |
|
if(ret == -1) |
|
goto ex; |
|
if(!S_ISREG(stbuf.st_mode)) { |
|
sprintf(xorriso->info_text, |
|
"-concat: iso_rr_path is not a regular data file: "); |
|
Text_shellsafe(filev[i], xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
} |
|
if(strcmp(mode, "overwrite") == 0) { |
|
ret= Xorriso_is_concat_target(xorriso, target, &ftype, &fd, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
if(ret == 2) { |
|
target_is_regular= 1; |
|
open_mode |= O_TRUNC; |
|
} |
|
if(fd == -1) { |
|
fd= open(target, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666); |
|
fd_opened= 1; |
|
} |
|
} else if(strcmp(mode, "append") == 0) { |
|
ret= Xorriso_is_concat_target(xorriso, target, &ftype, &fd, 1); |
|
if(ret <= 0) |
|
goto ex; |
|
target_is_regular= (ret == 2); |
|
if(fd == -1) { |
|
fd= open(target, O_WRONLY | O_CREAT | O_BINARY, 0666); |
|
fd_opened= 1; |
|
if(fd != -1 && target_is_regular) { |
|
ret= lseek(fd, (off_t) 0, SEEK_END); |
|
if(ret == -1) { |
|
sprintf(xorriso->info_text, |
|
"-concat append: Cannot lseek(2) to file end of "); |
|
Text_shellsafe(target, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
} |
|
} |
|
|
|
} else if(strcmp(mode, "pipe") == 0) { |
|
ret= Xorriso_pipe_open(xorriso, "-concat pipe", progv[0], progc, progv, |
|
"", &fd, &forked_pid, 2 | 8); |
|
if(ret <= 0) |
|
goto ex; |
|
fd_opened= 1; |
|
prog_forked= 1; |
|
|
|
} else { |
|
sprintf(xorriso->info_text, "-concat: Unknown mode "); |
|
Text_shellsafe(mode, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, ". Known modes: overwrite, append, pipe"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
if(fd == -1) { |
|
sprintf(xorriso->info_text, |
|
"-concat: Cannot open file handle to "); |
|
Text_shellsafe(target, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
|
|
for(i= 0; i < filec; i++) { |
|
ret= Xorriso_iso_file_to_fd(xorriso, filev[i], fd, 0); |
|
if(ret <= 0) { |
|
if(i < filec - 1) { |
|
ret= Xorriso_eval_problem_status(xorriso, ret, 1 | 2); |
|
if(ret < 0) { |
|
sprintf(xorriso->info_text, |
|
"-concat: Aborted although %d files stay unprocessed.", |
|
filec - i + 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
} |
|
} |
|
} |
|
|
|
ret= 1; |
|
ex:; |
|
if(fd_opened && fd != -1) |
|
close(fd); |
|
if(prog_forked) |
|
Xorriso_wait_child_end(xorriso, forked_pid, &status, 0); |
|
return(ret); |
|
}
|
|
|