~ubuntu-branches/ubuntu/precise/libisoburn/precise

« back to all changes in this revision

Viewing changes to xorriso/disk_ops.c

  • Committer: Bazaar Package Importer
  • Author(s): George Danchev
  • Date: 2011-05-26 16:21:32 UTC
  • mfrom: (9.1.12 sid)
  • Revision ID: james.westby@ubuntu.com-20110526162132-9lzoagfaggnera53
Tags: 1.0.8.pl00-4
* [MA] Improve package descriptions and README.Debian.
* [MA] Migrate to format "3.0 (quilt)" and compatibility 8.
  + debian/control: Drop build-dep on 'cdbs'. Require debhelper (>= 8).
  + debian/rules: Reformulate using 'dh'.
  + debian/libisoburn{1,-dev,-doc}.docs: New files.
  + debian/xorriso.docs: Addition of upstream documents.
* [GD] Make sure doxygen documentaton (doc package) is not built
       when dpkg-buildpackage -B is called (i.e. autobuilders).
* [GD] Move doxygen, graphviz to Build-Depends-Indep.
* [GD] Add missing copyrights for debian packaging.
* [GD] Standards-Version: 3.9.2 (no changes needed).
* [GD] More package description and README.Debian improvements;
       thanks to Tony Mancill <tmancill@debian.org>.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
 
3
 
 
4
   Copyright 2007-2010 Thomas Schmitt, <scdbackup@gmx.net>
 
5
 
 
6
   Provided under GPL version 2 or later.
 
7
 
 
8
   This file contains the implementation of actions on onjects of disk
 
9
   filesystems.
 
10
*/
 
11
 
 
12
#ifdef HAVE_CONFIG_H
 
13
#include "../config.h"
 
14
#endif
 
15
 
 
16
#include <ctype.h>
 
17
#include <sys/types.h>
 
18
#include <unistd.h>
 
19
#include <stdlib.h>
 
20
#include <stdio.h>
 
21
#include <string.h>
 
22
#include <sys/stat.h>
 
23
#include <sys/time.h>
 
24
#include <time.h>
 
25
#include <fcntl.h>
 
26
#include <errno.h>
 
27
#include <pwd.h>
 
28
#include <grp.h>
 
29
 
 
30
 
 
31
#include "xorriso.h"
 
32
#include "xorriso_private.h"
 
33
#include "xorrisoburn.h"
 
34
 
 
35
 
 
36
 
 
37
/* @param flag bit0= simple readlink(): no normalization, no multi-hop
 
38
*/
 
39
int Xorriso_resolve_link(struct XorrisO *xorriso,
 
40
                     char *link_path, char result_path[SfileadrL], int flag)
 
41
{
 
42
 ssize_t l;
 
43
 struct stat stbuf;
 
44
 int link_count= 0, ret, show_errno= 0;
 
45
 char buf[SfileadrL], dirbuf[SfileadrL], *lpt, *spt, sfe[5*SfileadrL];
 
46
 static int link_limit= 100;
 
47
 
 
48
 if(!(flag&1))
 
49
   if(stat(link_path, &stbuf)==-1)
 
50
     if(errno==ELOOP) {
 
51
       show_errno= errno;
 
52
       goto too_many_hops;
 
53
     }
 
54
 lpt= link_path;
 
55
 while(1) {
 
56
   l= readlink(lpt, buf, SfileadrL-1);
 
57
   if(l==-1) {
 
58
handle_error:;
 
59
     Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
 
60
     sprintf(xorriso->info_text, "Cannot obtain link target of : %s",
 
61
             Text_shellsafe(link_path, sfe, 0));
 
62
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
 
63
handle_abort:;
 
64
     if(strcmp(lpt, link_path)!=0) {
 
65
       sprintf(xorriso->info_text,
 
66
               "Problem occured with intermediate path : %s",
 
67
               Text_shellsafe(lpt, sfe, 0));
 
68
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0);
 
69
     }
 
70
     return(0);
 
71
   }
 
72
   buf[l]= 0;
 
73
   if(l==0) {
 
74
     Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
 
75
     sprintf(xorriso->info_text, "Empty link target with : %s",
 
76
             Text_shellsafe(link_path, sfe, 0));
 
77
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
 
78
     goto handle_abort;
 
79
   }
 
80
 
 
81
   if(flag&1) {
 
82
     strcpy(result_path, buf);
 
83
     return(1);
 
84
   }
 
85
 
 
86
   /* normalize relative to disk_path */
 
87
   if(Sfile_str(dirbuf, lpt, 0)<=0)
 
88
     return(-1);
 
89
   while(1) {
 
90
     spt= strrchr(dirbuf,'/');
 
91
     if(spt!=NULL) {
 
92
       *spt= 0;
 
93
       if(*(spt+1)!=0)
 
94
   break;
 
95
     } else
 
96
   break;
 
97
   }
 
98
   ret= Xorriso_normalize_img_path(xorriso, dirbuf, buf, result_path, 2|4);
 
99
   if(ret<=0)
 
100
     return(ret);
 
101
 
 
102
   if(lstat(result_path, &stbuf)==-1) {
 
103
     lpt= result_path;
 
104
     goto handle_error;
 
105
   }
 
106
   if(!S_ISLNK(stbuf.st_mode))
 
107
 break;
 
108
   
 
109
   lpt= result_path;
 
110
   link_count++;
 
111
   if(link_count>link_limit) {
 
112
too_many_hops:;
 
113
     Xorriso_msgs_submit(xorriso, 0, link_path, 0, "ERRFILE", 0);
 
114
     sprintf(xorriso->info_text, "Too many link hops with : %s",
 
115
             Text_shellsafe(link_path, sfe, 0));
 
116
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, show_errno,
 
117
                         "FAILURE",0);
 
118
     return(0);
 
119
   }
 
120
 }
 
121
 return(1);
 
122
}
 
123
 
 
124
 
 
125
int Xorriso_convert_uidstring(struct XorrisO *xorriso, char *uid_string,
 
126
                              uid_t *uid, int flag)
 
127
{
 
128
 double num;
 
129
 char text[80];
 
130
 struct passwd *pwd;
 
131
 
 
132
 sscanf(uid_string, "%lf", &num);
 
133
 sprintf(text,"%.f",num);
 
134
 if(strcmp(text,uid_string)==0) {
 
135
   *uid= num;
 
136
   return(1);
 
137
 }
 
138
 pwd= getpwnam(uid_string);
 
139
 if(pwd==NULL) {
 
140
   sprintf(xorriso->info_text, "-uid: Not a known user: '%s'", uid_string);
 
141
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 
142
   return(0);
 
143
 }
 
144
 *uid= pwd->pw_uid;
 
145
 return(1);
 
146
}
 
147
 
 
148
 
 
149
int Xorriso_convert_gidstring(struct XorrisO *xorriso, char *gid_string,
 
150
                              gid_t *gid, int flag)
 
151
{
 
152
 double num;
 
153
 char text[80];
 
154
 struct group *grp;
 
155
 
 
156
 sscanf(gid_string, "%lf", &num);
 
157
 sprintf(text,"%.f",num);
 
158
 if(strcmp(text,gid_string)==0) {
 
159
   *gid= num;
 
160
   return(1);
 
161
 }
 
162
 grp= getgrnam(gid_string);
 
163
 if(grp==NULL) {
 
164
   sprintf(xorriso->info_text, "-gid: Not a known group: '%s'", gid_string);
 
165
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 
166
   return(0);
 
167
 }
 
168
 *gid= grp->gr_gid;
 
169
 return(1);
 
170
}
 
171
 
 
172
 
 
173
int Xorriso_convert_modstring(struct XorrisO *xorriso, char *cmd, char *mode,
 
174
                              mode_t *mode_and, mode_t *mode_or, int flag)
 
175
{
 
176
 int who_val= 0;
 
177
 char sfe[5*SfileadrL], *mpt, *vpt, *opt;
 
178
 unsigned int num= 0;
 
179
 mode_t mode_val,mask;
 
180
 
 
181
 *mode_and= ~0;
 
182
 *mode_or= 0;
 
183
 if(mode[0]=='0') {
 
184
   *mode_and= 0;
 
185
   sscanf(mode,"%o",&num);
 
186
   *mode_or= num;
 
187
 } else if(strchr(mode,'+')!=NULL || strchr(mode,'-')!=NULL
 
188
           || strchr(mode,'=')!=NULL) {
 
189
   /* [ugoa][+-][rwxst] */;
 
190
   for(mpt= mode; mpt!=NULL; mpt= strchr(mpt, ',')) {
 
191
     if(*mpt==',')
 
192
       mpt++;
 
193
     if(strlen(mpt)<2)
 
194
       goto unrecognizable;
 
195
     who_val= 0;
 
196
     for(vpt= mpt; *vpt!='+' && *vpt!='-' && *vpt!='='; vpt++) {
 
197
       if(*vpt=='u')
 
198
         who_val|= 4;
 
199
       else if(*vpt=='g')
 
200
         who_val|= 2;
 
201
       else if(*vpt=='o')
 
202
         who_val|= 1;
 
203
       else if(*vpt=='a')
 
204
         who_val|= 7;
 
205
       else
 
206
         goto unrecognizable;
 
207
     }
 
208
     opt= vpt;
 
209
     mode_val= 0;
 
210
     for(vpt= opt+1; *vpt!=0 && *vpt!=','; vpt++) {
 
211
       if(*vpt=='r') {
 
212
         if(who_val&4)
 
213
           mode_val|= S_IRUSR;
 
214
         if(who_val&2)
 
215
           mode_val|= S_IRGRP;
 
216
         if(who_val&1)
 
217
           mode_val|= S_IROTH;
 
218
       } else if(*vpt=='w') {
 
219
         if(who_val&4)
 
220
           mode_val|= S_IWUSR;
 
221
         if(who_val&2)
 
222
           mode_val|= S_IWGRP;
 
223
         if(who_val&1)
 
224
           mode_val|= S_IWOTH;
 
225
       } else if(*vpt=='x') {
 
226
         if(who_val&4)
 
227
           mode_val|= S_IXUSR;
 
228
         if(who_val&2)
 
229
           mode_val|= S_IXGRP;
 
230
         if(who_val&1)
 
231
           mode_val|= S_IXOTH;
 
232
       } else if(*vpt=='s') {
 
233
         if(who_val&4)
 
234
           mode_val|= S_ISUID;
 
235
         if(who_val&2)
 
236
           mode_val|= S_ISGID;
 
237
       } else if(*vpt=='t') {
 
238
         if(who_val&1)
 
239
           mode_val|= S_ISVTX;
 
240
       } else
 
241
         goto unrecognizable;
 
242
     }
 
243
     if(*opt=='+') {
 
244
       (*mode_or)|= mode_val;
 
245
     } else if(*opt=='=') {
 
246
       mask= 0;
 
247
       if(who_val&1)
 
248
         mask|= S_IRWXO|S_ISVTX;
 
249
       if(who_val&2)
 
250
         mask|= S_IRWXG|S_ISGID;
 
251
       if(who_val&4)
 
252
         mask|= S_IRWXU|S_ISUID;
 
253
       (*mode_and)&= ~(mask);
 
254
       (*mode_or)= ((*mode_or) & ~mask) | mode_val;
 
255
     } else if(*opt=='-') {
 
256
       (*mode_or)&= ~mode_val;
 
257
       (*mode_and)&= ~mode_val;
 
258
     }
 
259
   }
 
260
 } else {
 
261
unrecognizable:;
 
262
   sprintf(xorriso->info_text,
 
263
           "%s: Unrecognizable or faulty permission mode %s\n", cmd,
 
264
           Text_shellsafe(mode, sfe, 0));
 
265
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
 
266
   return(0);
 
267
 }
 
268
 return(1);
 
269
}
 
