Implemented option -follow

master
Thomas Schmitt 15 years ago
parent 1ae0ee9b08
commit 20313a4654
  1. 107
      test/xorriso.1
  2. 537
      test/xorriso.c
  3. 20
      test/xorriso_private.h
  4. 2
      test/xorriso_timestamp.h
  5. 174
      test/xorrisoburn.c
  6. 8
      test/xorrisoburn.h

@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH XORRISO 1 "December 7, 2007"
.TH XORRISO 1 "December 15, 2007"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -71,7 +71,7 @@ Rock Ridge, POSIX, X/Open
.br
Command processing
.br
Result pager
Dialog, Readline, Result pager
.sp 1
Maybe you first want to have a look at section EXAMPLES near the end of
this text before reading the next few hundred lines of background information.
@ -105,7 +105,7 @@ together form a single filesystem image.
Adding a session to an existing ISO image is in this text referred as
\fBgrowing\fR.
.br
The multi-session model of the MMC standard does not apply to all all media
The multi-session model of the MMC standard does not apply to all media
types. But program growisofs by Andy Polyakov showed how to extend this
functionality to overwriteable media or disk files which carry valid ISO 9660
filesystems. This expansion method is referred as as emulated growing.
@ -220,8 +220,8 @@ filesystem objects as source and/or target media.
.B Libburn drives:
.br
Input drive, i.e. source of an existing or empty ISO image, can be any random
access readable libburn drive: optical media with readable data or blank,
regular files, block devices.
access readable libburn drive: optical media with readable data,
blank optical media, regular files, block devices.
.br
Rock Ridge info must be present in existing ISO images and it will be generated
by the program unconditionally.
@ -255,6 +255,7 @@ If path leads to a regular file or to a block device then the emulated drive
is random access readable and can be used for the method of growing if it
already contains a valid ISO 9660 image. Any other file type is not readable
via "stdio:" and can only be used as target for the method of modifying.
Non existing paths in existing directories are handled as empty regular files.
.PP
Be aware that especially the superuser can write into any accessible file or
device by using its path with the "stdio:" prefix. Addresses without prefix
@ -317,7 +318,23 @@ The program ends either by command -end, or by the end of program arguments
if not dialog was enabled up to that moment, or by a problem
event which triggers the threshold of command -abort_on.
.SS
.B Result pager:
.B Dialog, Readline, Result pager:
.br
Dialog mode prompts for an input line, parses it into words, and performs
them as commands with their parameters. It provides assisting services
to make dialog more comfortable.
.PP
Readline is an enhancement for the input line. You may know it already from
the bash shell.
.br
It allows to move the cursor over the text in the line by help of the
leftward and the rightward arrow key.
Text may be inserted at the cursor position. The delete key removes the
character under the cursor. Upward and Downward arrow keys navigate through
the history of previous input lines.
.br
See man readline for more info about libreadline.
.PP
Option -page activates a builtin result text pager which may be convenient in
dialog. After an action has put out the given number of terminal lines,
the pager prompts the user for a line of input.
@ -351,7 +368,7 @@ from file addresses.
.B Aquiring source and target drive:
.TP
\fB\-dev\fR address
Set input and output drive to the same address and load eventual ISO image.
Set input and output drive to the same address and load an eventual ISO image.
If there is no ISO image then create a blank one.
Set the image expansion method to growing.
.br
@ -470,9 +487,9 @@ If -pathspecs is set to "off" then eventual -disk_pattern expansion applies.
The resulting words are used as both, iso_rr_path and disk path. Eventually
-cdx gets prepended.
.TP
\fB\-path-list\fR disk_path
Like -add but read the pathspecs from file disk_path.
One pathspec per line.
\fB\-path_list\fR disk_path
Like -add but read the parameter words from file disk_path.
One pathspec resp. disk_path pattern per line.
.TP
> \fB\-cp_r\fR disk_path [***] iso_rr_path
Insert the given files or directory trees from filesystem
@ -576,7 +593,7 @@ Discard the manipulated ISO image and reload it from -indev.
.TP
\fB\-commit\fR
Perform the write operation. Afterwards eventually make the
-outdev the new -indev and load the image from there.
-outdev the new -dev and load the image from there.
Switch from eventual modifiying mode to growing mode.
(A subsequent -outdev will activate modification mode.)
-commit is performed automatically at end of program if there
@ -587,8 +604,8 @@ To suppress a final write, execute -rollback -end.
.br
Writing can last quite a while. It is not unnormal with several
types of media if there is no progress visible for the first
few minutes and if the drive gnaws on the media for a few
types of media that there is no progress visible for the first
few minutes or that the drive gnaws on the media for a few
minutes after all data have been transmitted.
xorriso and the drives are in a client-server relationship.
The drives have much freedom about what to do with the media.
@ -629,7 +646,7 @@ SORRY event occured.
\fB\-format\fR mode
Convert unformatted DVD-RW into overwriteable ones,
"de-ice" DVD+RW.
As mode submit the word "full" for now.
For now, mode should be the word "full".
.br
This action has no effect on media if -dummy is activated.
.br
@ -638,6 +655,9 @@ to the media's health. DVD+RW get formatted as far as needed
during writing, but an entirely formatted media might be better
readable in some DVD players.
.br
On the other hand unreliable DVD+RW can sometimes be repaired by
re-formatting.
.br
The progress reports issued by some drives while formatting are
quite unrealistic. Do not conclude success or failure from the
@ -646,13 +666,45 @@ SORRY event occured.
.TP
.B Settings for data insertion:
.TP
> \fB\-follow\fR "on"|"off"
Enable or disable resolution of symbolic links under disk_paths.
If disabled by "off" then symbolic links are added as link objects with
unchanged target address. If enabled by "on", then the link target gets added.
\fB\-follow\fR occasion[:occasion[...]]
Enable or disable resolution of symbolic links and mount points under
disk_paths. This applies to actions -add, -du*x, -ls*x and to -disk_pattern
expansion.
.br
There are two kinds of follow decisison to be made:
.br
"link" is the hop from a symbolic link to its target file object.
If enabled then symbolic links are handled as their target file objects,
else symbolic links are handled as themselves.
.br
"mount" is the hop from one filesystem to another subordinate filesystem.
If enabled then mount point directories are handled as any other directory,
else mount points are handled as empty directories if they are encountered in
directory tree traversals.
.br
Less general then above occasions:
.br
"pattern" is mount and link hopping, but only during -disk_pattern expansion.
.br
"param" is link hopping for parameter words (after eventual pattern expansion).
If enabled then -ls*x will show the link targets rather than the links
themselves. -du*x and -add will process the link targets but not follow links
in an eventual directory tree below the targets (unless "link" is enabled).
.br
Occasions can be combined in a colon separated list. All occasions
mentioned in the list will then lead to a positive follow decision.
.br
"off" prevents any positive follow decision. Use it if no other occasion
applies.
.br
Shortcuts:
.br
"default" is equivalent to "pattern:mount".
.br
"on" always decides positive. Equivalent to "link:mount".
.TP
\fB\-pathspecs\fR "on"|"off"
Control parameter interpretation with xorriso action -add.
Control parameter interpretation with xorriso actions -add and -path_list.
.br
"on" enables pathspecs of the form
.B target=source
@ -696,7 +748,7 @@ for their own decision.
.TP
\fB\-dummy\fR "on"|"off"
If "on" simulate burning or refuse with SORRY event if
no simulation is possible. If "on" do not blank or format.
no simulation is possible, do neither blank nor format.
.TP
\fB-fs\fR number["k"|"m"]
Set the size of the fifo buffer which smoothens the data
@ -754,11 +806,20 @@ Enable or disable to enter dialog mode after all arguments
are processed. In dialog mode input lines get prompted via
readline or from stdin.
.TP
\fB\-page\fR len width
Describe terminal to the text pager. See above, paragraph Result pager.
\fB\-page\fR length width
Describe terminal to the text pager. See also above, paragraph Result pager.
.br
If parameter length is nonzero then the user gets prompted after that
number of terminal lines. Zero length disables paging.
.br
Parameter width is the number of characters per terminal line. It is used
to compute the number of terminal lines which get occupied by an output line.
A usual terminal width is 80.
.TP
\fB\-use_readline\fR "on"|"off"
If "on" then use readline for dialog. Else use plain stdin.
.br
See also above, paragraph Dialog, Readline, Result pager.
.TP
\fB\-reassure\fR "on"|"tree"|"off"
If "on" then ask the user for "y" or "n"
@ -797,7 +858,7 @@ This is only possible when no ISO image changes are pending.
After this option was executed, there is no drive current
and no image loaded. Eventually one has to aquire a drive again.
.br
In order to be visible a device has to offer rw-permissions
In order to be visible, a device has to offer rw-permissions
with its libburn standard device file. Thus it might be only the
.B superuser
who is able to see all drives.