270
 
 
271
 
 
272
/* @param flag bit0= for Xorriso_msgs_submit: use pager
 
273
               bit1= do not issue warnings
 
274
*/
 
275
int Xorriso_hop_link(struct XorrisO *xorriso, char *link_path,
 
276
                    struct LinkiteM **link_stack, struct stat *stbuf, int flag)
 
277
{
 
278
 int ret;
 
279
 struct LinkiteM *litm;
 
280
 char sfe[5*SfileadrL];
 
281
 
 
282
 if(*link_stack != NULL) {
 
283
   if(Linkitem_get_link_count(*link_stack, 0) >= xorriso->follow_link_limit) {
 
284
     sprintf(xorriso->info_text,
 
285
             "Too many symbolic links in single tree branch at : %s",
 
286
             Text_shellsafe(link_path, sfe, 0));
 
287
     if(!(flag&2))
 
288
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,"WARNING",flag&1);
 
289
     return(0);
 
290
   }
 
291
 }
 
292
 ret= stat(link_path, stbuf);
 
293
 if(ret==-1)
 
294
   return(0);
 
295
 ret= Linkitem_find(*link_stack, stbuf->st_dev, stbuf->st_ino, &litm, 0);
 
296
 if(ret>0) {
 
297
   sprintf(xorriso->info_text,
 
298
           "Detected symbolic link loop around : %s",
 
299
           Text_shellsafe(link_path, sfe, 0));
 
300
   if(!(flag&2))
 
301
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", flag&1);
 
302
   return(0);
 
303
 }
 
304
 ret= Linkitem_new(&litm, link_path, stbuf->st_dev, stbuf->st_ino,
 
305
                   *link_stack, 0);
 
306
 if(ret<=0) {
 
307
   sprintf(xorriso->info_text,
 
308
           "Cannot add new item to link loop prevention stack");
 
309
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", flag&1);
 
310
   return(-1);
 
311
 }
 
312
 *link_stack= litm;
 
313
 return(1);
 
314
}
 
315
 
 
316
 
 
317
/* @param flag bit0= do not only sum up sizes but also print subdirs
 
318
               bit1= this is a recursion
 
319
   @return <=0 error , 1 ok , 2 could not open directory
 
320
*/
 
321
int Xorriso_show_dux_subs(struct XorrisO *xorriso,
 
322
                      char *abs_path, char *rel_path, off_t *size,
 
323
                      off_t boss_mem,
 
324
                      struct LinkiteM *link_stack,
 
325
                      int flag)
 
326
{
 
327
 int i, ret, no_sort= 0, filec= 0, l, j, fc, no_dive, is_link;
 
328
 char **filev= NULL, *namept;
 
329
 off_t sub_size, report_size, mem= 0;
 
330
 struct DirseQ *dirseq= NULL;
 
331
 struct stat stbuf;
 
332
 dev_t dir_dev;
 
333
 struct LinkiteM *own_link_stack;
 
334
 char *path= NULL, *show_path= NULL, *name= NULL, *sfe= NULL;
 
335
 
 
336
 sfe= malloc(5*SfileadrL);
 
337
 path= malloc(SfileadrL);
 
338
 show_path= malloc(SfileadrL);
 
339
 name= malloc(SfileadrL);
 
340
 if(path==NULL || show_path==NULL || name==NULL || sfe==NULL) {
 
341
   Xorriso_no_malloc_memory(xorriso, &sfe, 0);
 
342
   {ret= -1; goto ex;}
 
343
 }
 
344
 own_link_stack= link_stack;
 
345
 namept= name;
 
346
 *size= 0;
 
347
 
 
348
 if(lstat(abs_path, &stbuf)==-1)
 
349
   {ret= 2; goto ex;}
 
350
 dir_dev= stbuf.st_dev;
 
351
 if(S_ISLNK(stbuf.st_mode)) {
 
352
   if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&2))))
 
353
     {ret= 2; goto ex;}
 
354
   if(stat(abs_path, &stbuf)==-1)
 
355
     {ret= 2; goto ex;}
 
356
   if(dir_dev != stbuf.st_dev &&
 
357
      !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&2))))
 
358
     {ret= 2; goto ex;}
 
359
 }
 
360
 ret= Dirseq_new(&dirseq, abs_path, 1);
 
361
 if(ret<0) {
 
362
   sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
 
363
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 
364
   {ret= -1; goto ex;}
 
365
 }
 
366
 if(ret==0)
 
367
   {ret= 2; goto ex;}
 
368
 
 
369
 while(1) {
 
370
   Linkitem_reset_stack(&own_link_stack, link_stack, 0);
 
371
   ret= Dirseq_next_adr(dirseq,name,0);
 
372
   if(ret<0)
 
373
     goto ex;
 
374
   if(ret==0)
 
375
 break;
 
376
 
 
377
   sub_size= 0;
 
378
   strcpy(show_path, rel_path);
 
379
   if(Sfile_add_to_path(show_path, name, 0)<=0)
 
380
       goto much_too_long;
 
381
 
 
382
   strcpy(path, abs_path);
 
383
   if(Sfile_add_to_path(path, name, 0)<=0) {
 
384
much_too_long:;
 
385
     Xorriso_much_too_long(xorriso, strlen(path)+strlen(name)+1, 2);
 
386
     {ret= -1; goto ex;}
 
387
   }
 
388
   no_dive= 0;
 
389
 
 
390
   ret= lstat(path, &stbuf);
 
391
   if(ret==-1)
 
392
 continue;
 
393
   is_link= S_ISLNK(stbuf.st_mode);
 
394
   if(is_link && xorriso->do_follow_links) {
 
395
     ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1);
 
396
     if(ret<0)
 
397
       {ret= -1; goto ex;}
 
398
     if(ret!=1)
 
399
       no_dive= 1;
 
400
   }
 
401
   if(!S_ISDIR(stbuf.st_mode))
 
402
     no_dive= 1;
 
403
   if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
 
404
     no_dive= 1;
 
405
   if(!no_dive) {
 
406
     filec++;
 
407
     l= strlen(rel_path)+1;
 
408
     mem+= l;
 
409
     if(l % sizeof(char *))
 
410
       mem+= sizeof(char *)-(l % sizeof(char *));
 
411
     if(flag&1) /* diving and counting is done further below */
 
412
 continue;
 
413
     ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size, boss_mem,
 
414
                                own_link_stack,2);
 
415
     if(ret<0)
 
416
       goto ex;
 
417
     if(ret==0)
 
418
 continue;
 
419
   }
 
420
   
 
421
/*
 
422
   sub_size+= stbuf.st_size+strlen(name)+1;
 
423
*/
 
424
   sub_size+= stbuf.st_size+2048;
 
425
   if(sub_size>0)
 
426
     (*size)+= sub_size;
 
427
 }
 
428
 
 
429
 if(filec<=0 || !(flag&1))
 
430
   {ret= 1; goto ex;}
 
431
 
 
432
 /* Try to get a sorted list of directory names */
 
433
 mem+= (filec+1)*sizeof(char *);
 
434
 ret= Xorriso_check_temp_mem_limit(xorriso, mem+boss_mem, 2);
 
435
 if(ret<0)
 
436
   goto ex;
 
437
 Dirseq_rewind(dirseq, 0);
 
438
 if(ret==0) {
 
439
no_sort_possible:;
 
440
   no_sort= 1;
 
441
 } else {
 
442
   filev= (char **) calloc(filec+1, sizeof(char *));
 
443
   if(filev==NULL)
 
444
     goto no_sort_possible;
 
445
   else {
 
446
     for(i= 0; i<filec; i++)
 
447
       filev[i]= NULL;
 
448
     fc= 0;
 
449
     while(1) {
 
450
       ret= Dirseq_next_adr(dirseq,name,0);
 
451
       if(ret<0)
 
452
         goto ex;
 
453
       if(ret==0)
 
454
     break;
 
455
       strcpy(path, abs_path);
 
456
       if(Sfile_add_to_path(path, name, 0)<=0)
 
457
         goto much_too_long;
 
458
 
 
459
       ret= lstat(path,&stbuf);
 
460
       if(ret==-1)
 
461
     continue;
 
462
       is_link= S_ISLNK(stbuf.st_mode);
 
463
       if(is_link && xorriso->do_follow_links) {
 
464
         ret= stat(path,&stbuf);
 
465
         if(ret==-1)
 
466
     continue;
 
467
       }
 
468
       if(!S_ISDIR(stbuf.st_mode))
 
469
     continue;
 
470
       if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
 
471
     continue;
 
472
 
 
473
       if(fc>=filec) { /* Number of files changed (or programming error) */
 
474
revoke_sorting:;
 
475
         for(j=0; j<fc; j++)
 
476
           free((char *) filev[j]);
 
477
         free((char *) filev);
 
478
         filev= NULL;
 
479
         goto no_sort_possible;
 
480
       }
 
481
 
 
482
       filev[fc]= strdup(name);
 
483
       if(filev[fc]==NULL)
 
484
         goto revoke_sorting;
 
485
       fc++;
 
486
     }
 
487
     filec= fc;
 
488
     if(filec>1)
 
489
       Sort_argv(filec, filev, 0);
 
490
   }
 
491
 }
 
492
 
 
493
 for(i= 0; (no_sort || i<filec) && !(xorriso->request_to_abort); i++) {
 
494
   Linkitem_reset_stack(&own_link_stack, link_stack, 0);
 
495
   if(no_sort) {
 
496
     ret= Dirseq_next_adr(dirseq,name,0);
 
497
     if(ret<0)
 
498
       goto ex;
 
499
     if(ret==0)
 
500
 break;
 
501
   } else
 
502
     namept= filev[i];
 
503
 
 
504
   sub_size= 0;
 
505
   strcpy(show_path, rel_path);
 
506
   if(Sfile_add_to_path(show_path, namept, 0)<=0)
 
507
     goto much_too_long;
 
508
   strcpy(path, abs_path);
 
509
   if(Sfile_add_to_path(path, namept, 0)<=0)
 
510
     goto much_too_long;
 
511
   no_dive= 0;
 
512
 
 
513
   ret= lstat(path,&stbuf);
 
514
   if(ret==-1)
 
515
 continue;
 
516
   is_link= S_ISLNK(stbuf.st_mode);
 
517
   if(is_link && xorriso->do_follow_links) {
 
518
     ret= Xorriso_hop_link(xorriso, path, &own_link_stack, &stbuf, 1);
 
519
     if(ret<0)
 
520
       {ret= -1; goto ex;}
 
521
     if(ret!=1)
 
522
 continue;
 
523
   }
 
524
   if(!S_ISDIR(stbuf.st_mode))
 
525
 continue;
 
526
   if(dir_dev == stbuf.st_dev || xorriso->do_follow_mount) {
 
527
     ret= Xorriso_show_dux_subs(xorriso, path, show_path, &sub_size,
 
528
                                boss_mem+mem, own_link_stack, 2|(flag&1));
 
529
     if(ret<0)
 
530
       goto ex;
 
531
   }
 
532
 
 
533
/*
 
534
   sub_size+= stbuf.st_size+strlen(namept)+1;
 
535
*/
 
536
   sub_size+= stbuf.st_size+2048;
 
537
   if(sub_size>0)
 
538
     (*size)+= sub_size;
 
539
   report_size= sub_size/1024;
 
540
   if(report_size*1024<sub_size)
 
541
      report_size++;
 
542
   sprintf(xorriso->result_line, "%7.f ",(double) (report_size));
 
543
   sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n",
 
544
           Text_shellsafe(show_path, sfe, 0));
 
545
   Xorriso_result(xorriso, 0);
 
546
 }
 
547
 
 
548
 ret= 1;
 
549
ex:;
 
550
 if(sfe!=NULL)
 
551
   free(sfe);
 
552
 if(path!=NULL)
 
553
   free(path);
 
554
 if(show_path!=NULL)
 
555
   free(show_path);
 
556
 if(name!=NULL)
 
557
   free(name);
 
558
 Linkitem_reset_stack(&own_link_stack, link_stack, 0);
 
559
 Dirseq_destroy(&dirseq, 0);
 
560
 if(filev!=NULL) {
 
561
   for(i=0; i<filec; i++)
 
562
     if(filev[i]!=NULL)
 
563
       free((char *) filev[i]);
 
564
   free((char *) filev);
 
565
 }
 
566
 return(ret);
 
567
}
 
568
 
 
569
 
 
570
/* @param flag   bit1= add '+' to perms
 
571
                 bit2-3: hidden_state : 0=off, 1=iso_rr, 2=joliet= 3=on
 
572
*/
 
573
int Xorriso__mode_to_perms(mode_t st_mode, char perms[11], int flag)
 
574
{
 
575
 int hidden_state;
 
576
 
 
577
 strcpy(perms,"--------- ");
 
578
 if(st_mode&S_IRUSR) perms[0]= 'r';
 
579
 if(st_mode&S_IWUSR) perms[1]= 'w';
 
580
 if(st_mode&S_IXUSR) perms[2]= 'x';
 
581
 if(st_mode&S_ISUID) {
 
582
   if(st_mode&S_IXUSR)
 
583
     perms[2]= 's';
 
584
   else
 
585
     perms[2]= 'S';
 
586
 }
 
587
 if(st_mode&S_IRGRP) perms[3]= 'r';
 
588
 if(st_mode&S_IWGRP) perms[4]= 'w';
 
589
 if(st_mode&S_IXGRP) perms[5]= 'x';
 
590
 if(st_mode&S_ISGID) {
 
591
   if(st_mode&S_IXGRP)
 
592
     perms[5]= 's';
 
593
   else
 
594
     perms[5]= 'S';
 
595
 }
 
596
 if(st_mode&S_IROTH) perms[6]= 'r';
 
597
 if(st_mode&S_IWOTH) perms[7]= 'w';
 
598
 if(st_mode&S_IXOTH) perms[8]= 'x';
 
599
 if(st_mode&S_ISVTX) {
 
600
   if(st_mode&S_IXOTH)
 
601
     perms[8]= 't';
 
602
   else
 
603
     perms[8]= 'T';
 
604
 }
 
605
 hidden_state= (flag >> 2) & 3;
 
606
 if(hidden_state == 1)
 
607
   perms[9]= 'I';
 
608
 else if(hidden_state == 2)
 
609
   perms[9]= 'J';
 
610
 else if(hidden_state == 3)
 
611
   perms[9]= 'H';
 
612
 if(flag & 2) {
 
613
   if(hidden_state)
 
614
     perms[9]= tolower(perms[9]);
 
615
   else
 
616
     perms[9]= '+';
 
617
 }
 
618
 return(1);
 
619
}
 
620
 
 
621
 
 
622
/* @param flag bit0= recognize Xorriso_IFBOOT as file type
 
623
               bit1= add '+' to perms
 
624
               bit2-3: hidden_state : 0=off, 1=iso_rr, 2=joliet= 3=on
 
625
*/
 
626
int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag)
 
627
{
 
628
 int show_major_minor= 0, high_shift= 0, high_mask= 0;
 
629
 char *rpt, perms[11], mm_text[80];
 
630
 mode_t st_mode;
 
631
 dev_t dev, major, minor;
 
632
 
 
633
 rpt= xorriso->result_line;
 
634
 rpt[0]= 0;
 
635
 st_mode= stbuf->st_mode;
 
636
 
 
637
 if(S_ISDIR(st_mode))
 
638
   strcat(rpt, "d");
 
639
 else if(S_ISREG(st_mode)) {
 
640
   strcat(rpt, "-");
 
641
 } else if(S_ISLNK(st_mode))
 
642
   strcat(rpt, "l");
 
643
 else if(S_ISBLK(st_mode)) {
 
644
   strcat(rpt, "b");
 
645
   show_major_minor= 1;
 
646
 } else if(S_ISCHR(st_mode)) {
 
647
   strcat(rpt, "c");
 
648
   show_major_minor= 1;
 
649
 } else if(S_ISFIFO(st_mode))
 
650
   strcat(rpt, "p");
 
651
 else if(S_ISSOCK(st_mode))
 
652
   strcat(rpt, "s");
 
653
 else if((flag & 1) && (st_mode & S_IFMT) == Xorriso_IFBOOT)
 
654
   strcat(rpt, "e");
 
655
 else
 
656
   strcat(rpt, "?");
 
657
 
 
658
 Xorriso__mode_to_perms(st_mode, perms, flag & (2 | 12));
 
659
 strcat(rpt, perms);
 
660
 
 
661
 sprintf(rpt+strlen(rpt)," %3u ",(unsigned int) stbuf->st_nlink);
 
662
 
 
663
 sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_uid);
 
664
 sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_gid);
 
665
 if(show_major_minor) {
 
666
   dev= stbuf->st_rdev;
 
667
 
 
668
   /* according to /usr/include/sys/sysmacros.h : gnu_dev_major(),_minor() 
 
669
      >>> but this looks as if it should go to some system dependency
 
670
      >>> in FreeBSD dev_t is 32 bit
 
671
   */
 
672
   if(sizeof(dev_t) > 4) {
 
673
     high_shift= 32;
 
674
     high_mask= ~0xfff;
 
675
   }
 
676
   major= (((dev >> 8) & 0xfff) |
 
677
           ((unsigned int) (dev >> high_shift) & high_mask))
 
678
          & 0xffffffff;
 
679
   minor= (((dev & 0xff) | ((unsigned int) (dev >> 12) & ~0xff))) & 0xffffffff;
 
680
 
 
681
   sprintf(mm_text, "%u,%u", (unsigned int) major, (unsigned int) minor);
 
682
   sprintf(rpt+strlen(rpt), "%8s ", mm_text);
 
683
 } else
 
684
   sprintf(rpt+strlen(rpt), "%8.f ", (double) stbuf->st_size);
 
685
 
 
686
 Ftimetxt(stbuf->st_mtime, rpt+strlen(rpt), 0);
 
687
 strcat(rpt, " ");
 
688
 
 
689
 return(1);
 
690
}
 
691
 
 
692
 
 
693
struct DirentrY {
 
694
 char *adr;
 
695
 struct DirentrY *next;
 
696
};
 
697
 
 
698
 
 
699
int Xorriso_sorted_dir_x(struct XorrisO *xorriso, char *dir_path,
 
700
                         int *filec, char ***filev, off_t boss_mem, int flag)
 
701
{
 
702
 int count= 0, ret;
 
703
 char name[SfileadrL];
 
704
 struct DirseQ *dirseq= NULL;
 
705
 off_t mem;
 
706
 struct DirentrY *last= NULL, *current= NULL;
 
707
 
 
708
 *filec= 0;
 
709
 *filev= NULL;
 
710
 mem= boss_mem;
 
711
 ret= Dirseq_new(&dirseq, dir_path, 1);
 
712
 if(ret<=0)
 
713
   goto ex;
 
714
 while(1) { /* loop over directory content */
 
715
   ret= Dirseq_next_adr(dirseq,name,0);
 
716
   if(ret==0)
 
717
 break;
 
718
   if(ret<0)
 
719
     goto ex;
 
720
   mem+= strlen(name)+8+sizeof(struct DirentrY)+sizeof(char *);
 
721
   if(mem>xorriso->temp_mem_limit)
 
722
     {ret= 0; goto ex;}
 
723
 
 
724
   current= (struct DirentrY *) calloc(1, sizeof(struct DirentrY));
 
725
   if(current==NULL)
 
726
     {ret= -1; goto ex;}
 
727
   current->adr= NULL;
 
728
   current->next= last;
 
729
   last= current;
 
730
   last->adr= strdup(name);
 
731
   if(last->adr==NULL)
 
732
     {ret= -1; goto ex;}
 
733
   count++;
 
734
 }
 
735
 *filec= count;
 
736
 if(count==0)
 
737
   {ret= 1; goto ex;}
 
738
 (*filev)= (char **) calloc(count, sizeof(char *));
 
739
 if(*filev==NULL)
 
740
   {ret= -1; goto ex; }
 
741
 count= 0;
 
742
 for(current= last; current!=NULL; current= last) {
 
743
   last= current->next;
 
744
   (*filev)[count++]= current->adr;
 
745
   free((char *) current);
 
746
 }
 
747
 Sort_argv(*filec, *filev, 0);
 
748
 ret= 1; 
 
749
ex:;
 
750
 for(current= last; current!=NULL; current= last) {
 
751
   last= current->next;
 
752
   free(current->adr);
 
753
   free((char *) current);
 
754
 }
 
755
 return(ret);
 
756
}
 