@ -2333,6 +2333,90 @@ next_in_dirseq:;
}
/* ------------------------------ LinkiteM -------------------------------- */
struct LinkiteM {
char *link_path;
dev_t target_dev;
ino_t target_ino;
int link_count;
struct LinkiteM *next;
};
int Linkitem_destroy(struct LinkiteM **o, int flag);
int Linkitem_new(struct LinkiteM **o, char *link_path, dev_t target_dev,
ino_t target_ino, struct LinkiteM *next, int flag)
{
struct LinkiteM *m;
m= *o= TSOB_FELD(struct LinkiteM,1);
if(m==NULL)
return(-1);
m->target_dev= target_dev;
m->target_ino= target_ino;
m->next= next;
m->link_count= 1;
if(next!=NULL)
m->link_count= m->next->link_count+1;
m->link_path= strdup(link_path);
if(m->link_path==NULL)
goto failed;
return(1);
failed:;
Linkitem_destroy(o, 0);
return(-1);
}
int Linkitem_destroy(struct LinkiteM **o, int flag)
{
if((*o)==NULL)
return(0);
if((*o)->link_path!=NULL)
free((*o)->link_path);
free((char *) (*o));
*o= NULL;
return(1);
}
int Linkitem_reset_stack(struct LinkiteM **o, struct LinkiteM *to, int flag)
{
struct LinkiteM *m, *m_next= NULL;
/* Prevent memory corruption */
for(m= *o; m!=to; m= m->next)
if(m==NULL) { /* this may actually not happen */
*o= to;
return(-1);
}
for(m= *o; m!=to; m= m_next) {
m_next= m->next;
Linkitem_destroy(&m, 0);
}
*o= to;
return(1);
}
int Linkitem_find(struct LinkiteM *stack, dev_t target_dev, ino_t target_ino,
struct LinkiteM **result, int flag)
{
struct LinkiteM *m;
for(m= stack; m!=NULL; m= m->next) {
if(target_dev == m->target_dev && target_ino == m->target_ino) {
*result= m;
return(1);
}
}
return(0);
}
/* ------------------------------- Xorriso -------------------------------- */
/** The list of startup file names */
@ -2370,7 +2454,11 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag)
strcpy(m->wdx, m->initial_wdx);
m->did_something_useful= 0;
m->do_joliet= 0;
m->do_follow_pattern= 1;
m->do_follow_param= 0;
m->do_follow_links= 0;
m->follow_link_limit= 100;
m->do_follow_mount= 1;
m->do_global_uid= 0;
m->global_uid= 0;
m->volid[0]= 0;
@ -3307,6 +3395,90 @@ int Xorriso_match_file(struct XorrisO *xorriso, char *to_match, char *adr,
}
/* @param flag bit0= simple readlink(): no normalization, no multi-hop
*/
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[SfileadrL], dirbuf[SfileadrL], *lpt, *spt, sfe[5*SfileadrL];
static int link_limit= 100;
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:;
sprintf(xorriso->info_text, "Cannot obtain link target of : %s",
Text_shellsafe(link_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY",0);
handle_abort:;
if(strcmp(lpt, link_path)!=0) {
sprintf(xorriso->info_text,
"Problem occured with intermediate path : %s",
Text_shellsafe(lpt, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0);
}
return(0);
}
buf[l]= 0;
if(l==0) {
sprintf(xorriso->info_text, "Empty link target with : %s",
Text_shellsafe(link_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY",0);
goto handle_abort;
}
if(flag&1) {
strcpy(result_path, buf);
return(1);
}
/* normalize relative to disk_path */
if(Sfile_str(dirbuf, lpt, 0)<=0)
return(-1);
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)
return(ret);
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:;
sprintf(xorriso->info_text, "Too many link hops with : %s",
Text_shellsafe(link_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, show_errno,"SORRY",0);
return(0);
}
}
return(1);
}
int Xorriso_status_result(struct XorrisO *xorriso, char *filter, FILE *fp,
int flag)
/*
@ -3343,7 +3515,7 @@ int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag)
*/
{
int is_default,no_defaults,i;
char *line, sfe[5*SfileadrL];
char *line, sfe[5*SfileadrL], mode[80];
static char channel_prefixes[4][4]= {".","R","I","M"};
no_defaults= flag&1;
@ -3457,8 +3629,20 @@ int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag)
if(!(is_default && no_defaults))
Xorriso_status_result(xorriso,filter,fp,flag&2);
is_default= !xorriso->do_follow_links;
sprintf(line,"-follow %s\n", xorriso->do_follow_links ? "on" : "off");
is_default= (xorriso->do_follow_pattern && (!xorriso->do_follow_param)
&& xorriso->do_follow_mount && !xorriso->do_follow_links);
mode[0]= 0;
if(xorriso->do_follow_pattern)
strcat(mode,":pattern");
if(xorriso->do_follow_param)
strcat(mode,":param");
if(xorriso->do_follow_links)
strcat(mode,":link");
if(xorriso->do_follow_mount)
strcat(mode,":mount");
if(mode[0]==0)
strcpy(mode, ":off");
sprintf(line,"-follow %s\n", mode+1);
if(!(is_default && no_defaults))
Xorriso_status_result(xorriso,filter,fp,flag&2);
@ -3740,10 +3924,14 @@ int Xorriso_obtain_pattern_files_x(
int *filec, char **filev, int count_limit, off_t *mem,
int *dive_count, int flag)
{
int ret, failed_at;
char adr[SfileadrL], name[SfileadrL];
int ret, failed_at, follow_mount, follow_links;
char adr[SfileadrL], name[SfileadrL], path_data[SfileadrL], *path;
struct DirseQ *dirseq;
struct stat stbuf;
dev_t dir_dev;
follow_mount= (xorriso->do_follow_mount || xorriso->do_follow_pattern);
follow_links= (xorriso->do_follow_links || xorriso->do_follow_pattern);
if(!(flag&2))
*dive_count= 0;
else
@ -3754,6 +3942,15 @@ int Xorriso_obtain_pattern_files_x(
if(ret!=2)
goto ex;
if(lstat(dir_adr, &stbuf)==-1)
{ret= 2; goto ex;}
dir_dev= stbuf.st_dev;
if(S_ISLNK(stbuf.st_mode)) {
if(stat(dir_adr, &stbuf)==-1)
{ret= 2; goto ex;}
if(dir_dev != stbuf.st_dev && !follow_mount)
{ret= 2; goto ex;}
}
ret= Dirseq_new(&dirseq, dir_adr, 1);
if(ret<0) {
sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
@ -3781,12 +3978,27 @@ int Xorriso_obtain_pattern_files_x(
if(ret>0) { /* no match */
if(failed_at <= *dive_count) /* no hope for a match */
continue;
path= adr;
if(adr[0]!='/') {
path= path_data;
ret= Xorriso_make_pattern_adr(xorriso, xorriso->wdx, adr, path, 1|4);
if(ret<=0)
goto ex;
}
ret= Sfile_type(adr, 1|((xorriso->do_follow_links || !(flag&2))<<2));
if(ret!=2)
if(follow_links)
ret= stat(path,&stbuf);
else
ret= lstat(path,&stbuf);
if(ret==-1)
continue;
if(!S_ISDIR(stbuf.st_mode))
continue;
if(dir_dev != stbuf.st_dev && !follow_mount)
continue;
/* dive deeper */
ret= Xorriso_obtain_pattern_files_x(xorriso, adr, adr,
ret= Xorriso_obtain_pattern_files_x(xorriso, adr, path,
filec, filev, count_limit, mem, dive_count, flag|2);
if(ret<=0)
goto ex;
@ -3807,6 +4019,7 @@ ex:;
return(ret);
}
int Xorriso_eval_nonmatch(struct XorrisO *xorriso, char *pattern,
int *nonconst_mismatches, off_t *mem, int flag)
{
@ -4270,7 +4483,7 @@ int Xorriso_msgs_submit(struct XorrisO *xorriso,
1= no problem, go on
0= function failed but xorriso would not abort, go on
<0= do abort
-1 = due to probelm_status
-1 = due to problem_status
-2 = due to xorriso->request_to_abort
*/
int Xorriso_eval_problem_status(struct XorrisO *xorriso, int ret, int flag)
@ -4393,23 +4606,83 @@ int Xorriso_check_temp_mem_limit(struct XorrisO *xorriso, off_t mem, int flag)
}
/* @param flag bit0= for Xorriso_msgs_submit: use pager
*/
int Xorriso_hop_link(struct XorrisO *xorriso, char *link_path,
struct LinkiteM **link_stack, struct stat *stbuf, int flag)
{
int ret;
struct LinkiteM *litm;
char sfe[5*SfileadrL];
if(*link_stack != NULL) {
if((*link_stack)->link_count>=xorriso->follow_link_limit) {
sprintf(xorriso->info_text,
"Too many symbolic links in single tree branch at : %s",
Text_shellsafe(link_path, sfe, 0));
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 : %s",
Text_shellsafe(link_path, sfe, 0));
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, int flag)
off_t boss_mem,
struct LinkiteM *link_stack,
int flag)
{
int i, ret, no_sort= 0, filec= 0, l, j, fc;
int i, ret, no_sort= 0, filec= 0, l, j, fc, no_dive, is_link;
char path[SfileadrL], show_path[SfileadrL], name[SfileadrL], sfe[5*SfileadrL];
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;
namept= name;
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");
@ -4420,6 +4693,7 @@ int Xorriso_show_dux_subs(struct XorrisO *xorriso,
{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;
@ -4437,26 +4711,45 @@ 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;
if(S_ISDIR(stbuf.st_mode)) {
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 *));
ret= Xorriso_show_dux_subs(xorriso, path,show_path,&sub_size,boss_mem,0);
if(flag&1) /* diving and counting is done further down */
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;
Xorriso_process_msg_queues(xorriso,0);
}
if(filec<=0 || !(flag&1))
@ -4488,19 +4781,33 @@ no_sort_possible:;
strcpy(path, abs_path);
if(Sfile_add_to_path(path, name, 0)<=0)
goto much_too_long;
ret= lstat(path, &stbuf);
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;
filev[fc]= strdup(name);
if(filev[fc]==NULL) {
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;
@ -4510,20 +4817,16 @@ no_sort_possible:;
}
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;
ret= lstat(path, &stbuf);
if(ret==-1)
continue;
if(!S_ISDIR(stbuf.st_mode))
continue;
} else
namept= filev[i];
sub_size= 0;
strcpy(show_path, rel_path);
if(Sfile_add_to_path(show_path, namept, 0)<=0)
@ -4531,11 +4834,34 @@ no_sort_possible:;
strcpy(path, abs_path);
if(Sfile_add_to_path(path, namept, 0)<=0)
goto much_too_long;
no_dive= 0;
ret= Xorriso_show_dux_subs(xorriso,
path, show_path, &sub_size, boss_mem+mem, flag&1);
if(ret<0)
goto ex;
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++;
@ -4547,6 +4873,7 @@ no_sort_possible:;
ret= 1;
ex:;
Linkitem_reset_stack(&own_link_stack, link_stack, 0);
Dirseq_destroy(&dirseq, 0);
if(filev!=NULL) {
for(i=0; i<filec; i++)
@ -4652,7 +4979,8 @@ int Xorriso_lsx_filev(struct XorrisO *xorriso, int filec, char **filev,
off_t boss_mem, int flag)
{
int i, ret, was_error= 0;
char sfe[5*SfileadrL], path[SfileadrL], *rpt;
char sfe[5*SfileadrL], sfe2[5*SfileadrL], path[SfileadrL];
char *rpt, link_target[SfileadrL];
off_t size;
struct stat stbuf;
@ -4667,14 +4995,11 @@ int Xorriso_lsx_filev(struct XorrisO *xorriso, int filec, char **filev,
was_error++;
continue;
}
if(xorriso->do_follow_links)
ret= stat(path, &stbuf);
else
ret= lstat(path, &stbuf);
ret= lstat(path, &stbuf);
if(ret==-1) {
sprintf(xorriso->info_text, "Not found in local filesystem: %s",
Text_shellsafe(path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 1);
was_error++;
continue;
}
@ -4691,22 +5016,33 @@ int Xorriso_lsx_filev(struct XorrisO *xorriso, int filec, char **filev,
ret= Xorriso_make_pattern_adr(xorriso, xorriso->wdx, filev[i], path, 1|4);
if(ret<=0)
continue;
if(xorriso->do_follow_links)
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);
else
ret= lstat(path, &stbuf);
if(ret==-1)
ret= lstat(path, &stbuf);
}
if(ret==-1)
continue;
link_target[0]= 0;
rpt[0]= 0;
if((flag&5)==1) {
ret= Xorriso_format_ls_l(xorriso, &stbuf, 0);
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 -du_s */
size= stbuf.st_size;
if(S_ISDIR(stbuf.st_mode)) {
ret= Xorriso_show_dux_subs(xorriso,
path, filev[i], &size, boss_mem, flag&1);
ret= Xorriso_show_dux_subs(xorriso, path, filev[i], &size, boss_mem,
NULL, flag&1);
if(ret<0)
return(-1);
if(ret==0)
@ -4714,8 +5050,13 @@ int Xorriso_lsx_filev(struct XorrisO *xorriso, int filec, char **filev,
}
sprintf(rpt, "%7.f ",(double) (size/1024));
}
sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n",
Text_shellsafe(filev[i], sfe, 0));
if(link_target[0])
sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s -> %s\n",
Text_shellsafe(filev[i], sfe, 0),
Text_shellsafe(link_target, sfe2, 0));
else
sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n",
Text_shellsafe(filev[i], sfe, 0));
Xorriso_result(xorriso, 0);
}
return(!was_error);
@ -4798,11 +5139,11 @@ int Xorriso_option_add(struct XorrisO *xorriso, int argc, char **argv,
goto problem_handler;
}
ret= Xorriso_normalize_img_path(xorriso, target, eff_path, 2);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, target, eff_path, 2);
if(ret<=0)
goto problem_handler;
strcpy(target, eff_path);
ret= Xorriso_normalize_img_path(xorriso, source, eff_path, 2|4);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, source,eff_path,2|4);
if(ret<=0)
goto problem_handler;
strcpy(source, eff_path);
@ -4998,14 +5339,14 @@ int Xorriso_option_cdi(struct XorrisO *xorriso, char *iso_rr_path, int flag)
return(-1);
}
ret= Xorriso_normalize_img_path(xorriso, path, eff_path, 1);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 1);
if(ret<0)
return(ret);
if(ret==0) {
sprintf(xorriso->info_text, "-cdi: not existing yet in ISO image : %s",
Text_shellsafe(path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
ret= Xorriso_normalize_img_path(xorriso, path, eff_path, 2);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 2);
if(ret<=0)
return(ret);
} else if(ret!=2) {
@ -5051,7 +5392,7 @@ int Xorriso_option_cdx(struct XorrisO *xorriso, char *disk_path, int flag)
return(-1);
}
ret= Xorriso_normalize_img_path(xorriso, path, eff_path, 2|4);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, path, eff_path, 2|4);
if(ret<=0)
return(ret);
if(eff_path[0]) {
@ -5523,14 +5864,62 @@ int Xorriso_option_iso_rr_pattern(struct XorrisO *xorriso, char *mode,int flag)
/* Option -follow */
int Xorriso_option_follow(struct XorrisO *xorriso, char *mode, int flag)
{
if(strcmp(mode, "off")==0)
xorriso->do_follow_links= 0;
else if(strcmp(mode, "on")==0)
xorriso->do_follow_links= 1;
else {
sprintf(xorriso->info_text, "-follow: unknown mode '%s'", mode);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
return(0);
int was_fl, was_fm, was_fpr, was_fpt, l;
char *cpt, *npt;
was_fpt= xorriso->do_follow_pattern;
was_fpr= xorriso->do_follow_param;
was_fl= xorriso->do_follow_links;
was_fm= xorriso->do_follow_mount;
xorriso->do_follow_pattern= 0;
xorriso->do_follow_param= 0;
xorriso->do_follow_links= 0;
xorriso->do_follow_mount= 0;
npt= cpt= mode;
for(cpt= mode; npt!=NULL; cpt= npt+1) {
npt= strchr(cpt,':');
if(npt==NULL)
l= strlen(cpt);
else
l= npt-cpt;
if(l==0)
goto unknown_mode;
if(strncmp(cpt, "off", l)==0) {
xorriso->do_follow_pattern= 0;
xorriso->do_follow_param= 0;
xorriso->do_follow_links= 0;
xorriso->do_follow_mount= 0;
} else if(strncmp(cpt, "on", l)==0) {
xorriso->do_follow_pattern= 1;
xorriso->do_follow_param= 1;
xorriso->do_follow_links= 1;
xorriso->do_follow_mount= 1;
} else if(strncmp(cpt, "default", l)==0) {
xorriso->do_follow_pattern= 1;
xorriso->do_follow_param= 0;
xorriso->do_follow_links= 0;
xorriso->do_follow_mount= 1;
} else if(strncmp(cpt, "link", l)==0 || strncmp(cpt,"links", l)==0) {
xorriso->do_follow_links= 1;
} else if(strncmp(cpt, "mount", l)==0) {
xorriso->do_follow_mount= 1;
} else if(strncmp(cpt,"param", l)==0) {
xorriso->do_follow_param= 1;
} else if(strncmp(cpt, "pattern", l)==0) {
xorriso->do_follow_pattern= 1;
} else {
unknown_mode:;
if(l<SfileadrL)
sprintf(xorriso->info_text, "-follow: unknown mode '%s'", cpt);
else
sprintf(xorriso->info_text, "-follow: oversized mode parameter (%d)",l);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
xorriso->do_follow_pattern= was_fpt;
xorriso->do_follow_param= was_fpr;
xorriso->do_follow_links= was_fl;
xorriso->do_follow_mount= was_fm;
return(0);
}
}
return(1);
}
@ -5695,7 +6084,8 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag)
" Delete empty directories.",
" -- Mark end of particular action argument list.",
"",
"> -follow \"on\"|\"off\" Follow symbolic links within disk_path.",
" -follow \"on\"|\"pattern:param:link:mount\"|\"default\"|\"off\"",
" Follow symbolic links and mount points within disk_path.",
"",
" -overwrite \"on\"|\"nondir\"|\"off\"",
" Allow or disallow to overwrite existing files in ISO image.",
@ -6134,18 +6524,8 @@ int Xorriso_option_mvi(struct XorrisO *xorriso, int argc, char **argv,
if(ret<=0)
goto ex;
#ifdef NIX
/* <<< */
/* Check existence of old addresses */
for(i= 0; i<optc; i++) {
ret= Xorriso_normalize_img_path(xorriso, optv[i], eff_origin, 0);
if(ret<=0)
{ret= 0; goto ex;}
}
#endif /* NIX */
/* Evaluate target address */
ret= Xorriso_normalize_img_path(xorriso, destv[0], eff_dest, 1);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, destv[0], eff_dest, 1);
if(ret<0)
{ret= 0; goto ex;}
if(ret==2) {
@ -6159,13 +6539,13 @@ int Xorriso_option_mvi(struct XorrisO *xorriso, int argc, char **argv,
{ret= 0; goto ex;}
}
if(ret==0) { /* compute complete eff_dest */
ret= Xorriso_normalize_img_path(xorriso, destv[0], eff_dest, 2);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, destv[0],eff_dest,2);
if(ret<0)
{ret= 0; goto ex;}
}
/* Perform movements */
for(i= 0; i<optc; i++) {
ret= Xorriso_normalize_img_path(xorriso, optv[i], eff_origin, 0);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi,optv[i],eff_origin,0);
if(ret<=0 || xorriso->request_to_abort)
goto problem_handler;
if(is_dir) {
@ -6580,7 +6960,7 @@ int Xorriso_option_rmi(struct XorrisO *xorriso, int argc, char **argv,
if(ret<=0)
goto problem_handler;
}
ret= Xorriso_normalize_img_path(xorriso, path, eff_path, 2);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 2);
if(ret<=0)
goto problem_handler;
strcpy(path, eff_path);
@ -6805,7 +7185,7 @@ int Xorriso_option_use_readline(struct XorrisO *xorriso, char *mode, int flag)
}
/* Option -uid */
/* Option -V */
int Xorriso_option_v_capital(struct XorrisO *xorriso, char *volid, int flag)
{
fprintf(stderr, ">>> LIBISOFS : -V %s\n", volid);
@ -6816,14 +7196,15 @@ int Xorriso_option_v_capital(struct XorrisO *xorriso, char *volid, int flag)
/* Option -version */
int Xorriso_option_version(struct XorrisO *xorriso, int flag)
{
/* >>> print rather to result channel */;
printf("xorriso %s : RockRidge filesystem manipulator\n", PROG_VERSION);
printf("Copyright (C) 2007, Thomas Schmitt <scdbackup@gmx.net>, libburnia project\n");
printf("Version timestamp : %s\n",Xorriso_timestamP);
printf("Build timestamp : %s\n",Xorriso_build_timestamP);
sprintf(xorriso->result_line,
"xorriso %s : RockRidge filesystem manipulator\n", PROG_VERSION);
sprintf(xorriso->result_line+strlen(xorriso->result_line),
"Copyright (C) 2007, Thomas Schmitt <scdbackup@gmx.net>, libburnia project\n");
sprintf(xorriso->result_line+strlen(xorriso->result_line),
"Version timestamp : %s\n",Xorriso_timestamP);
sprintf(xorriso->result_line+strlen(xorriso->result_line),
"Build timestamp : %s\n",Xorriso_build_timestamP);
Xorriso_result(xorriso, 0);
return(1);
}

@ -32,7 +32,7 @@
/* <<< ??? */
typedef int (*Cleanup_app_handler_T)();
struct LinkiteM;
/* maximum number of history lines to be reported with -status:long_history */
#define Xorriso_status_history_maX 100
@ -67,7 +67,11 @@ struct XorrisO { /* the global context of xorriso */
/* >>> put libisofs aspects here <<< */
int do_joliet;
int do_follow_pattern;
int do_follow_param;
int do_follow_links;
int follow_link_limit;
int do_follow_mount;
int do_global_uid;
uid_t global_uid;
int do_global_gid;
@ -242,6 +246,17 @@ int Xorriso_register_matched_adr(struct XorrisO *xorriso,
int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag);
/* @param flag bit0= simple readlink(): no normalization, no multi-hop
*/
int Xorriso_resolve_link(struct XorrisO *xorriso,
char *link_path, char result_path[SfileadrL], int flag);
/* @param flag bit0= for Xorriso_msgs_submit: use pager
*/
int Xorriso_hop_link(struct XorrisO *xorriso, char *link_path,
struct LinkiteM **link_stack, struct stat *stbuf, int flag);
int Sfile_str(char target[SfileadrL], char *source, int flag);
@ -267,5 +282,8 @@ int Dirseq_next_adr(struct DirseQ *o, char reply[SfileadrL], int flag);
int Linkitem_reset_stack(struct LinkiteM **o, struct LinkiteM *to, int flag);
#endif /* Xorriso_private_includeD */

@ -1 +1 @@
#define Xorriso_timestamP "2007.12.15.162039"
#define Xorriso_timestamP "2007.12.15.183022"

@ -592,8 +592,8 @@ int Xorriso_get_volume(struct XorrisO *xorriso, struct iso_volume **volume,
@return -1 = faulty path format, 0 = not found ,
1 = found simple node , 2 = found directory
*/
int Xorriso_normalize_img_path(struct XorrisO *xorriso, char *img_path,
char eff_path[], int flag)
int Xorriso_normalize_img_path(struct XorrisO *xorriso, char *wd,
char *img_path, char eff_path[], int flag)
{
int ret, is_dir= 0, done= 0;
struct iso_volume *volume;
@ -613,10 +613,7 @@ int Xorriso_normalize_img_path(struct XorrisO *xorriso, char *img_path,
apt= npt= path;
if(img_path[0]!='/') {
if(flag&4)
strcpy(path, xorriso->wdx);
else
strcpy(path, xorriso->wdi);
strcpy(path, wd);
ret= Sfile_add_to_path(path, img_path, 0);
if(ret<=0)
goto much_too_long;
@ -705,7 +702,7 @@ int Xorriso_get_node_by_path(struct XorrisO *xorriso,
char sfe[5*SfileadrL], path[SfileadrL];
struct iso_volume *volume;
ret= Xorriso_normalize_img_path(xorriso, in_path, path, 0);
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, in_path, path, 0);
if(ret<=0)
return(ret);
if(eff_path!=NULL)
@ -726,21 +723,39 @@ int Xorriso_get_node_by_path(struct XorrisO *xorriso,
/* @param flag bit0= recursion is active */
int Xorriso_add_tree(struct XorrisO *xorriso, struct iso_tree_node_dir *dir,
char *img_dir_path, char *disk_dir_path, int flag)
char *img_dir_path, char *disk_dir_path,
struct LinkiteM *link_stack, int flag)
{
struct iso_volume *volume;
struct iso_tree_node *node;
int ret, target_is_dir, source_is_dir, fret, was_failure= 0;
int ret, target_is_dir, source_is_dir, source_is_link, fret, was_failure= 0;
int do_not_dive;
struct DirseQ *dirseq= NULL;
char sfe[5*SfileadrL], sfe2[5*SfileadrL];
char disk_path[2*SfileadrL], img_path[2*SfileadrL];
char *name, *img_name;
struct stat stbuf;
char disk_path[2*SfileadrL], img_path[2*SfileadrL], link_target[SfileadrL];
char *name, *img_name, *srcpt;
struct stat stbuf, hstbuf;
dev_t dir_dev;
struct LinkiteM *own_link_stack;
own_link_stack= link_stack;
ret= Xorriso_get_volume(xorriso, &volume, 0);
if(ret<=0)
return(ret);
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))))
return(2);
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))))
return(2);
}
ret= Dirseq_new(&dirseq, disk_dir_path, 1);
if(ret<0) {
sprintf(xorriso->info_text,"Failed to create source filesystem iterator");
@ -748,6 +763,7 @@ int Xorriso_add_tree(struct XorrisO *xorriso, struct iso_tree_node_dir *dir,
{ret= -1; goto ex;}
}
if(ret==0) {
cannot_open_dir:;
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, "SORRY", 0);
@ -766,6 +782,8 @@ int Xorriso_add_tree(struct XorrisO *xorriso, struct iso_tree_node_dir *dir,
img_name= img_path+strlen(img_path);
while(1) { /* loop over directory content */
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);
if(ret==0)
@ -778,21 +796,48 @@ int Xorriso_add_tree(struct XorrisO *xorriso, struct iso_tree_node_dir *dir,
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(disk_path), 0)<=0)
if(Xorriso_much_too_long(xorriso, strlen(srcpt), 0)<=0)
{ret= 0; goto was_problem;}
if(lstat(disk_path, &stbuf)==-1) {
if(lstat(srcpt, &stbuf)==-1) {
cannot_lstat:;
sprintf(xorriso->info_text,
"Cannot determine attributes of source file %s",
Text_shellsafe(disk_path, sfe, 0));
Text_shellsafe(srcpt, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 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;