757
 
 
758
 
 
759
/* @param flag bit0= long format
 
760
               bit1= do not print count of nodes
 
761
               bit2= du format
 
762
               bit3= print directories as themselves (ls -d)
 
763
*/
 
764
int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd,
 
765
                      int filec, char **filev, off_t boss_mem, int flag)
 
766
{
 
767
 int i, ret, was_error= 0, dfilec= 0, pass, passes;
 
768
 char sfe[5*SfileadrL], sfe2[5*SfileadrL], path[SfileadrL], *acl_text= NULL;
 
769
 char *rpt, link_target[SfileadrL], **dfilev= NULL;
 
770
 off_t size;
 
771
 struct stat stbuf;
 
772
 
 
773
 rpt= xorriso->result_line;
 
774
 
 
775
 Sort_argv(filec, filev, 0);
 
776
 
 
777
 /* Count valid nodes, warn of invalid ones */
 
778
 for(i= 0; i<filec; i++) {
 
779
   ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4);
 
780
   if(ret<=0) {
 
781
     was_error++;
 
782
 continue;
 
783
   }
 
784
   ret= lstat(path, &stbuf);
 
785
   if(ret==-1) {
 
786
     sprintf(xorriso->info_text, "Not found in local filesystem: %s",
 
787
             Text_shellsafe(path, sfe, 0));
 
788
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 1);
 
789
     was_error++;
 
790
 continue;
 
791
   }
 
792
 }
 
793
 
 
794
 if((flag&8) && !(flag&(2|4))) {
 
795
   sprintf(xorriso->info_text,"Valid local files found: %d\n",filec-was_error);
 
796
   Xorriso_info(xorriso,1);
 
797
   if(filec-was_error<=0)
 
798
     return(!was_error);
 
799
 }
 
800
 
 
801
 passes= 1+!(flag&(4|8));
 
802
 for(pass= 0; pass<passes; pass++)
 
803
 for(i= 0; i<filec && !(xorriso->request_to_abort); i++) {
 
804
   ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4);
 
805
   if(ret<=0)
 
806
 continue;
 
807
   ret= lstat(path, &stbuf);
 
808
   if(ret==-1)
 
809
 continue;
 
810
   if(S_ISLNK(stbuf.st_mode) &&
 
811
      (xorriso->do_follow_links || xorriso->do_follow_param)) {
 
812
     ret= stat(path, &stbuf);
 
813
     if(ret==-1) 
 
814
       ret= lstat(path, &stbuf);
 
815
     if(ret==-1)
 
816
 continue;
 
817
   }
 
818
   if(S_ISDIR(stbuf.st_mode) && !(flag&(4|8))) {
 
819
     if(pass==0)
 
820
 continue;
 
821
     if(filec>1) {
 
822
       strcpy(xorriso->result_line, "\n");
 
823
       Xorriso_result(xorriso,0);
 
824
       sprintf(xorriso->result_line, "%s:\n", Text_shellsafe(filev[i], sfe,0));
 
825
       Xorriso_result(xorriso,0);
 
826
     }
 
827
     ret= Xorriso_sorted_dir_x(xorriso, path, &dfilec, &dfilev, boss_mem, 0);
 
828
     if(ret<=0) {
 
829
 
 
830
       /* >>> DirseQ loop and single item Xorriso_lsx_filev() */;
 
831
 
 
832
     } else {
 
833
       if(flag&1) {
 
834
         sprintf(xorriso->result_line, "total %d\n", dfilec);
 
835
         Xorriso_result(xorriso,0);
 
836
       }
 
837
       Xorriso_lsx_filev(xorriso, path,
 
838
                         dfilec, dfilev, boss_mem, (flag&1)|2|8);
 
839
     }
 
840
     if(dfilec>0)
 
841
       Sfile_destroy_argv(&dfilec, &dfilev, 0);
 
842
 continue;
 
843
   } else
 
844
     if(pass>0)
 
845
 continue;
 
846
   link_target[0]= 0;
 
847
   rpt[0]= 0;
 
848
   if((flag&5)==1) {
 
849
     Xorriso_local_getfacl(xorriso, path, &acl_text, 16);
 
850
     ret= Xorriso_format_ls_l(xorriso, &stbuf, (acl_text != NULL) << 1);
 
851
     Xorriso_local_getfacl(xorriso, path, &acl_text, 1 << 15);
 
852
     if(ret<=0)
 
853
 continue;
 
854
     if(S_ISLNK(stbuf.st_mode)) {
 
855
       ret= Xorriso_resolve_link(xorriso, path, link_target, 1);
 
856
       if(ret<=0)
 
857
         link_target[0]= 0;
 
858
     }
 
859
   } else if(flag&4) { /* -du or -dus */
 
860
     size= stbuf.st_size;
 
861
     if(S_ISDIR(stbuf.st_mode)) {
 
862
       ret= Xorriso_show_dux_subs(xorriso, path, filev[i], &size, boss_mem,
 
863
                                  NULL, flag&1);
 
864
       if(ret<0)
 
865
         return(-1);
 
866
       if(ret==0)
 
867
 continue;
 
868
     }
 
869
     sprintf(rpt, "%7.f ",(double) (size/1024));
 
870
   }
 
871
   if(link_target[0])
 
872
     sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s -> %s\n",
 
873
             Text_shellsafe(filev[i], sfe, 0),
 
874
             Text_shellsafe(link_target, sfe2, 0));
 
875
   else
 
876
     sprintf(xorriso->result_line+strlen(xorriso->result_line), "%s\n",
 
877
               Text_shellsafe(filev[i], sfe, 0));
 
878
   Xorriso_result(xorriso, 0);
 
879
 }
 
880
 return(!was_error);
 
881
}
 
882
 
 
883
 
 
884
/*
 
885
   @param flag >>> bit0= remove whole sub tree: rm -r
 
886
               bit1= remove empty directory: rmdir  
 
887
               bit2= recursion: do not reassure in mode 2 "tree"
 
888
               bit3= this is for overwriting and not for plain removal
 
889
               bit4= count deleted files in xorriso->pacifier_count
 
890
               bit5= with bit0 only remove directory content, not the directory
 
891
               bit6= permission to call Xorriso_make_accessible()
 
892
   @return   <=0 = error
 
893
               1 = removed leaf file object
 
894
               2 = removed directory or tree
 
895
               3 = did not remove on user revocation
 
896
*/
 
897
int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag)
 
898
{
 
899
 int ret, is_dir= 0, made_accessible= 0;
 
900
 struct stat victim_stbuf, *victim_node= NULL;
 
901
 struct DirseQ *dirseq= NULL;
 
902
 char *sfe= NULL, *sub_path= NULL;
 
903
 struct PermiteM *perm_stack_mem;
 
904
 
 
905
 perm_stack_mem= xorriso->perm_stack;
 
906
 
 
907
 /* Avoiding large local memory objects in order to save stack space */
 
908
 sfe= malloc(5*SfileadrL);
 
909
 sub_path= malloc(2*SfileadrL);
 
910
 if(sfe==NULL || sub_path==NULL) {
 
911
   Xorriso_no_malloc_memory(xorriso, &sfe, 0);
 
912
   {ret= -1; goto ex;}
 
913
 }
 
914
 
 
915
 if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0)
 
916
   {ret= 0; goto ex;}
 
917
 
 
918
 ret= lstat(path, &victim_stbuf);
 
919
 if(ret==-1) {
 
920
   if((flag & 64) && errno == EACCES) {
 
921
     ret= Xorriso_make_accessible(xorriso, path, 0);
 
922
     if(ret < 0)
 
923
       goto ex;
 
924
     made_accessible= 1;
 
925
     ret= lstat(path, &victim_stbuf);
 
926
   }
 
927
   if(ret==-1) {
 
928
     sprintf(xorriso->info_text, "Cannot lstat(%s)",
 
929
             Text_shellsafe(path, sfe, 0));
 
930
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 
931
     {ret= 0; goto ex;}
 
932
   }
 
933
 }
 
934
 if(strcmp(path, "/")==0) {
 
935
   sprintf(xorriso->info_text, "May not delete root directory");
 
936
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 
937
   {ret= 0; goto ex;}
 
938
 }
 
939
 victim_node= &victim_stbuf;
 
940
 if(S_ISDIR(victim_stbuf.st_mode))
 
941
   is_dir= 1;
 
942
 if(!is_dir) {
 
943
   if(flag&2) { /* rmdir */
 
944
     sprintf(xorriso->info_text, "%s in disk filesystem is not a directory",
 
945
             Text_shellsafe(path, sfe, 0));
 
946
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 
947
     ret= 0; goto ex;
 
948
   }
 
949
 } else {
 
950
   if(flag&1) { /* rm -r */
 
951
 
 
952
#ifdef Osirrox_not_yeT
 
953
     /* >>> */
 
954
 
 
955
     if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) ||
 
956
        (flag&32)) {
 
957
       /* Iterate over subordinates and delete them */
 
958
       mem= boss_mem;
 
959
 
 
960
       ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem,
 
961
                         &iter, &node_array, &node_count, &node_idx,
 
962
                         &node, 1|2);
 
963
       if(ret<=0) {
 
964
cannot_create_iter:;
 
965
         Xorriso_cannot_create_iter(xorriso, ret, 0);
 
966
         ret= -1; goto ex;
 
967
       }
 
968
       pl= strlen(path);
 
969
       strcpy(sub_path, path);
 
970
       if(pl==0 || sub_path[pl-1]!='/') {
 
971
         sub_path[pl++]= '/';
 
972
         sub_path[pl]= 0;
 
973
       }
 
974
       sub_name= sub_path+pl;
 
975
       while(1) { 
 
976
         ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter,
 
977
                                &node_array, &node_count, &node_idx, &node, 0);
 
978
         if(ret<0)
 
979
           goto ex;
 
980
         if(ret==0 || xorriso->request_to_abort)
 
981
       break;
 
982
         name= (char *) iso_node_get_name(node);
 
983
         if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0)
 
984
           {ret= 0; goto rm_r_problem_handler;}
 
985
         strcpy(sub_name, name);
 
986
         ret= Xorriso_rmi(xorriso, iter, mem, sub_path, (flag&(1|2|8|16))|4);
 
987
         if(ret==3 || ret<=0 || xorriso->request_to_abort) {
 
988
rm_r_problem_handler:;
 
989
           not_removed= 1;
 
990
           fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
 
991
           if(fret<0)
 
992
             goto dir_not_removed;
 
993
         }
 
994
       }
 
995
       if(flag&32)
 
996
         {ret= 2; goto ex;}
 
997
 
 
998
       if(not_removed) {
 
999
dir_not_removed:;
 
1000
         sprintf(xorriso->info_text, "Directory not removed: %s",
 
1001
                 Text_shellsafe(path, sfe, 0));
 
1002
         Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 
1003
         if(ret>0)
 
1004
           ret= 3;
 
1005
         goto ex;
 
1006
       }
 
1007
     }
 
1008
 
 
1009
#else /* Osirrox_not_yeT */
 
1010
 
 
1011
       sprintf(xorriso->info_text, "-rm_rx is not implemented yet");
 
1012
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 
1013
       ret= 0; goto ex;
 
1014
 
 
1015
#endif /* !Osirrox_not_yeT */
 
1016
 
 
1017
   } else {
 
1018
     if(!(flag&2)) { /* not rmdir */
 
1019
       sprintf(xorriso->info_text, "%s in disk filesystem is a directory",
 
1020
               Text_shellsafe(path, sfe, 0));
 
1021
       Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 
1022
       ret= 0; goto ex;
 
1023
     }
 
1024
     ret= Dirseq_new(&dirseq, path, 1);
 
1025
     if(ret>0) {
 
1026
       ret= Dirseq_next_adr(dirseq, sfe, 0);
 
1027
       if(ret>0) {
 
1028
         sprintf(xorriso->info_text,
 
1029
                 "Directory not empty on attempt to delete: %s",
 
1030
                 Text_shellsafe(path, sfe, 0));
 
1031
         Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 
1032
         ret= 0; goto ex;
 
1033
       }
 
1034
     }
 
1035
   }
 
1036
 }
 
1037
 if(xorriso->request_to_abort)
 
1038
   {ret= 3; goto ex;}
 
1039
 ret= Xorriso_reassure_restore(xorriso, path, (flag&(4|8)) | !!is_dir);
 
1040
 if(ret<=0 || ret==3)
 
1041
   goto ex;
 
1042
 if(is_dir)
 
1043
   ret= rmdir(path);
 
1044
 else
 
1045
   ret= unlink(path);
 
1046
 if(ret == -1) {
 
1047
   if((flag & 64) && errno == EACCES && !made_accessible) {
 
1048
     ret= Xorriso_make_accessible(xorriso, path, 0);
 
1049
     if(ret < 0)
 
1050
       goto ex;
 
1051
     made_accessible= 1;
 
1052
     if(is_dir)
 
1053
       ret= rmdir(path);
 
1054
     else
 
1055
       ret= unlink(path);
 
1056
   }
 
1057
   if(ret == -1) {
 
1058
     sprintf(xorriso->info_text, "Cannot delete from disk filesystem %s",
 
1059
             Text_shellsafe(path, sfe, 0));
 
1060
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 
1061
     ret= -1; goto ex;
 
1062
   }
 
1063
 }
 
1064
 if(flag&16)
 
1065
   xorriso->pacifier_count++;
 
1066
 ret= 1+!!is_dir;
 
1067
ex:;
 
1068
 if(made_accessible)
 
1069
   Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 
1070
 if(sfe!=NULL)
 
1071
   free(sfe);
 
1072
 if(sub_path!=NULL)
 
1073
   free(sub_path);
 
1074
 Dirseq_destroy(&dirseq, 0);
 
1075
 return(ret);
 
1076
 
1077
 
 
1078
 
 
1079
/* @param flag bit0= recursion
 
1080
*/ 
 
1081
int Xorriso_findx_action(struct XorrisO *xorriso, struct FindjoB *job,
 
1082
                         char *abs_path, char *show_path, int depth, int flag)
 
1083
{
 
1084
 int ret= 0, type, action= 0, dpl= 0, compare_result, uret;
 
1085
 uid_t user= 0;
 
1086
 gid_t group= 0;
 
1087
 time_t date= 0;
 
1088
 mode_t mode_or= 0, mode_and= ~1;
 
1089
 char *target, *text_2, sfe[5*SfileadrL], *disk_prefix, iso_path[SfileadrL];
 
1090
 char *basename;
 
1091
 struct FindjoB *subjob;
 
1092
 struct stat stbuf; 
 
1093
 
 
1094
 action= Findjob_get_action_parms(job, &target, &text_2, &user, &group,
 
1095
                                &mode_and, &mode_or, &type, &date, &subjob, 0);
 
1096
 if(action<0)
 
1097
   action= 0;
 
1098
 if(action<0)
 
1099
   action= 0;
 
1100
 if(action==15 || action==16 || action==18 || action==19 || action==20) {
 
1101
   /* in_iso , not_in_iso, add_missing , empty_iso_dir , is_full_in_iso */
 
1102
   Findjob_get_start_path(job, &disk_prefix, 0);
 
1103
   if(strncmp(abs_path, disk_prefix, strlen(disk_prefix))!=0)
 
1104
     {ret= -1; goto ex;}
 
1105
   dpl= strlen(disk_prefix);
 
1106
   if(strlen(target)+strlen(abs_path)-dpl >= SfileadrL)
 
1107
     {ret= -1; goto ex;}
 
1108
   if(abs_path[dpl]=='/')
 
1109
     dpl++;
 
1110
   ret= Xorriso_make_abs_adr(xorriso, target, abs_path+dpl, iso_path, 4);
 
1111
   if(ret<=0)
 
1112
     {goto ex;}
 
1113
 
 
1114
 }
 
1115
 if(action==15) { /* in_iso */
 
1116
   ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
 
1117
   if(ret<0)
 
1118
     {ret= 1; goto ex;}
 
1119
   sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0));
 
1120
   Xorriso_result(xorriso, 0);
 
1121
   ret= 1;
 
1122
 } else if(action==16) { /* not_in_iso */
 
1123
   ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl,
 
1124
                                &compare_result, 4);
 
1125
   if(ret<xorriso->find_compare_result)
 
1126
     xorriso->find_compare_result= ret;
 
1127
   if(ret>=0)
 
1128
     ret= 1;
 
1129
 } else if(action==18) { /* add_missing */
 
1130
   ret= Xorriso_compare_2_files(xorriso, abs_path, iso_path, abs_path+dpl,
 
1131
                                &compare_result, 4|(1<<31));
 
1132
   if(ret<xorriso->find_compare_result)
 
1133
     xorriso->find_compare_result= ret;
 
1134
   if(ret==0) {
 
1135
     uret= Xorriso_update_interpreter(xorriso, NULL, NULL, compare_result,
 
1136
                                      abs_path, iso_path, ((flag&1)<<2) | 2);
 
1137
     if(uret<=0)
 
1138
       ret= 0;
 
1139
   }
 
1140
   if(ret>=0)
 
1141
     ret= 1;
 
1142
 } else if(action==19) { /* empty_iso_dir */
 
1143
   ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
 
1144
   if(ret<0)
 
1145
     {ret= 1; goto ex;}
 
1146
   if(!S_ISDIR(stbuf.st_mode))
 
1147
     {ret= 1; goto ex;}
 
1148
   ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, iso_path, 1|32);
 
1149
   if(ret>0) {
 
1150
     sprintf(xorriso->info_text, "Emptied directory %s",
 
1151
             Text_shellsafe(iso_path, sfe, 0));
 
1152
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
 
1153
   }
 
1154
 } else if(action==20) { /* is_full_in_iso */
 
1155
   ret= Xorriso_iso_lstat(xorriso, iso_path, &stbuf, 0);
 
1156
   if(ret<0)
 
1157
     {ret= 1; goto ex;}
 
1158
   if(!S_ISDIR(stbuf.st_mode))
 
1159
     {ret= 1; goto ex;}
 
1160
   strcpy(sfe, xorriso->wdi);
 
1161
   strcpy(xorriso->wdi, iso_path);
 
1162
   ret= Xorriso_ls(xorriso, 4|8);
 
1163
   strcpy(xorriso->wdi, sfe);
 
1164
   if(ret>0) {
 
1165
     sprintf(xorriso->result_line,
 
1166
            "d %s (ISO) : non-empty directory (would not match mount point)\n",
 
1167
            Text_shellsafe(iso_path, sfe, 0));
 
1168
     Xorriso_result(xorriso,0);
 
1169
   }
 
1170
   {ret= 1; goto ex;}
 
1171
 } else if(action == 40) { /* estimate_size */
 
1172
   basename= strrchr(abs_path, '/');
 
1173
   if(basename != NULL)
 
1174
     basename++;
 
1175
   else
 
1176
     basename= abs_path;
 
1177
   ret= lstat(abs_path, &stbuf);
 
1178
   if(ret != -1)
 
1179
     ret= Xorriso_estimate_file_size(xorriso, job, basename, stbuf.st_mode,
 
1180
                                     stbuf.st_size, 0);
 
1181
 } else {
 
1182
   sprintf(xorriso->result_line, "%s\n", Text_shellsafe(show_path, sfe, 0));
 
1183
   Xorriso_result(xorriso, 0);
 
1184
   ret= 1;
 
1185
 } 
 
1186
ex:;
 
1187
 if(action==15 || action==16 || action==18 || action==19 || action==20)
 
1188
   if(xorriso->no_volset_present)
 
1189
     xorriso->request_to_abort= 1; /* Need an image. No use to try again. */
 
1190
 return(ret);
 
1191
}
 
1192
 
 
1193
 
 
1194
/* @param flag bit0=recursion
 
1195
*/
 
1196
int Xorriso_findx(struct XorrisO *xorriso, struct FindjoB *job,
 
1197
                  char *abs_dir_parm, char *dir_path,
 
1198
                  struct stat *dir_stbuf, int depth,
 
1199
                  struct LinkiteM *link_stack, int flag)
 
1200
{
 
1201
 int ret,is_link, no_dive;
 
1202
 struct DirseQ *dirseq= NULL;
 
1203
 struct stat stbuf;
 
1204
 struct LinkiteM *own_link_stack;
 
1205
 char *abs_dir_path, *namept;
 
1206
 char *name= NULL, *path= NULL, *sfe= NULL;
 
1207
 char *abs_dir_path_data= NULL, *abs_path= NULL;
 
1208
 
 
1209
 if(xorriso->request_to_abort)
 
1210
   {ret= 0; goto ex;}
 
1211
 
 
1212
 sfe= malloc(5*SfileadrL);
 
1213
 name= malloc(SfileadrL);
 
1214
 path= malloc(SfileadrL);
 
1215
 abs_dir_path_data= malloc(SfileadrL);
 
1216
 abs_path= malloc(SfileadrL);
 
1217
 if(name==NULL || sfe==NULL || path==NULL ||
 
1218
    abs_dir_path_data==NULL || abs_path==NULL) {
 
1219
   Xorriso_no_malloc_memory(xorriso, &sfe, 0);
 
1220
   {ret= -1; goto ex;}
 
1221
 }
 
1222
 own_link_stack= link_stack;
 
1223
 abs_dir_path= abs_dir_parm;
 
1224
 if(abs_dir_path[0]==0) {
 
1225
   ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, dir_path,
 
1226
                             abs_dir_path_data, 1|2|8);
 
1227
   if(ret<=0)
 
1228
     goto ex;
 
1229
   abs_dir_path= abs_dir_path_data;
 
1230
   ret= Xorriso_path_is_excluded(xorriso, abs_dir_path, !(flag&1));
 
1231
   if(ret<0)
 
1232
     goto ex;
 
1233
   if(ret>0)
 
1234
     {ret= 0; goto ex;}
 
1235
   ret= lstat(abs_dir_path, dir_stbuf);
 
1236
   if(ret==-1)
 
1237
     {ret= 0; goto ex;}
 
1238
   if(S_ISLNK(dir_stbuf->st_mode) &&
 
1239
      (xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
 
1240
     if(stat(abs_dir_path, &stbuf)!=-1)
 
1241
       if(dir_stbuf->st_dev == stbuf.st_dev ||
 
1242
         (xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1))))
 
1243
         memcpy(dir_stbuf, &stbuf, sizeof(struct stat));
 
1244
 
 
1245
   namept= strrchr(dir_path, '/');
 
1246
   if(namept==NULL)
 
1247
     namept= dir_path;
 
1248
   else
 
1249
     namept++;
 
1250
 
 
1251
   ret= Findjob_test_2(xorriso, job, NULL, namept, dir_path, NULL, dir_stbuf,
 
1252
                       0);
 
1253
   if(ret<0)
 
1254
     goto ex;
 
1255
   if(ret>0) {
 
1256
     ret= Xorriso_findx_action(xorriso, job, abs_dir_path, dir_path, depth,
 
1257
                               flag&1);
 
1258
     if(xorriso->request_to_abort)
 
1259
       {ret= 0; goto ex;}
 
1260
     if(ret<=0) {
 
1261
       if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
 
1262
         goto ex;
 
1263
     }
 
1264
   }
 
1265
 }
 
1266
 if(xorriso->request_to_abort)
 
1267
   {ret= 1; goto ex;}
 
1268
 if(!S_ISDIR(dir_stbuf->st_mode))
 
1269
   {ret= 2; goto ex;}
 
1270
 
 
1271
 ret= Dirseq_new(&dirseq, abs_dir_path, 1);
 
1272
 if(ret<0) {
 
1273
   sprintf(xorriso->info_text, "Cannot obtain disk directory iterator");
 
1274
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 
1275
   {ret= -1; goto ex;}
 
1276
 }
 
1277
 if(ret==0)
 
1278
   {ret= 2; goto ex;}
 
1279
 
 
1280
 while(!xorriso->request_to_abort) {
 
1281
   Linkitem_reset_stack(&own_link_stack, link_stack, 0);
 
1282
   ret= Dirseq_next_adr(dirseq,name,0);
 
1283
   if(ret==0)
 
1284
 break;
 
1285
   if(ret<0) {
 
1286
     sprintf(xorriso->info_text,"Failed to obtain next directory entry");
 
1287
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
 
1288
     {ret= -1; goto ex;}
 
1289
   }
 
1290
   ret= Xorriso_make_abs_adr(xorriso, abs_dir_path, name, abs_path, 1);
 
1291
   if(ret<=0)
 
1292
     goto ex;
 
1293
   ret= Xorriso_make_abs_adr(xorriso, dir_path, name, path, 4);
 
1294
   if(ret<=0)
 
1295
     goto ex;
 
1296
   ret= Xorriso_path_is_excluded(xorriso, abs_path, 0); /* (is never param) */
 
1297
   if(ret<0)
 
1298
     goto ex;
 
1299
   if(ret>0)
 
1300
 continue;
 
1301
   ret= lstat(abs_path, &stbuf);
 
1302
   if(ret==-1)
 
1303
 continue;
 
1304
   no_dive= 0;
 
1305
 
 
1306
   is_link= S_ISLNK(stbuf.st_mode);
 
1307
   if(is_link && xorriso->do_follow_links) {
 
1308
     ret= Xorriso_hop_link(xorriso, abs_path, &own_link_stack, &stbuf, 2);
 
1309
     if(ret<0)
 
1310
       {ret= -1; goto ex;}
 
1311
     if(ret!=1)
 
1312
       no_dive= 1;
 
1313
   }
 
1314
 
 
1315
   ret= Findjob_test_2(xorriso, job, NULL, name, path, dir_stbuf, &stbuf, 0);
 
1316
   if(ret<0)
 
1317
     goto ex;
 
1318
   if(ret>0) {
 
1319
     ret= Xorriso_findx_action(xorriso, job, abs_path, path, depth, flag&1);
 
1320
     if(xorriso->request_to_abort)
 
1321
       {ret= 0; goto ex;}
 
1322
     if(ret<=0) {
 
1323
       if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
 
1324
         goto ex;
 
1325
     }
 
1326
   }
 
1327
   if(!S_ISDIR(stbuf.st_mode))
 
1328
     no_dive= 1;
 
1329
   if(dir_stbuf->st_dev != stbuf.st_dev && !xorriso->do_follow_mount)
 
1330
     no_dive= 1;
 
1331
   if(!no_dive) {
 
1332
     ret= Xorriso_findx(xorriso, job, abs_path, path, &stbuf, depth+1,
 
1333
                        own_link_stack, flag|1);
 
1334
     if(ret<0)
 
1335
       goto ex;
 
1336
   }
 
1337
 }
 
1338
 
 
1339
 ret= 1;
 
1340
ex:;
 
1341
 if(sfe!=NULL)
 
1342
   free(sfe);
 
1343
 if(name!=NULL)
 
1344
   free(name);
 
1345
 if(path!=NULL)
 
1346
   free(path);
 
1347
 if(abs_dir_path_data!=NULL)
 
1348
   free(abs_dir_path_data);
 
1349
 if(abs_path!=NULL)
 
1350
   free(abs_path);
 
1351
 Dirseq_destroy(&dirseq, 0);
 
1352
 return(ret);
 
1353
}
 
1354
 
 
1355
 
 
1356
/* @param flag bit0= no hardlink reconstruction
 
1357
               bit1= do not set xorriso->node_*_prefixes
 
1358
               bit5= -extract_single: eventually do not insert directory tree
 
1359
*/
 
1360
int Xorriso_restore_sorted(struct XorrisO *xorriso, int count,
 
1361
                           char **src_array, char **tgt_array,
 
1362
                           int *problem_count, int flag)
 
1363
{
 
1364
 int i, ret, with_node_array= 0, hflag= 0, hret;
 
1365
 
 
1366
 *problem_count= 0;
 
1367
 if(!(((xorriso->ino_behavior & 16) && xorriso->do_restore_sort_lba) ||
 
1368
      (xorriso->ino_behavior & 4) || (flag & 1))) {
 
1369
   ret= Xorriso_make_hln_array(xorriso, 0);
 
1370
   if(ret<=0)
 
1371
     goto ex;
 
1372
 }
 
1373
 if(xorriso->do_restore_sort_lba) {
 
1374
   /* Count affected nodes */
 
1375
   Xorriso_destroy_node_array(xorriso, 0);
 
1376
   for(i= 0; i < count; i++) {
 
1377
     if(src_array[i] == NULL || tgt_array[i] == NULL)
 
1378
   continue;
 
1379
     /* sort_lba : Make directories plus node_array and then
 
1380
                   run array extractor (with eventual hardlink detection)
 
1381
     */
 
1382
     hflag= (1 << 7) | ((!!(flag & 2)) << 9);
 
1383
     ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
 
1384
                          (off_t) 0, (off_t) 0, hflag);
 
1385
     if(ret <= 0) {
 
1386
       (*problem_count)++;
 
1387
       hret= Xorriso_eval_problem_status(xorriso, ret, 0);
 
1388
       if(hret < 0)
 
1389
         goto ex;
 
1390
     }
 
1391
     with_node_array= 1;
 
1392
   }
 
1393
 }
 
1394
 
 
1395
 if(with_node_array) {
 
1396
   /* Allocate and fill node array */
 
1397
   if(xorriso->node_counter <= 0)
 
1398
     {ret= 2; goto ex;}
 
1399
   ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit, 0,
 
1400
                               !xorriso->do_restore_sort_lba);
 
1401
   if(ret<=0)
 
1402
     goto ex;
 
1403
   for(i= 0; i < count; i++) {
 
1404
     if(src_array[i] == NULL || tgt_array[i] == NULL)
 
1405
   continue;
 
1406
     ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
 
1407
                          (off_t) 0, (off_t) 0, 2 << 7);
 
1408
     if(ret <= 0) {
 
1409
       (*problem_count)++;
 
1410
       hret= Xorriso_eval_problem_status(xorriso, ret, 0);
 
1411
       if(hret < 0)
 
1412
         goto ex;
 
1413
     }
 
1414
   }
 
1415
 }
 
1416
 
 
1417
 /* Perform restore operations */
 
1418
 if(xorriso->do_restore_sort_lba) {
 
1419
   ret= Xorriso_restore_node_array(xorriso, 0);
 
1420
   if(ret <= 0)
 
1421
     goto ex;
 
1422
 } else {
 
1423
   for(i= 0; i < count; i++) {
 
1424
     if(src_array[i] == NULL || tgt_array[i] == NULL)
 
1425
   continue;
 
1426
     ret= Xorriso_restore(xorriso, src_array[i], tgt_array[i],
 
1427
                          (off_t) 0, (off_t) 0, 0);
 
1428
     if(ret <= 0) {
 
1429
       (*problem_count)++;
 
1430
       hret= Xorriso_eval_problem_status(xorriso, ret, flag & 32);
 
1431
       if(ret < 0)
 
1432
         goto ex;
 
1433
     }
 
1434
   }
 
1435
 }
 
1436
 
 
1437
 ret= 1;
 
1438
ex:;
 
1439
 return(ret);
 
1440
}
 
1441
 
 
1442
 
 
1443
/* @param flag bit0= path is a directory
 
1444
               bit2= recursion: do not reassure in mode 2 "tree"
 
1445
               bit3= this is for overwriting and not for plain removal
 
1446
*/
 
1447
int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag)
 
1448
{
 
1449
 int ret;
 
1450
 char sfe[5*SfileadrL];
 
1451
 
 
1452
 while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4)))
 
1453
       && !xorriso->request_not_to_ask) {
 
1454
   /* ls -ld */
 
1455
   Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 1|2|8);
 
1456
   if(flag&1) /* du -s */
 
1457
     Xorriso_lsx_filev(xorriso, xorriso->wdx, 1, &path, (off_t) 0, 2|4);
 
1458
   if(flag&8)
 
1459
     sprintf(xorriso->info_text,
 
1460
  "File exists. Remove ?  n= keep old, y= remove, x= abort, @= stop asking\n");
 
1461
   else
 
1462
     sprintf(xorriso->info_text,
 
1463
  "Remove above file ?  n= keep it, y= remove it, x= abort, @= stop asking\n");
 
1464
   Xorriso_info(xorriso, 4);
 
1465
   ret= Xorriso_request_confirmation(xorriso, 1|2|4|16);
 
1466
   if(ret<=0)
 
1467
     goto ex;
 
1468
   if(xorriso->request_to_abort) {
 
1469
     sprintf(xorriso->info_text,
 
1470
             "Removal operation aborted by user before file: %s",
 
1471
             Text_shellsafe(path, sfe, 0));
 
1472
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 
1473
     ret= 3; goto ex;
 
1474
   }
 
1475
   if(ret==3)
 
1476
 continue;
 
1477
   if(ret==6) /* yes */
 
1478
 break;
 
1479
   if(ret==4) { /* yes, do not ask again */
 
1480
     xorriso->request_not_to_ask= 1;
 
1481
 break;
 
1482
   }
 
1483
   if(ret==1) { /* no */
 
1484
     sprintf(xorriso->info_text, "Kept in existing state: %s",
 
1485
             Text_shellsafe(path, sfe, 0));
 
1486
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
 
1487
     ret= 3; goto ex;
 
1488
   }
 
1489
 }
 
1490
 ret= 1;
 
1491
ex:
 
1492
 return(ret);
 
1493
}
 
1494
 
 
1495
 
 
1496
/* @param flag bit7= return 4 if restore fails from denied permission
 
1497
                     do not issue error message
 
1498
   @return <=0 failure , 1 success ,
 
1499
           4 with bit7: permission to  create file was denied
 
1500
*/
 
1501
int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path,
 
1502
                          char *tmp_path, int *fd, int flag)
 
1503
{
 
1504
 char *cpt;
 
1505
 
 
1506
 cpt= strrchr(orig_path, '/');
 
1507
 if(cpt==NULL)
 
1508
   tmp_path[0]= 0;
 
1509
 else {
 
1510
   strncpy(tmp_path, orig_path, cpt+1-orig_path);
 
1511
   tmp_path[cpt+1-orig_path]= 0;
 
1512
 }
 
1513
 strcat(tmp_path, "_tmp_xorriso_restore_XXXXXX");
 
1514
 *fd= mkstemp(tmp_path);
 
1515
 if(*fd==-1) {
 
1516
   if(errno == EACCES && (flag & 128))
 
1517
     return(4);
 
1518
   strcpy(xorriso->info_text, "Cannot create temporary file : ");
 
1519
   Text_shellsafe(tmp_path, xorriso->info_text, 1);
 
1520
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 
1521
   return(0);
 
1522
 }
 
1523
 fchmod(*fd, S_IRUSR|S_IWUSR);
 
1524
 return(1);
 
1525
}
 
1526
 
 
1527
 
 
1528
/* @param flag bit0= change regardless of xorriso->do_auto_chmod
 
1529
               bit1= desired is only rx
 
1530
   @return -1=severe error , -2= cannot chmod, 0= nothing to do, 1 = chmoded
 
1531
*/
 
1532
int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag)
 
1533
{
 
1534
 int ret, is_link= 0;
 
1535
 char *path_pt, sfe[5*SfileadrL], link_target[SfileadrL];
 
1536
 mode_t mode, desired= S_IRUSR | S_IWUSR | S_IXUSR;
 
1537
 struct stat stbuf;
 
1538
 
 
1539
 if(!(xorriso->do_auto_chmod || (flag & 1)))
 
1540
   return(0);
 
1541
 
 
1542
 if(flag & 2)
 
1543
   desired &= ~S_IWUSR;
 
1544
 path_pt= disk_path;
 
1545
 ret= lstat(path_pt, &stbuf);
 
1546
 if(ret==-1)
 
1547
   return(0);
 
1548
 if(S_ISLNK(stbuf.st_mode)) {
 
1549
   is_link= 1;
 
1550
   ret= stat(path_pt, &stbuf);
 
1551
   if(ret==-1)
 
1552
     return(0);
 
1553
 }
 
1554
 if(!S_ISDIR(stbuf.st_mode))
 
1555
   return(0);
 
1556
 if(is_link) {
 
1557
   ret= Xorriso_resolve_link(xorriso, path_pt, link_target, 0);
 
1558
   if(ret<=0)
 
1559
     return(ret);
 
1560
   path_pt= link_target;
 
1561
 }
 
1562
 if((stbuf.st_mode & desired) == desired)
 
1563
   return(0);
 
1564
 if(stbuf.st_uid!=geteuid())
 
1565
   return(-2);
 
1566
 
 
1567
 mode= (stbuf.st_mode | desired) & 07777;
 
1568
 ret= chmod(path_pt, mode);
 
1569
 if(ret==-1) {
 
1570
   sprintf(xorriso->info_text,
 
1571
           "Cannot change access permissions of disk directory: chmod %o %s",
 
1572
           (unsigned int) (mode & 07777), Text_shellsafe(path_pt, sfe, 0));
 
1573
   Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0);
 
1574
   return(-2);
 
1575
 }
 
1576
 ret= Permstack_push(&(xorriso->perm_stack), path_pt, &stbuf, 0);
 
1577
 if(ret<=0)
 
1578
   return(ret);
 
1579
 return(1);
 
1580
}
 
1581
 
 
1582
 
 
1583
int Xorriso_make_accessible(struct XorrisO *xorriso, char *disk_path, int flag)
 
1584
{
 
1585
 int done= 0, ret, just_rx= 2;
 
1586
 char *npt, *apt, path[SfileadrL], *wpt;
 
1587
 
 
1588
 apt= disk_path;
 
1589
 wpt= path;
 
1590
 for(npt= apt; !done; apt= npt + 1) {
 
1591
   npt= strchr(apt, '/');
 
1592
   if(npt == NULL)
 
1593
 break;
 
1594
   if(strchr(npt + 1, '/') == NULL)
 
1595
     just_rx= 0;
 
1596
   strncpy(wpt, apt, npt + 1 - apt);
 
1597
   wpt+= npt + 1 - apt;
 
1598
   *wpt= 0;
 
1599
   ret= Xorriso_auto_chmod(xorriso, path, just_rx);
 
1600
   if(ret == -1)
 
1601
     return(-1);
 
1602
   if(ret == -2)
 
1603
     return(0);
 
1604
 }
 
1605
 return(1);
 
1606
}
 
1607
 
 
1608
 
 
1609
/* @param flag bit0= prefer to find a match after *img_prefixes
 
1610
                     (but deliver img_prefixes if no other can be found)
 
1611
*/
 
1612
int Xorriso_make_restore_path(struct XorrisO *xorriso,
 
1613
         struct Xorriso_lsT **img_prefixes, struct Xorriso_lsT **disk_prefixes,
 
1614
         char img_path[SfileadrL], char disk_path[SfileadrL], int flag)
 
1615
{
 
1616
 int li;
 
1617
 struct Xorriso_lsT *s, *d, *found_s= NULL, *found_d= NULL;
 
1618
 char *ipfx, *dpfx;
 
1619
 
 
1620
 /* Obtain disk_path by replacing start piece of img_path */
 
1621
 
 
1622
 d= *disk_prefixes;
 
1623
 for(s= *img_prefixes; s != NULL;
 
1624
     s= Xorriso_lst_get_next(s, 0), d= Xorriso_lst_get_next(d, 0)) {
 
1625
 
 
1626
   ipfx= Xorriso_lst_get_text(s, 0);
 
1627
   li= strlen(ipfx);
 
1628
   dpfx= Xorriso_lst_get_text(d, 0);
 
1629
   if(strncmp(img_path, ipfx, li) != 0)
 
1630
 continue;
 
1631
   if(img_path[li] != 0 && img_path[li] != '/')
 
1632
 continue;
 
1633
   if(strlen(dpfx) + strlen(img_path) - li + 1 >= SfileadrL)
 
1634
     return(-1);
 
1635
   if(img_path[li]=='/')
 
1636
     sprintf(disk_path, "%s/%s", dpfx, img_path + strlen(ipfx) + 1);
 
1637
   else
 
1638
     strcpy(disk_path, dpfx);
 
1639
   found_s= s;
 
1640
   found_d= d;
 
1641
   if(s != *img_prefixes || !(flag & 1))
 
1642
 break;
 
1643
 }
 
1644
 *img_prefixes= found_s;
 
1645
 *disk_prefixes= found_d;
 
1646
 return(found_s != NULL);
 
1647
}
 
1648
 
 
1649
 
 
1650
/* @param flag bit0=permission to run Xorriso_make_accessible
 
1651
*/
 
1652
int Xorriso_restore_make_hl(struct XorrisO *xorriso,
 
1653
                            char *old_path, char *new_path, int flag)
 
1654
{
 
1655
 int ret;
 
1656
 struct PermiteM *perm_stack_mem;
 
1657
 
 
1658
 ret= link(old_path, new_path);
 
1659
 if(ret == 0)
 
1660
   return(1);
 
1661
 if(errno == EACCES && (flag & 1)) {
 
1662
   perm_stack_mem= xorriso->perm_stack;
 
1663
   ret= Xorriso_make_accessible(xorriso, new_path, 0);
 
1664
   if(ret > 0) {
 
1665
      ret= link(old_path, new_path);
 
1666
      if(ret == 0) {
 
1667
        Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 
1668
        return(1);
 
1669
      }
 
1670
   }
 
1671
   Permstack_pop(&(xorriso->perm_stack), perm_stack_mem, xorriso, 0);
 
1672
 }
 
1673
 
 
1674
 sprintf(xorriso->info_text, "Hardlinking failed: ");
 
1675
 Text_shellsafe(new_path, xorriso->info_text, 1);
 
1676
 strcat(xorriso->info_text, " -> ");
 
1677
 Text_shellsafe(old_path, xorriso->info_text, 1);
 
1678
 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "WARNING", 0);
 
1679
 return(0);
 
1680
}
 
1681
 
 
1682
 
 
1683
int Xorriso_afile_fopen(struct XorrisO *xorriso,
 
1684
                        char *filename, char *mode, FILE **ret_fp, int flag)
 
1685
/*
 
1686
 bit0= do not print error message on failure
 
1687
 bit1= do not open stdin
 
1688
*/
 
1689
{
 
1690
 FILE *fp= NULL;
 
1691
 
 
1692
 *ret_fp= NULL;
 
1693
 if(strcmp(filename,"-")==0) {
 
1694
   if(mode[0]=='a' || mode[0]=='w' ||
 
1695
      (mode[0]=='r' && mode[1]=='+') ||
 
1696
      (mode[0]=='r' && mode[1]=='b' && mode[2]=='+')) 
 
1697
     fp= stdout;
 
1698
   else if(flag & 2) {
 
1699
     Xorriso_msgs_submit(xorriso, 0, "Not allowed as input path: '-'", 0,
 
1700
                       "FAILURE", 0);
 
1701
     return(0);
 
1702
   } else {
 
1703
     Xorriso_msgs_submit(xorriso, 0, "Ready for data at standard input", 0,
 
1704
                         "NOTE", 0);
 
1705
     fp= stdin;
 
1706
   }
 
1707
 } else if(strncmp(filename,"tcp:",4)==0){
 
1708
   Xorriso_msgs_submit(xorriso, 0, "TCP/IP service isn't implemented yet.", 0,
 
1709
                       "FAILURE", 0);
 
1710
 } else if(strncmp(filename,"file:",5)==0){
 
1711
   fp= fopen(filename+5,mode);
 
1712
 } else {
 
1713
   fp= fopen(filename,mode);
 
1714
 }
 
1715
 if(fp==NULL){
 
1716
   if(!(flag&1)) {
 
1717
     sprintf(xorriso->info_text,
 
1718
             "Failed to open file '%s' in %s mode\n", filename, mode);
 
1719
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
 
1720
   }
 
1721
   return(0);
 
1722
 }
 
1723
 *ret_fp= fp;
 
1724
 return(1);
 
1725
}
 
1726
 
 
1727
 
 
1728
/*
 
1729
   @param flag bit0= make absolute command paths with known systems
 
1730
               bit1= do not allow prefixes with cmd
 
1731
               bit2= interpret unprefixed cmd as shell:
 
1732
*/
 
1733
int Xorriso_make_mount_cmd(struct XorrisO *xorriso, char *cmd,
 
1734
                           int lba, int track, int session, char *volid,
 
1735
                           char *devadr, char result[SfileadrL], int flag)
 
1736
{
 
1737
 int ret, reg_file= 0, is_safe= 0, sys_code= 0;
 
1738
 char form[6*SfileadrL], session_text[12], track_text[12], lba_text[12];
 
1739
 char *vars[5][2], sfe[5*SfileadrL], volid_sfe[5*80+1], *cpt, *sysname;
 
1740
 struct stat stbuf;
 
1741
 
 
1742
 if(strlen(cmd) > SfileadrL) {
 
1743
/*
 
1744
too_long:;
 
1745
*/
 
1746
   Xorriso_msgs_submit(xorriso, 0, "Argument much too long", 0, "FAILURE", 0);
 
1747
   return(0);
 
1748
 }
 
1749
 ret= stat(devadr, &stbuf);
 
1750
 if(ret != -1)
 
1751
   if(S_ISREG(stbuf.st_mode))
 
1752
     reg_file= 1;
 
1753
 if(strncmp(cmd, "linux:", 6) == 0 && !(flag & 2)) {
 
1754
   cpt= cmd + 6;
 
1755
   sys_code= 1;
 
1756
 } else if(strncmp(cmd, "freebsd:", 8) == 0 && !(flag & 2)) {
 
1757
   cpt= cmd + 8;
 
1758
   sys_code= 2;
 
1759
 } else if(strncmp(cmd, "string:", 7) == 0 && !(flag & 2)) {
 
1760
   cpt= cmd + 7;
 
1761
   strcpy(form, cpt);
 
1762
 } else if(flag & 4) {
 
1763
   cpt= cmd;
 
1764
   strcpy(form, cpt);
 
1765
 } else {
 
1766
   cpt= cmd;
 
1767
   ret= System_uname(&sysname, NULL, NULL, NULL, 0);
 
1768
   if(ret <= 0) {
 
1769
     Xorriso_msgs_submit(xorriso, 0,
 
1770
                         "-mount*: Cannot determine current system type",
 
1771
                         0, "FAILURE", 0);
 
1772
     return(0);
 
1773
   } else if(strcmp(sysname, "FreeBSD") == 0 ||
 
1774
             strcmp(sysname, "GNU/kFreeBSD") == 0) {
 
1775
                                         /* "GNU/kFreeBSD" = Debian kfreebsd */
 
1776
     sys_code= 2;
 
1777
   } else if(strcmp(sysname, "Linux") == 0) {
 
1778
     sys_code= 1;
 
1779
   } else {
 
1780
     sprintf(xorriso->info_text, "-mount*: Unsupported system type %s",
 
1781
             Text_shellsafe(sysname, sfe, 0));
 
1782
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 
1783
     return(0);
 
1784
   }
 
1785
 }
 
1786
 
 
1787
 if(sys_code == 1) { /* GNU/Linux */
 
1788
   sprintf(form,
 
1789
           "%smount -t iso9660 -o %snodev,noexec,nosuid,ro,sbsector=%%sbsector%% %%device%% %s",
 
1790
           (flag & 1 ? "/bin/" : ""),
 
1791
           (reg_file || (xorriso->mount_opts_flag & 1) ? "loop," : ""),
 
1792
           Text_shellsafe(cpt, sfe, 0));
 
1793
   is_safe= 1;
 
1794
 } else if(sys_code == 2) { /* FreeBSD */
 
1795
   if(reg_file) {
 
1796
 
 
1797
/*  <<< Considered to create vnode as of
 
1798
        J.R. Oldroyd <fbsd@opal.com>, 20 Nov 2008
 
1799
        but for now refraining from creating that persistent file object
 
1800
 
 
1801
     strcpy(form, "n=$(mdconfig -a -t vnode -f %device%)");
 
1802
     sprintf(form + strlen(form),
 
1803
         " && mount -t cd9660 -o noexec,nosuid -s %%sbsector%% /dev/\"$n\" %s",
 
1804
         Text_shellsafe(cmd+8, sfe, 0));
 
1805
*/
 
1806
 
 
1807
     Xorriso_msgs_submit(xorriso, 0, 
 
1808
           "Detected regular file as mount device with FreeBSD style command.",
 
1809
           0, "FAILURE", 0);
 
1810
     Xorriso_msgs_submit(xorriso, 0,
 
1811
"Command mdconfig -a -t vnode -f can create a device node which uses the file",
 
1812
                         0, "HINT", 0);
 
1813
     return(0);
 
1814
   } else {
 
1815
     sprintf(form,
 
1816
         "%smount_cd9660 -o noexec,nosuid -s %%sbsector%% %%device%% %s",
 
1817
         (flag & 1 ? "/sbin/" : ""), Text_shellsafe(cmd+8, sfe, 0));
 
1818
     /*
 
1819
       Not working on FreeBSD 7.2 according to Zsolt Kuti, 11 Oct 2009:
 
1820
         "%smount -t cd9660 -o noexec,nosuid -o -s %%sbsector%% %%device%% %s",
 
1821
     */
 
1822
   }
 
1823
   is_safe= 1;
 
1824
 }
 
1825
 sprintf(session_text, "%d", session);
 
1826
 sprintf(track_text, "%d", track);
 
1827
 sprintf(lba_text, "%d", lba);
 
1828
 vars[0][0]= "sbsector";
 
1829
 vars[0][1]= lba_text;
 
1830
 vars[1][0]= "track";
 
1831
 vars[1][1]= track_text;
 
1832
 vars[2][0]= "session";
 
1833
 vars[2][1]= session_text;
 
1834
 vars[3][0]= "volid";
 
1835
 vars[3][1]= Text_shellsafe(volid, volid_sfe, 0);
 
1836
 vars[4][0]= "device";
 
1837
 vars[4][1]= Text_shellsafe(devadr, sfe, 0);
 
1838
 ret= Sregex_resolve_var(form, vars, 5, "%", "%", "%", result, SfileadrL, 0);
 
1839
 if(ret <= 0)
 
1840
   return(ret);
 
1841
 return(1 + is_safe);
 
1842
}
 
1843
 
 
1844
 
 
1845
int Xorriso_append_scdbackup_record(struct XorrisO *xorriso, int flag)
 
1846
{
 
1847
 FILE *fp= NULL;
 
1848
 char dummy[81], name[81], timestamp[81], size[81], md5[81];
 
1849
 
 
1850
 if(xorriso->scdbackup_tag_written[0] == 0)
 
1851
   return(1);
 
1852
 
 
1853
 name[0]= timestamp[0]= size[0]= md5[0]= 0;
 
1854
 sscanf(xorriso->scdbackup_tag_written, "%s %s %s %s %s %s %s",
 
1855
        dummy, dummy, dummy, name, timestamp, size, md5);
 
1856
 sprintf(xorriso->info_text, "scdbackup tag written : %s %s %s %s\n",
 
1857
         name, timestamp, size, md5);
 
1858
 Xorriso_msgs_submit(xorriso, 0,  xorriso->info_text, 0, "NOTE", 0);
 
1859
 
 
1860
 if(xorriso->scdbackup_tag_listname[0]) {
 
1861
   fp= fopen(xorriso->scdbackup_tag_listname, "a");
 
1862
   if(fp==0) {
 
1863
     strcpy(xorriso->info_text, "-scdbackup_tag: Cannot open file ");
 
1864
     Text_shellsafe(xorriso->scdbackup_tag_listname, xorriso->info_text, 1);
 
1865
     Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
 
1866
     return(0);
 
1867
   }
 
1868
   fprintf(fp, "%s %s %s %s\n", name, timestamp, size, md5);
 
1869
   fclose(fp);
 
1870
 }
 
1871
 return(1);
 
1872
}
 
1873