"Fossies" - the Fresh Open Source Software Archive 
Member "xorriso-1.5.4/xorriso/iso_manip.c" (30 Jan 2021, 144132 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "iso_manip.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.5.2_vs_1.5.4.
1
2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
3
4 Copyright 2007-2019 Thomas Schmitt, <scdbackup@gmx.net>
5
6 Provided under GPL version 2 or later.
7
8 This file contains functions which manipulate the libisofs tree model.
9 */
10
11 #ifdef HAVE_CONFIG_H
12 #include "../config.h"
13 #endif
14
15 #include <ctype.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/stat.h>
22 #include <sys/time.h>
23 #include <time.h>
24 #include <errno.h>
25
26
27 #include "xorriso.h"
28 #include "xorriso_private.h"
29 #include "xorrisoburn.h"
30
31 #include "lib_mgt.h"
32 #include "iso_img.h"
33 #include "iso_tree.h"
34 #include "iso_img.h"
35 #include "iso_manip.h"
36 #include "sort_cmp.h"
37 #include "parse_exec.h"
38 #include "write_run.h"
39
40
41
42 /* @param flag bit0= give directory x-permission where is r-permission
43 bit1= do not transfer ACL or xattr
44 bit2= record dev,inode (only if enabled by xorriso)
45 bit3= with bit0: pretend to have indeed a directory
46 bit5= transfer ACL or xattr from eventual link target
47 */
48 int Xorriso_transfer_properties(struct XorrisO *xorriso, struct stat *stbuf,
49 char *disk_path, IsoNode *node, int flag)
50 {
51 mode_t mode;
52 int ret= 1;
53 size_t num_attrs= 0, *value_lengths= NULL;
54 char **names= NULL, **values= NULL;
55
56 mode= stbuf->st_mode;
57
58 if((!(flag & 2)) && !(xorriso->do_aaip & 1))
59 /* Will drop ACL. Update mode S_IRWXG by eventual group:: ACL entry */
60 iso_local_get_perms_wo_acl(disk_path, &mode, flag & 32);
61
62 if((flag & 1) && ((flag & 8) || S_ISDIR(mode))) {
63 if(mode&S_IRUSR)
64 mode|= S_IXUSR;
65 if(mode&S_IRGRP)
66 mode|= S_IXGRP;
67 if(mode&S_IROTH)
68 mode|= S_IXOTH;
69 }
70 iso_node_set_permissions(node, mode & 07777);
71 iso_node_set_uid(node, stbuf->st_uid);
72 iso_node_set_gid(node, stbuf->st_gid);
73 iso_node_set_atime(node, stbuf->st_atime);
74 iso_node_set_mtime(node, stbuf->st_mtime);
75 iso_node_set_ctime(node, stbuf->st_ctime);
76
77 if((xorriso->do_aaip & 5) && !(flag & 2)) {
78 ret= iso_local_get_attrs(disk_path, &num_attrs, &names, &value_lengths,
79 &values, ((xorriso->do_aaip & 1) && !(flag & 2))
80 | ((!(xorriso->do_aaip & 4)) << 2)
81 | (flag & 32));
82 if(ret < 0) {
83 Xorriso_process_msg_queues(xorriso,0);
84 Xorriso_report_iso_error(xorriso, disk_path, ret,
85 "Error when obtaining local ACL and xattr", 0,
86 "FAILURE", 1 | 2);
87 ret= 0; goto ex;
88 }
89
90 /* Preserve namespace isofs, but not ACL or system xattr */
91 ret= iso_node_set_attrs(node, num_attrs, names, value_lengths, values,
92 1 | 8 | 16);
93 if(ret < 0) {
94 Xorriso_process_msg_queues(xorriso,0);
95 Xorriso_report_iso_error(xorriso, "", ret,
96 "Error when setting ACL and xattr to image node",
97 0, "FAILURE", 1);
98 ret= 0; goto ex;
99 }
100 }
101
102 if((flag & 4) && ((xorriso->do_aaip & 16) || !(xorriso->ino_behavior & 2))) {
103 ret= Xorriso_record_dev_inode(xorriso, disk_path, (dev_t) 0, (ino_t) 0,
104 (void *) node, "", flag & 32);
105 if(ret <= 0)
106 goto ex;
107 }
108
109 ret= 1;
110 ex:;
111 Xorriso_process_msg_queues(xorriso,0);
112 iso_local_get_attrs(disk_path, &num_attrs, &names, &value_lengths,
113 &values, 1 << 15); /* free memory */
114 return(ret);
115 }
116
117
118 int Xorriso_graft_split(struct XorrisO *xorriso, IsoImage *volume,
119 IsoDir *dir, char *disk_path, char *img_name,
120 char *nominal_source, char *nominal_target,
121 off_t size, IsoNode **node, int flag)
122 {
123 int ret;
124 IsoDir *new_dir= NULL;
125 IsoNode *part_node;
126 int partno, total_parts;
127 off_t offset;
128 char *part_name= NULL;
129
130 Xorriso_alloc_meM(part_name, char, SfileadrL);
131
132 ret= iso_image_add_new_dir(volume, dir, img_name, &new_dir);
133 if(ret < 0)
134 goto ex;
135 *node= (IsoNode *) new_dir;
136 if(xorriso->update_flags & 1) {
137 ret= Xorriso_mark_update_merge(xorriso, img_name, node, 1);
138 if(ret <= 0)
139 {ret= 0; goto ex;}
140 }
141 total_parts= size / xorriso->split_size;
142 if(size % xorriso->split_size)
143 total_parts++;
144 for(partno= 1; partno<=total_parts; partno++) {
145 offset = xorriso->split_size * (off_t) (partno-1);
146 Splitpart__compose(part_name, partno, total_parts, offset,
147 xorriso->split_size, size, 0);
148 ret= Xorriso_tree_graft_node(xorriso, volume,
149 new_dir, disk_path, part_name,
150 nominal_source, nominal_target,
151 offset, xorriso->split_size,
152 &part_node, 8);
153 if(ret<=0)
154 goto ex;
155 }
156 sprintf(xorriso->info_text, "Split into %d parts: ", total_parts);
157 Text_shellsafe(nominal_target, xorriso->info_text, 1);
158 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
159 ret= 1;
160 ex:;
161 Xorriso_free_meM(part_name);
162 return(ret);
163 }
164
165
166 /*
167 @param flag bit0= ISO_NODE_NAME_NOT_UNIQUE exception mode:
168 Do not issue message. Return existing node into *node.
169 bit1= if name truncation happens: copy truncated into img_name
170 bit3= cut_out_node: offset and size are valid
171 bit8= hide in iso_rr
172 bit9= hide in joliet
173 bit10= hide in hfsplus
174 */
175 int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume,
176 IsoDir *dir, char *disk_path, char *img_name,
177 char *nominal_source, char *nominal_target,
178 off_t offset, off_t cut_size,
179 IsoNode **node, int flag)
180 {
181 int ret, stbuf_valid= 0;
182 struct stat stbuf;
183 char *namept, *eff_name, *trunc_name= NULL;
184 off_t size= 0;
185
186 eff_name= img_name;
187 if(lstat(disk_path, &stbuf) != -1) {
188 stbuf_valid= 1;
189 if(S_ISREG(stbuf.st_mode))
190 size= stbuf.st_size;
191 }
192 if((int) strlen(eff_name) > xorriso->file_name_limit) {
193 Xorriso_alloc_meM(trunc_name, char, SfileadrL);
194 strncpy(trunc_name, eff_name, SfileadrL - 1);
195 trunc_name[SfileadrL - 1]= 0;
196 ret= iso_truncate_leaf_name(1, xorriso->file_name_limit, trunc_name, 0);
197 if(ret < 0)
198 goto ex;
199 strcpy(xorriso->info_text, "File name had to be truncated and MD5 marked: ");
200 Text_shellsafe(eff_name, xorriso->info_text, 1);
201 strcat(xorriso->info_text, " -> ");
202 Text_shellsafe(trunc_name, xorriso->info_text, 1);
203 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
204 eff_name= trunc_name;
205 if(flag & 2)
206 strcpy(img_name, trunc_name);
207 }
208 if(flag&8) {
209 if(cut_size > xorriso->file_size_limit && xorriso->file_size_limit > 0) {
210 sprintf(xorriso->info_text,
211 "File piece exceeds size limit of %.f bytes: %.f from ",
212 (double) xorriso->file_size_limit, (double) cut_size);
213 Text_shellsafe(disk_path, xorriso->info_text, 1);
214 strcat(xorriso->info_text, "\n");
215 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
216 return(0);
217 }
218 ret= iso_tree_add_new_cut_out_node(volume, dir, eff_name, disk_path,
219 offset, cut_size, node);
220 if(ret<0)
221 goto ex;
222 } else {
223 if(xorriso->split_size > 0 && size > xorriso->split_size) {
224 ret= Xorriso_graft_split(xorriso, volume, dir, disk_path, eff_name,
225 nominal_source, nominal_target, size,
226 node, 0);
227 if(ret<=0)
228 goto ex;
229 } else if(size > xorriso->file_size_limit && xorriso->file_size_limit > 0) {
230 sprintf(xorriso->info_text,
231 "File exceeds size limit of %.f bytes: ",
232 (double) xorriso->file_size_limit);
233 Text_shellsafe(disk_path, xorriso->info_text, 1);
234 strcat(xorriso->info_text, "\n");
235 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
236 return(0);
237 } else {
238 ret= iso_tree_add_new_node(volume, dir, eff_name, disk_path, node);
239 if(ret<0)
240 goto ex;
241 }
242 }
243 if(flag & (256 | 512 | 1024)) {
244 ret= Xorriso_set_hidden(xorriso, (void *) *node, "", (flag >> 8) & 7, 0);
245 if(ret <= 0)
246 goto ex;
247 }
248 if(stbuf_valid && ((xorriso->do_aaip & 16) || !(xorriso->ino_behavior & 2))) {
249 ret= Xorriso_record_dev_inode(xorriso, disk_path,
250 stbuf.st_dev, stbuf.st_ino, (void *) *node, "", 1);
251 if(ret <= 0)
252 goto ex;
253 }
254 if(xorriso->update_flags & 1) {
255 ret= Xorriso_mark_update_merge(xorriso, eff_name, *node, 1);
256 if(ret <= 0)
257 goto ex;
258 }
259
260 ex:;
261 if(ret<0) {
262 if(ret == (int) ISO_NODE_NAME_NOT_UNIQUE && (flag & 1)) {
263 iso_image_dir_get_node(volume, dir, eff_name, node, 0);
264 } else {
265 Xorriso_process_msg_queues(xorriso,0);
266 if(ret == (int) ISO_RR_NAME_TOO_LONG ||
267 ret == (int) ISO_RR_NAME_RESERVED ||
268 ret == (int) ISO_RR_PATH_TOO_LONG)
269 namept= nominal_target;
270 else
271 namept= nominal_source;
272 Xorriso_report_iso_error(xorriso, namept, ret,
273 "Cannot add node to tree", 0, "FAILURE", 1|2);
274 }
275 } else {
276 if(LIBISO_ISREG(*node))
277 xorriso->pacifier_byte_count+= iso_file_get_size((IsoFile *) *node);
278 ret= 1;
279 }
280 Xorriso_free_meM(trunc_name);
281 return(ret);
282 }
283
284
285 /*
286 @param boss_iter Opaque handle to be forwarded to actions in ISO image
287 Set to NULL if calling this function without having
288 a boss iterator object.
289 @param node Pointer to pointer to existing node,
290 *node is set to NULL, if the node gets removed.
291 @param flag bit0= source is directory
292 bit4= return 3 on rejection by exclusion or user
293 bit6= do not delete eventually existing node from di_array
294 bit7= no special handling of split file directories
295 @return 1= no action was needed, 2= target removed,
296 3= rejected with bit4, <=0 means error
297 */
298 int Xoriso_handle_collision(struct XorrisO *xorriso, void *boss_iter,
299 IsoNode **node, char *img_path,
300 char *full_img_path, char *disk_path,
301 char *show_path, int flag)
302 {
303 int ret, target_is_dir, target_is_split, source_is_dir;
304
305 source_is_dir= flag & 1;
306 target_is_dir= LIBISO_ISDIR(*node);
307
308 target_is_split= 0;
309 if(target_is_dir && !(flag & 128))
310 target_is_split= Xorriso_is_split(xorriso, "", (void *) *node, 1 | 2);
311
312 if(!((target_is_dir && !target_is_split) && source_is_dir)) {
313 Xorriso_process_msg_queues(xorriso, 0);
314
315 /* handle overwrite situation */;
316 if(xorriso->do_overwrite == 1 ||
317 (xorriso->do_overwrite == 2 && !(target_is_dir && !target_is_split))) {
318 ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, img_path,
319 1 | 8 | (flag & 64));
320 if(ret <= 0)
321 return(ret);
322 if(ret == 3) {
323 sprintf(xorriso->info_text, "User revoked adding of: ");
324 Text_shellsafe(show_path, xorriso->info_text, 1);
325 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
326 return(3 * !!(flag & 16));
327 }
328 *node= NULL;
329 return(2);
330 }
331
332 if (disk_path[0])
333 Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
334 if(strcmp(full_img_path, img_path) == 0)
335 sprintf(xorriso->info_text,
336 "While grafting '%s' : file object exists and may not be overwritten",
337 img_path);
338 else
339 sprintf(xorriso->info_text,
340 "While grafting '%s' : '%s' exists and may not be overwritten",
341 full_img_path, img_path);
342 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
343 return(0);
344 }
345 return(1);
346 }
347
348
349 /* @param flag bit0= recursion is active
350 bit1= do not report added files
351 bit6= do not delete eventually existing node from di_array
352 bit7= no special handling of split file directories
353 bit8= hide in iso_rr
354 bit9= hide in joliet
355 */
356 int Xorriso_add_tree(struct XorrisO *xorriso, IsoDir *dir,
357 char *img_dir_path, char *disk_dir_path,
358 struct LinkiteM *link_stack, int flag)
359 {
360 IsoImage *volume;
361 IsoNode *node;
362 int ret, source_is_dir, source_is_link, fret, was_failure= 0;
363 int do_not_dive, hide_attrs;
364 struct DirseQ *dirseq= NULL;
365 char *name, *img_name, *srcpt, *stbuf_src= "";
366 struct stat stbuf, hstbuf;
367 dev_t dir_dev;
368 struct LinkiteM *own_link_stack = NULL;
369 char *sfe= NULL, *sfe2= NULL;
370 char *disk_path= NULL, *img_path= NULL, *link_target= NULL;
371
372 #define Xorriso_add_handle_collisioN 1
373 #define Xorriso_optimistic_add_treE 1
374
375 #ifndef Xorriso_optimistic_add_treE
376 #ifndef Xorriso_add_handle_collisioN
377 int target_is_split= 0, target_is_dir;
378 #endif
379 #endif
380
381 /* Avoiding large local memory objects in order to save stack space */
382 sfe= malloc(5*SfileadrL);
383 sfe2= malloc(5*SfileadrL);
384 disk_path= malloc(2*SfileadrL);
385 img_path= malloc(2*SfileadrL);
386 link_target= calloc(SfileadrL, 1);
387 if(sfe==NULL || sfe2==NULL || disk_path==NULL || img_path==NULL ||
388 link_target==NULL) {
389 Xorriso_no_malloc_memory(xorriso, &sfe, 0);
390 {ret= -1; goto ex;}
391 }
392
393 own_link_stack= link_stack;
394
395 ret= Xorriso_get_volume(xorriso, &volume, 0);
396 if(ret<=0)
397 goto ex;
398
399 stbuf_src= disk_dir_path;
400 if(lstat(disk_dir_path, &stbuf)==-1)
401 goto cannot_open_dir;
402 dir_dev= stbuf.st_dev;
403 if(S_ISLNK(stbuf.st_mode)) {
404 if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
405 {ret= 2; goto ex;}
406 stbuf_src= disk_dir_path;
407 if(stat(disk_dir_path, &stbuf)==-1)
408 goto cannot_open_dir;
409 if(dir_dev != stbuf.st_dev &&
410 !(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1))))
411 {ret= 2; goto ex;}
412 }
413 ret= Dirseq_new(&dirseq, disk_dir_path, 1);
414 if(ret<0) {
415 sprintf(xorriso->info_text,"Failed to create source filesystem iterator");
416 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
417 {ret= -1; goto ex;}
418 }
419 if(ret==0) {
420 cannot_open_dir:;
421 Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0);
422 sprintf(xorriso->info_text,"Cannot open as source directory: %s",
423 Text_shellsafe(disk_dir_path, sfe, 0));
424 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
425 {ret= 0; goto ex;}
426 }
427
428 if(Sfile_str(disk_path, disk_dir_path,0)<=0)
429 {ret= -1; goto ex;}
430 if(disk_path[0]==0 || disk_path[strlen(disk_path)-1]!='/')
431 strcat(disk_path,"/");
432 name= disk_path+strlen(disk_path);
433 if(Sfile_str(img_path, img_dir_path, 0)<=0)
434 {ret= -1; goto ex;}
435 if(img_path[0] == 0)
436 strcat(img_path, "/");
437 else if(img_path[strlen(img_path) - 1] != '/')
438 strcat(img_path, "/");
439 img_name= img_path+strlen(img_path);
440
441 while(1) { /* loop over directory content */
442 stbuf_src= "";
443 Linkitem_reset_stack(&own_link_stack, link_stack, 0);
444 srcpt= disk_path;
445 Xorriso_process_msg_queues(xorriso,0);
446 ret= Dirseq_next_adr(dirseq,name,0); /* name is a pointer into disk_path */
447 if(ret==0)
448 break;
449 if(ret<0) {
450 sprintf(xorriso->info_text,"Failed to obtain next directory entry");
451 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
452 {ret= -1; goto ex;}
453 }
454
455 /* Compare exclusions against disk_path resp. name */
456 ret= Xorriso_path_is_excluded(xorriso, disk_path, 0); /* (is never param) */
457 if(ret<0)
458 {ret= -1; goto ex;}
459 if(ret>0)
460 continue;
461 /* Check for mkisofs-style hidings */
462 hide_attrs= (flag >> 8) & 3;
463 if(hide_attrs != 3) {
464 ret= Xorriso_path_is_hidden(xorriso, disk_path, 0);
465 if(ret<0)
466 goto ex;
467 if(ret>=0)
468 hide_attrs|= ret;
469 }
470
471 strcpy(img_name, name);
472 if(Xorriso_much_too_long(xorriso, strlen(img_path), 0)<=0)
473 {ret= 0; goto was_problem;}
474 if(Xorriso_much_too_long(xorriso, strlen(srcpt), 0)<=0)
475 {ret= 0; goto was_problem;}
476 stbuf_src= srcpt;
477 if(lstat(srcpt, &stbuf)==-1) {
478 cannot_lstat:;
479 Xorriso_msgs_submit(xorriso, 0, srcpt, 0, "ERRFILE", 0);
480 sprintf(xorriso->info_text,
481 "Cannot determine attributes of source file %s",
482 Text_shellsafe(srcpt, sfe, 0));
483 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
484 ret= 0; goto was_problem;
485 }
486 source_is_dir= 0;
487 source_is_link= S_ISLNK(stbuf.st_mode);
488 if(xorriso->do_follow_links && source_is_link) {
489 /* Xorriso_hop_link checks for wide link loops */
490 ret= Xorriso_hop_link(xorriso, srcpt, &own_link_stack, &hstbuf, 0);
491 if(ret<0)
492 goto was_problem;
493 if(ret==1) {
494 ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 0);
495 if(ret<=0)
496 goto was_problem;
497 srcpt= link_target;
498 stbuf_src= srcpt;
499 if(lstat(srcpt, &stbuf)==-1)
500 goto cannot_lstat;
501 } else {
502 if(Xorriso_eval_problem_status(xorriso, 0, 1|2)<0)
503 {ret= 0; goto was_problem;}
504 ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1);
505 if(ret<=0)
506 goto was_problem;
507 }
508 } else if (S_ISLNK(stbuf.st_mode)) {
509 ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1);
510 if(ret<=0)
511 goto was_problem;
512 }
513 do_not_dive= 0;
514 if(S_ISDIR(stbuf.st_mode)) {
515 source_is_dir= 1;
516 if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
517 do_not_dive= 1;
518 }
519
520 #ifdef Xorriso_optimistic_add_treE
521
522 ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name,
523 "", img_path, (off_t) 0, (off_t) 0,
524 &node, 1 | (hide_attrs << 8));
525 if(ret == (int) ISO_NODE_NAME_NOT_UNIQUE) {
526 ret= Xoriso_handle_collision(xorriso, NULL, &node, img_path, img_path,
527 srcpt, img_path,
528 (!!source_is_dir) | (flag & (64 | 128)));
529 if(ret <= 0)
530 goto was_problem;
531 if(node == NULL) {
532 ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name,
533 "", img_path, (off_t) 0, (off_t) 0,
534 &node, (hide_attrs << 8));
535 if(ret <= 0)
536 node= NULL;
537 }
538 }
539
540 #else /* Xorriso_optimistic_add_treE */
541
542 /* does a node exist with this name ? */
543 node= NULL;
544 if(dir != NULL) {
545 ret= iso_image_get_dir_node(volume, dir, img_name, &node);
546 } else {
547 ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1);
548 }
549 if(ret>0) {
550 target_is_dir= LIBISO_ISDIR(node);
551 target_is_split= 0;
552 if(target_is_dir && !(flag & 128))
553 target_is_split= Xorriso_is_split(xorriso, "", (void *) node, 1 | 2);
554
555 if(!((target_is_dir && !target_is_split) && source_is_dir)) {
556 Xorriso_process_msg_queues(xorriso,0);
557
558 /* handle overwrite situation */;
559 if(xorriso->do_overwrite==1 ||
560 (xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) {
561 ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, img_path,
562 1 | 8 | (flag & 64));
563 if(ret<=0)
564 goto was_problem;
565 if(ret==3) {
566 sprintf(xorriso->info_text, "User revoked adding of: %s",
567 Text_shellsafe(img_path, sfe, 0));
568 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
569 ret= 0; goto was_problem;
570 }
571 node= NULL;
572 } else {
573 Xorriso_msgs_submit(xorriso, 0, srcpt, 0, "ERRFILE", 0);
574 sprintf(xorriso->info_text,
575 "While grafting %s : file object exists and may not be overwritten by %s",
576 Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0));
577 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
578 ret= 0; goto was_problem;
579 }
580 }
581 }
582
583 if(node==NULL) {
584 ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name,
585 "", img_path, (off_t) 0, (off_t) 0,
586 &node, (hide_attrs << 8));
587 }
588
589 #endif /* Xorriso_optimistic_add_treE */
590
591 if(node==NULL) {
592 Xorriso_process_msg_queues(xorriso,0);
593 Xorriso_msgs_submit(xorriso, 0, stbuf_src, 0, "ERRFILE", 0);
594 sprintf(xorriso->info_text, "Grafting failed: %s = %s",
595 Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0));
596 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
597 ret= 0; goto was_problem;
598 }
599
600 xorriso->pacifier_count++;
601 if((xorriso->pacifier_count%100)==0)
602 Xorriso_pacifier_callback(xorriso, "files added", xorriso->pacifier_count,
603 xorriso->pacifier_total, "", 0);
604
605 Xorriso_set_change_pending(xorriso, 0);
606 if(source_is_dir) {
607 if(do_not_dive) {
608 sprintf(xorriso->info_text, "Did not follow mount point : %s",
609 Text_shellsafe(disk_path, sfe, 0));
610 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
611 } else {
612 ret= Xorriso_add_tree(xorriso, (IsoDir *) node,
613 img_path, disk_path, own_link_stack,
614 1 | (flag & (2 | 64 | 128)));
615 }
616 if(ret<=0)
617 goto was_problem;
618 }
619
620 continue; /* regular bottom of loop */
621 was_problem:;
622 was_failure= 1;
623 fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
624 if(fret<0)
625 goto ex;
626 }
627
628 ret= 1;
629 ex:
630 if(sfe!=NULL)
631 free(sfe);
632 if(sfe2!=NULL)
633 free(sfe2);
634 if(disk_path!=NULL)
635 free(disk_path);
636 if(img_path!=NULL)
637 free(img_path);
638 if(link_target!=NULL)
639 free(link_target);
640 Xorriso_process_msg_queues(xorriso,0);
641 Linkitem_reset_stack(&own_link_stack, link_stack, 0);
642 Dirseq_destroy(&dirseq, 0);
643 if(ret<=0)
644 return(ret);
645 return(!was_failure);
646 }
647
648
649 /* @param flag bit0= cut_out mode : base on leaf parent directory
650 bit1= do not check and perform hidings
651 */
652 int Xorriso_copy_implicit_properties(struct XorrisO *xorriso, IsoDir *dir,
653 char *full_img_path, char *img_path, char *full_disk_path, int flag)
654 {
655 int ret, nfic, nic, nfdc, d, i;
656 char *nfi= NULL, *ni= NULL, *nfd= NULL, *cpt;
657 struct stat stbuf;
658
659 Xorriso_alloc_meM(nfi, char, SfileadrL);
660 Xorriso_alloc_meM(ni, char, SfileadrL);
661 Xorriso_alloc_meM(nfd, char, SfileadrL);
662
663 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, full_img_path, nfi,
664 1|2);
665 if(ret<=0)
666 goto ex;
667 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, img_path, ni, 1|2);
668 if(ret<=0)
669 goto ex;
670 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, full_disk_path, nfd,
671 1|2|4);
672 if(ret<=0)
673 goto ex;
674 nfic= Sfile_count_components(nfi, 0);
675 nic= Sfile_count_components(ni, 0);
676 nfdc= Sfile_count_components(nfd, 0);
677 d= nfic-(flag&1)-nic;
678 if(d<0)
679 {ret= -1; goto ex;}
680 if(d>nfdc)
681 {ret= 0; goto ex;}
682 for(i= 0; i<d; i++) {
683 cpt= strrchr(nfd, '/');
684 if(cpt==NULL)
685 {ret= -1; goto ex;} /* should not happen */
686 *cpt= 0;
687 }
688 if(nfd[0]==0)
689 strcpy(nfd, "/");
690 if(stat(nfd, &stbuf)==-1)
691 {ret= 0; goto ex;}
692 Xorriso_transfer_properties(xorriso, &stbuf, nfd, (IsoNode *) dir,
693 ((8 | 1) * ((flag&1) && d==0)) | 4 | 32);
694 sprintf(xorriso->info_text, "Copied properties for ");
695 Text_shellsafe(ni, xorriso->info_text, 1);
696 sprintf(xorriso->info_text+strlen(xorriso->info_text), " from ");
697 Text_shellsafe(nfd, xorriso->info_text, 1);
698 if(!((flag&1) && d==0))
699 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
700
701 if(!(flag & 2)) {
702 /* Check for mkisofs-style hidings */
703 ret= Xorriso_path_is_hidden(xorriso, nfd, 0);
704 if(ret<0)
705 goto ex;
706 if(ret>=0) {
707 /* Hide dir */
708 ret= Xorriso_set_hidden(xorriso, (void *) dir, "", ret, 0);
709 if(ret <= 0)
710 goto ex;
711 }
712 }
713 ret= 1;
714 ex:
715 Xorriso_free_meM(nfi);
716 Xorriso_free_meM(ni);
717 Xorriso_free_meM(nfd);
718 return(ret);
719 }
720
721
722 /* @param bit0= copy link target properties rather than link properties
723 bit1= give directory x-permission where is r-permission
724 bit2= record dev,inode (only if enabled by xorriso)
725 */
726 int Xorriso_copy_properties(struct XorrisO *xorriso,
727 char *disk_path, char *img_path, int flag)
728 {
729 int ret;
730 IsoNode *node;
731 struct stat stbuf;
732
733 ret= Xorriso_get_node_by_path(xorriso, img_path, NULL, &node, 0);
734 if(ret<=0)
735 return(ret);
736 if(flag & 1) {
737 if(stat(disk_path, &stbuf)==-1)
738 return(0);
739 } else {
740 if(lstat(disk_path, &stbuf)==-1)
741 return(0);
742 }
743 Xorriso_transfer_properties(xorriso, &stbuf, disk_path, node,
744 ((flag & 2) >> 1) | ((flag & 1) << 5) | (flag & 4));
745 Xorriso_set_change_pending(xorriso, 0);
746 return(1);
747 }
748
749
750 int Xorriso_add_symlink(struct XorrisO *xorriso, IsoDir *parent,
751 char *link_target, char *leaf_name,
752 char *nominal_path, int flag)
753 {
754 int ret= 0;
755 IsoSymlink *link= NULL;
756 IsoImage *volume;
757
758 ret= Xorriso_get_volume(xorriso, &volume, 0);
759 if(ret <= 0)
760 return(ret);
761 ret= iso_image_add_new_symlink(volume, parent, leaf_name, link_target, &link);
762 Xorriso_process_msg_queues(xorriso,0);
763 if(ret < 0) {
764 Xorriso_report_iso_error(xorriso, nominal_path, ret,
765 "Cannot create symbolic link", 0, "FATAL", 1);
766 ret= 0;
767 }
768 return(ret);
769 }
770
771
772 /* @param boss_iter Opaque handle to be forwarded to actions in ISO image
773 Set to NULL if calling this function from outside ISO world
774 @param flag bit0= mkdir: graft in as empty directory, not as copy from disk
775 bit1= do not report added files
776 bit2= -follow, -not_*: this is not a command parameter
777 bit3= use offset and cut_size for cut_out_node
778 bit4= return 3 on rejection by exclusion or user
779 bit5= if directory then do not add sub tree
780 bit6= do not delete eventually existing node from di_array
781 bit7= no special handling of split file directories
782 bit8= hide in iso_rr
783 bit9= hide in joliet
784 bit10= ln -s: graft in as symbolic link.
785 Link target is handed over in parameter disk_path.
786 @return <=0 = error , 1 = added simple node , 2 = added directory ,
787 3 = rejected
788 */
789 int Xorriso_graft_in(struct XorrisO *xorriso, void *boss_iter,
790 char *disk_path, char *img_path,
791 off_t offset, off_t cut_size, int flag)
792 {
793 IsoImage *volume;
794 char *path= NULL, *apt, *npt, *cpt;
795 char *disk_path_pt, *resolved_disk_path= NULL;
796 IsoDir *dir= NULL, *hdir;
797 IsoNode *node;
798 int done= 0, is_dir= 0, l, ret, source_is_dir, resolve_link= 0;
799 int hide_attrs;
800 struct stat stbuf;
801
802 #define Xorriso_graft_handle_collisioN 1
803 #define Xorriso_optimistic_graft_iN 1
804
805 #ifndef Xorriso_optimistic_graft_iN
806 #ifndef Xorriso_graft_handle_collisioN
807 int target_is_split, target_is_dir;
808 #endif
809 #endif
810
811 Xorriso_alloc_meM(path, char, SfileadrL);
812 Xorriso_alloc_meM(resolved_disk_path, char, SfileadrL);
813
814 hide_attrs= (flag >> 8) & 3;
815 if (disk_path == NULL && !(flag & 1)) {
816 Xorriso_msgs_submit(xorriso, 0,
817 "Program error: Xorriso_graft_in(): disk_path == NULL && !(flag & 1)",
818 0, "ABORT", 0);
819 {ret= -1; goto ex;}
820 }
821 if (disk_path == NULL) {
822 disk_path= "";
823 } else {
824 ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&4));
825 if(ret<0)
826 goto ex;
827 if(ret>0)
828 {ret= 3*!!(flag&16); goto ex;}
829
830 /* Check for mkisofs-style hidings */
831 if(hide_attrs != 3) {
832 ret= Xorriso_path_is_hidden(xorriso, disk_path, 0);
833 if(ret<0)
834 goto ex;
835 if(ret>=0)
836 hide_attrs|= ret;
837 }
838 }
839
840 for(cpt= img_path; 1; cpt++) {
841 cpt= strstr(cpt,"/.");
842 if(cpt==NULL)
843 break;
844 if(cpt[2]=='.') {
845 if(cpt[3]=='/' || cpt[3]==0)
846 break;
847 } else if(cpt[2]=='/' || cpt[2]==0)
848 break;
849 }
850 if(cpt!=NULL) {
851 if(disk_path[0])
852 Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
853 sprintf(xorriso->info_text,
854 "Unsupported relative addressing in iso_rr_path ");
855 Text_shellsafe(img_path, xorriso->info_text, 1);
856 if(disk_path[0]) {
857 strcat(xorriso->info_text, " (disk: ");
858 Text_shellsafe(disk_path, xorriso->info_text, 1);
859 strcat(xorriso->info_text, ")");
860 }
861 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
862 {ret= 0; goto ex;}
863 }
864
865 ret= Xorriso_get_volume(xorriso, &volume, 0);
866 if(ret<=0)
867 goto ex;
868
869 strncpy(path, img_path, SfileadrL - 1);
870 path[SfileadrL - 1]= 0;
871 apt= npt= path;
872
873 if(!(flag & (1 | 1024))) {
874 if(disk_path[0] == 0) {
875 Xorriso_msgs_submit(xorriso, 0, "/", 0, "ERRFILE", 0);
876 sprintf(xorriso->info_text,
877 "Will not graft-in the whole local filesystem by path '/'");
878 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
879 {ret= 0; goto ex;}
880 }
881 ret= lstat(disk_path, &stbuf);
882 if(ret!=-1) {
883 if(S_ISDIR(stbuf.st_mode))
884 is_dir= 1;
885 else if((stbuf.st_mode&S_IFMT)==S_IFLNK &&
886 (xorriso->do_follow_links ||
887 (xorriso->do_follow_param && !(flag&4)))) {
888 resolve_link= 1;
889 ret= stat(disk_path, &stbuf);
890 if(ret!=-1) {
891 if(S_ISDIR(stbuf.st_mode))
892 is_dir= 1;
893 }
894 }
895 }
896 if(ret == -1) {
897 Xorriso_process_msg_queues(xorriso,0);
898 Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
899 sprintf(xorriso->info_text,
900 "Cannot determine attributes of source file ");
901 Text_shellsafe(disk_path, xorriso->info_text, 1);
902 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
903 {ret= 0; goto ex;}
904 }
905 if(S_ISDIR(stbuf.st_mode)) {
906 is_dir= 1;
907 } else {
908 l= strlen(img_path);
909 if(l>0)
910 if(img_path[l-1]=='/')
911 l= 0;
912 if(l==0) {
913 Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
914 sprintf(xorriso->info_text, "Source ");
915 Text_shellsafe(disk_path, xorriso->info_text, 1);
916 strcat(xorriso->info_text, " is not a directory. Target ");
917 Text_shellsafe(img_path, xorriso->info_text, 1);
918 strcat(xorriso->info_text, " would be.");
919 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
920 {ret= 0; goto ex;}
921 }
922 }
923 }
924
925 dir= iso_image_get_root(volume);
926 if(dir==NULL) {
927 Xorriso_process_msg_queues(xorriso,0);
928 sprintf(xorriso->info_text,
929 "While grafting '%s' : no root node available", img_path);
930 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
931 {ret= 0; goto ex;}
932 }
933 for(npt= apt; !done; apt= npt+1) {
934 npt= strchr(apt, '/');
935 if(npt==NULL) {
936 npt= apt+strlen(apt);
937 done= 1;
938 } else
939 *npt= 0;
940 if(*apt==0) {
941 *apt= '/';
942 apt++;
943 if(done)
944 goto attach_source;
945 continue;
946 }
947 source_is_dir= (is_dir || (flag&1) || !done);
948
949 #ifdef Xorriso_optimistic_graft_iN
950
951 /* Directories of the source path are likely to exist already as directory
952 in the image.
953 That will cause two lookups with optimistic, and only one with
954 pessimistic.
955 So optimism will pay off only with the leaf. I.e. if(done).
956 */
957 if(source_is_dir) { /* eventually create directory */
958 ret= iso_image_dir_get_node(volume, dir, apt, &node, 0);
959 if(ret == 1) {
960 ret= Xoriso_handle_collision(xorriso, boss_iter, &node, path,
961 img_path, disk_path,
962 disk_path[0] ? disk_path : img_path,
963 (!!source_is_dir) | (flag & (16 | 64 | 128)));
964 if(ret <= 0 || ret == 3)
965 goto ex;
966 if(ret == 1 && node != NULL)
967 dir= (IsoDir *) node;
968 } else
969 node= NULL;
970 if(node == NULL) {
971 ret= iso_image_add_new_dir(volume, dir, apt, &hdir);
972 if(ret < 0) {
973 Xorriso_process_msg_queues(xorriso,0);
974 if(disk_path[0])
975 Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
976 Xorriso_report_iso_error(xorriso, img_path, ret,
977 "Cannot create directory", 0, "FAILURE", 1);
978 sprintf(xorriso->info_text,
979 "While grafting '%s' : could not insert '%s'", img_path, path);
980 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
981 {ret= 0; goto ex;}
982 }
983 if(xorriso->update_flags & 1) {
984 ret= Xorriso_mark_update_merge(xorriso, path, (IsoNode *) hdir, 1);
985 if(ret <= 0)
986 {ret= 0; goto ex;}
987 }
988
989 dir= hdir;
990 Xorriso_set_change_pending(xorriso, 0);
991 iso_node_set_ctime((IsoNode *) dir, time(NULL));
992 iso_node_set_uid((IsoNode *) dir, geteuid());
993 iso_node_set_gid((IsoNode *) dir, getegid());
994
995 if(disk_path[0] && !done) {
996 /* This not only copies disk directory properties
997 but also sets eventual hide_attrs */
998 Xorriso_copy_implicit_properties(xorriso, dir, img_path, path,
999 disk_path, !!(flag&8));
1000 }
1001 }
1002 }
1003
1004 if(done) {
1005 attach_source:;
1006 if(flag&1) {
1007 /* directory node was created above */;
1008
1009 } else if(flag & 1024) {
1010 ret= Xorriso_add_symlink(xorriso, dir, disk_path, apt, img_path, 0);
1011 if(ret <= 0)
1012 goto ex;
1013 Xorriso_set_change_pending(xorriso, 0);
1014
1015 } else if(is_dir) {
1016 Xorriso_transfer_properties(xorriso, &stbuf, disk_path,
1017 (IsoNode *) dir, 4 | 32);
1018 if(!(flag&32)) {
1019 ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL,
1020 flag & (2 | 64 | 128));
1021 if(ret<=0)
1022 goto ex;
1023 }
1024 } else {
1025 if(resolve_link) {
1026 ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0);
1027 if(ret<=0)
1028 goto ex;
1029 disk_path_pt= resolved_disk_path;
1030 } else
1031 disk_path_pt= disk_path;
1032
1033 ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt,
1034 disk_path, img_path, offset, cut_size,
1035 &node, 1 | (flag & 8) | (hide_attrs << 8));
1036 if(ret == (int) ISO_NODE_NAME_NOT_UNIQUE) {
1037 ret= Xoriso_handle_collision(xorriso, boss_iter, &node, img_path,
1038 img_path, disk_path,
1039 disk_path[0] ? disk_path : img_path,
1040 (flag & (16 | 64 | 128)));
1041 if(ret <= 0 || ret == 3)
1042 goto ex;
1043 ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt,
1044 disk_path, img_path, offset, cut_size,
1045 &node, (flag & 8) | (hide_attrs << 8));
1046 }
1047 if(ret<=0) {
1048 sprintf(xorriso->info_text, "Grafting failed: ");
1049 Text_shellsafe(img_path, xorriso->info_text, 1);
1050 strcat(xorriso->info_text, " = ");
1051 Text_shellsafe(disk_path, xorriso->info_text, 1);
1052 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1053 {ret= 0; goto ex;}
1054 }
1055 Xorriso_set_change_pending(xorriso, 0);
1056
1057 /* <<< Why set the name once again ?
1058 iso_image_set_node_name(volume, node, apt, 1);
1059 */
1060
1061 xorriso->pacifier_count++;
1062 if(xorriso->pacifier_count%100 && !(flag&2))
1063 Xorriso_pacifier_callback(xorriso, "files added",
1064 xorriso->pacifier_count,
1065 xorriso->pacifier_total, "", 0);
1066 }
1067 } else
1068 *npt= '/';
1069
1070 #else /* Xorriso_optimistic_graft_iN */
1071
1072 node= NULL;
1073 ret= iso_image_dir_get_node(volume, dir, apt, &node, 0);
1074 if(ret == 1) {
1075
1076 #ifdef Xorriso_graft_handle_collisioN
1077
1078 ret= Xoriso_handle_collision(xorriso, boss_iter, &node, path, img_path,
1079 disk_path,
1080 disk_path[0] ? disk_path : img_path,
1081 (!!source_is_dir) | (flag & (16 | 64 | 128)));
1082 if(ret <= 0 || ret == 3)
1083 goto ex;
1084 if(ret == 2)
1085 goto handle_path_node;
1086
1087 #else /* Xorriso_graft_handle_collisioN */
1088
1089 target_is_dir= LIBISO_ISDIR(node);
1090
1091 target_is_split= 0;
1092 if(target_is_dir && !(flag & 128))
1093 target_is_split= Xorriso_is_split(xorriso, "", (void *) node, 1 | 2);
1094
1095 if(!((target_is_dir && !target_is_split) && source_is_dir)) {
1096 Xorriso_process_msg_queues(xorriso,0);
1097
1098 /* handle overwrite situation */;
1099 if(xorriso->do_overwrite==1 ||
1100 (xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) {
1101 ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, path,
1102 1 | 8 | (flag & 64));
1103 if(ret<=0)
1104 goto ex;
1105 if(ret==3) {
1106 sprintf(xorriso->info_text, "User revoked adding of: ");
1107 if(disk_path[0])
1108 Text_shellsafe(disk_path, xorriso->info_text, 1);
1109 else
1110 Text_shellsafe(img_path, xorriso->info_text, 1);
1111 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1112 {ret= 3*!!(flag&16); goto ex;}
1113 }
1114 node= NULL;
1115 goto handle_path_node;
1116 }
1117
1118 if (disk_path[0])
1119 Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
1120 sprintf(xorriso->info_text,
1121 "While grafting '%s' : '%s' exists and may not be overwritten",
1122 img_path, path);
1123 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1124 {ret= 0; goto ex;}
1125 }
1126
1127 #endif /* ! Xorriso_graft_handle_collisioN */
1128
1129 dir= (IsoDir *) node;
1130 }
1131
1132 handle_path_node:;
1133 if(node==NULL && source_is_dir) { /* make a directory */
1134 ret= iso_image_add_new_dir(volume, dir, apt, &hdir);
1135 if(ret<0) {
1136 Xorriso_process_msg_queues(xorriso,0);
1137 if(disk_path[0])
1138 Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
1139 Xorriso_report_iso_error(xorriso, img_path, ret,
1140 "Cannot create directory", 0, "FAILURE", 1);
1141 sprintf(xorriso->info_text,
1142 "While grafting '%s' : could not insert '%s'", img_path, path);
1143 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1144 {ret= 0; goto ex;}
1145 }
1146 if(xorriso->update_flags & 1) {
1147 ret= Xorriso_mark_update_merge(xorriso, path, (IsoNode *) hdir, 1);
1148 if(ret <= 0)
1149 {ret= 0; goto ex;}
1150 }
1151
1152 dir= hdir;
1153 Xorriso_set_change_pending(xorriso, 0);
1154 iso_node_set_ctime((IsoNode *) dir, time(NULL));
1155 iso_node_set_uid((IsoNode *) dir, geteuid());
1156 iso_node_set_gid((IsoNode *) dir, getegid());
1157
1158 if(disk_path[0] && !done)
1159 /* This not only copies disk directory properties
1160 but also sets eventual hide_attrs */
1161 Xorriso_copy_implicit_properties(xorriso, dir, img_path, path, disk_path,
1162 !!(flag&8));
1163 }
1164 if(done) {
1165 attach_source:;
1166 if(flag&1) {
1167 /* directory node was created above */;
1168
1169 } else if(flag & 1024) {
1170 ret= Xorriso_add_symlink(xorriso, dir, disk_path, apt, img_path, 0);
1171 if(ret <= 0)
1172 goto ex;
1173
1174 } else if(is_dir) {
1175 Xorriso_transfer_properties(xorriso, &stbuf, disk_path,
1176 (IsoNode *) dir, 4 | 32);
1177 if(!(flag&32)) {
1178 ret= Xorriso_add_tree(xorriso, dir, img_path, disk_path, NULL,
1179 flag & (2 | 64 | 128));
1180 if(ret<=0)
1181 goto ex;
1182 }
1183 } else {
1184 if(resolve_link) {
1185 ret= Xorriso_resolve_link(xorriso, disk_path, resolved_disk_path, 0);
1186 if(ret<=0)
1187 goto ex;
1188 disk_path_pt= resolved_disk_path;
1189 } else
1190 disk_path_pt= disk_path;
1191
1192 ret= Xorriso_tree_graft_node(xorriso, volume, dir, disk_path_pt, apt,
1193 disk_path, img_path, offset, cut_size,
1194 &node, (flag&8) | (hide_attrs << 8));
1195 if(ret<=0) {
1196 sprintf(xorriso->info_text, "Grafting failed: ");
1197 Text_shellsafe(img_path, xorriso->info_text, 1);
1198 strcat(xorriso->info_text, " = ");
1199 Text_shellsafe(disk_path, xorriso->info_text, 1);
1200 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1201 {ret= 0; goto ex;}
1202 }
1203 Xorriso_set_change_pending(xorriso, 0);
1204 iso_image_set_node_name(volume, node, apt, 1);
1205
1206 xorriso->pacifier_count++;
1207 if(xorriso->pacifier_count%100 && !(flag&2))
1208 Xorriso_pacifier_callback(xorriso, "files added",
1209 xorriso->pacifier_count,
1210 xorriso->pacifier_total, "", 0);
1211 }
1212 } else
1213 *npt= '/';
1214
1215 #endif /* ! Xorriso_optimistic_graft_iN */
1216
1217 }
1218
1219 Xorriso_process_msg_queues(xorriso,0);
1220 ret= 1+!!is_dir;
1221 ex:;
1222 Xorriso_free_meM(path);
1223 Xorriso_free_meM(resolved_disk_path);
1224 return(ret);
1225 }
1226
1227
1228 /* @param flag bit0= -follow: disk_path is not a command parameter
1229 */
1230 int Xorriso_cut_out(struct XorrisO *xorriso, char *disk_path,
1231 off_t startbyte, off_t bytecount, char *iso_rr_path, int flag)
1232 {
1233 int ret;
1234 char *eff_source= NULL, *eff_dest= NULL;
1235 struct stat stbuf;
1236
1237 Xorriso_alloc_meM(eff_source, char, SfileadrL);
1238 Xorriso_alloc_meM(eff_dest, char, SfileadrL);
1239
1240 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_source,
1241 2|4);
1242 if(ret<=0)
1243 goto ex;
1244 ret= Xorriso_path_is_excluded(xorriso, disk_path, !(flag&1));
1245 if(ret!=0)
1246 {ret= 0; goto ex;}
1247
1248 if(lstat(eff_source, &stbuf)==-1) {
1249 Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0);
1250 sprintf(xorriso->info_text, "-cut_out: Cannot determine type of ");
1251 Text_shellsafe(eff_source, xorriso->info_text, 1);
1252 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
1253 {ret= 0; goto ex;}
1254 }
1255
1256 if((stbuf.st_mode&S_IFMT) == S_IFLNK) {
1257 if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
1258 goto unsupported_type;
1259 if(stat(eff_source, &stbuf)==-1) {
1260 Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0);
1261 sprintf(xorriso->info_text,
1262 "-cut_out: Cannot determine link target type of ");
1263 Text_shellsafe(eff_source, xorriso->info_text, 1);
1264 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
1265 {ret= 0; goto ex;}
1266 }
1267 }
1268 if(S_ISREG(stbuf.st_mode)) {
1269 if(stbuf.st_size<startbyte) {
1270 Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0);
1271 sprintf(xorriso->info_text,
1272 "-cut_out: Byte offset %.f larger than file size %.f",
1273 (double) startbyte, (double) stbuf.st_size);
1274 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0);
1275 {ret= 0; goto ex;}
1276 }
1277 } else {
1278 unsupported_type:;
1279 Xorriso_msgs_submit(xorriso, 0, eff_source, 0, "ERRFILE", 0);
1280 sprintf(xorriso->info_text, "-cut_out: Unsupported file type (%s) with ",
1281 Ftypetxt(stbuf.st_mode, 0));
1282 Text_shellsafe(eff_source, xorriso->info_text, 1);
1283 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
1284 {ret= 0; goto ex;}
1285 }
1286
1287 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, iso_rr_path, eff_dest,
1288 2);
1289 if(ret<=0)
1290 goto ex;
1291
1292 ret= Xorriso_graft_in(xorriso, NULL, eff_source, eff_dest,
1293 startbyte, bytecount, 8);
1294 ex:;
1295 Xorriso_free_meM(eff_source);
1296 Xorriso_free_meM(eff_dest);
1297 return(ret);
1298 }
1299
1300
1301 /* @param flag bit0= do not produce info message on success
1302 bit1= do not raise protest if directory already exists
1303 @return 1=success,
1304 0=was already directory, -1=was other type, -2=other error
1305 */
1306 int Xorriso_mkdir(struct XorrisO *xorriso, char *path, int flag)
1307 {
1308 int ret;
1309 char *eff_path= NULL;
1310
1311 Xorriso_alloc_meM(eff_path, char, SfileadrL);
1312
1313 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 1);
1314 if(ret<0)
1315 {ret= -2; goto ex;}
1316 if(ret>0) {
1317 if(ret == 2 && (flag & 2))
1318 {ret= 0; goto ex;}
1319 sprintf(xorriso->info_text,"-mkdir: Address already existing ");
1320 Text_shellsafe(eff_path, xorriso->info_text, 1);
1321 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
1322 (ret==2 ? "WARNING" : "FAILURE"), 0);
1323 {ret= -1 + (ret == 2); goto ex;}
1324 }
1325 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, path, eff_path, 2);
1326 if(ret<0)
1327 {ret= -2; goto ex;}
1328 ret= Xorriso_graft_in(xorriso, NULL, NULL, eff_path, (off_t) 0, (off_t) 0, 1);
1329 if(ret<=0)
1330 {ret= -2; goto ex;}
1331 if(!(flag&1)) {
1332 sprintf(xorriso->info_text, "Created directory in ISO image: ");
1333 Text_shellsafe(eff_path, xorriso->info_text, 1);
1334 strcat(xorriso->info_text, "\n");
1335 Xorriso_info(xorriso, 0);
1336 }
1337 ret= 1;
1338 ex:;
1339 Xorriso_free_meM(eff_path);
1340 return(ret);
1341 }
1342
1343
1344 /* @param boss_iter If not NULL then this is an iterator suitable for
1345 iso_dir_iter_remove() which is then to be used instead
1346 of iso_node_remove().
1347 @param flag bit0= remove whole sub tree: rm -r
1348 bit1= remove empty directory: rmdir
1349 bit2= recursion: do not reassure in mode 2 "tree"
1350 bit3= this is for overwriting and not for plain removal
1351 bit4= count deleted files in xorriso->pacifier_count
1352 bit5= with bit0 only remove directory content, not the directory
1353 bit6= do not delete eventually existing node from di_array
1354 @return <=0 = error
1355 1 = removed simple node
1356 2 = removed directory or tree
1357 3 = did not remove on user revocation
1358 */
1359 int Xorriso_rmi(struct XorrisO *xorriso, void *boss_iter, off_t boss_mem,
1360 char *path, int flag)
1361 {
1362 int ret, is_dir= 0, pl, not_removed= 0, fret;
1363 IsoNode *victim_node= NULL, *node;
1364 IsoDir *boss_node, *root_dir;
1365 IsoDirIter *iter= NULL;
1366 IsoImage *volume;
1367 char *sub_name, *name;
1368 char *sfe= NULL, *sub_path= NULL;
1369 off_t mem;
1370 IsoNode **node_array= NULL;
1371 int node_count= 0, node_idx;
1372
1373 /* Avoiding large local memory objects in order to save stack space */
1374 sfe= malloc(5*SfileadrL);
1375 sub_path= malloc(2*SfileadrL);
1376 if(sfe==NULL || sub_path==NULL) {
1377 Xorriso_no_malloc_memory(xorriso, &sfe, 0);
1378 {ret= -1; goto ex;}
1379 }
1380
1381 #ifndef Libisofs_iso_dir_iter_sufficienT
1382 /* Ticket 127: A80301 - A80302
1383 I do not not deem IsoDirIter safe for node list manipulations.
1384 The parameter boss_iter once was intended to allow such but
1385 has now been downgraded to a mere check for eventual programming bugs.
1386 */
1387 if(boss_iter!=NULL) {
1388 sprintf(xorriso->info_text,
1389 "Program error: Xorriso_rmi() was requested to delete iterated node %s",
1390 Text_shellsafe(path, sfe, 0));
1391 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
1392 ret= -1; goto ex;
1393 }
1394 #endif /* Libisofs_iso_dir_iter_sufficienT */
1395
1396 ret= Xorriso_get_volume(xorriso, &volume, 0);
1397 if(ret<=0)
1398 goto ex;
1399
1400 if(Xorriso_much_too_long(xorriso, strlen(path), 0)<=0)
1401 {ret= 0; goto ex;}
1402 ret= Xorriso_node_from_path(xorriso, volume, path, &victim_node, 0);
1403 if(ret<=0)
1404 goto ex;
1405 root_dir= iso_image_get_root(volume);
1406 if(((void *) root_dir) == ((void *) victim_node) && !(flag & 1)) {
1407 sprintf(xorriso->info_text, "May not delete root directory");
1408 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1409 {ret= 0; goto ex;}
1410 }
1411
1412 if(LIBISO_ISDIR(victim_node))
1413 is_dir= 1;
1414 if(!is_dir) {
1415 if(flag&2) { /* rmdir */
1416 sprintf(xorriso->info_text, "%s in loaded ISO image is not a directory",
1417 Text_shellsafe(path, sfe, 0));
1418 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1419 ret= 0; goto ex;
1420 }
1421 } else {
1422 if(flag&1) { /* rm -r */
1423 if((xorriso->do_reassure==1 && !xorriso->request_not_to_ask) ||
1424 (flag&32) || ((void *) root_dir) == ((void *) victim_node)) {
1425 /* Iterate over subordinates and delete them */
1426 mem= boss_mem;
1427
1428 ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem,
1429 &iter, &node_array, &node_count, &node_idx,
1430 &node, 1|2);
1431 if(ret<=0) {
1432 cannot_create_iter:;
1433 Xorriso_cannot_create_iter(xorriso, ret, 0);
1434 ret= -1; goto ex;
1435 }
1436 pl= strlen(path);
1437 strcpy(sub_path, path);
1438 if(pl==0 || sub_path[pl-1]!='/') {
1439 sub_path[pl++]= '/';
1440 sub_path[pl]= 0;
1441 }
1442 sub_name= sub_path+pl;
1443 while(1) {
1444 ret= Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter,
1445 &node_array, &node_count, &node_idx, &node, 0);
1446 if(ret<0)
1447 goto ex;
1448 if(ret==0 || xorriso->request_to_abort)
1449 break;
1450 name= (char *) iso_node_get_name(node);
1451 if(Xorriso_much_too_long(xorriso, pl+1+strlen(name), 0)<=0)
1452 {ret= 0; goto rm_r_problem_handler;}
1453 strcpy(sub_name, name);
1454 ret= Xorriso_rmi(xorriso, iter, mem, sub_path,
1455 (flag & ( 1 | 2 | 8 | 16 | 64)) | 4);
1456 if(ret==3 || ret<=0 || xorriso->request_to_abort) {
1457 rm_r_problem_handler:;
1458 not_removed= 1;
1459 fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
1460 if(fret<0)
1461 goto dir_not_removed;
1462 }
1463 }
1464 if(flag&32)
1465 {ret= 2; goto ex;}
1466
1467 if(not_removed) {
1468 dir_not_removed:;
1469 sprintf(xorriso->info_text, "Directory not removed: %s",
1470 Text_shellsafe(path, sfe, 0));
1471 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1472 if(ret>0)
1473 ret= 3;
1474 goto ex;
1475 }
1476 }
1477 } else {
1478 if(!(flag&2)) { /* not rmdir */
1479 sprintf(xorriso->info_text, "%s in loaded ISO image is a directory",
1480 Text_shellsafe(path, sfe, 0));
1481 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1482 ret= 0; goto ex;
1483 }
1484
1485 ret= iso_dir_get_children((IsoDir *) victim_node, &iter);
1486 Xorriso_process_msg_queues(xorriso,0);
1487 if(ret<0)
1488 goto cannot_create_iter;
1489 if(ret>0) {
1490 if(iso_dir_iter_next(iter, &node) == 1) {
1491 sprintf(xorriso->info_text,
1492 "Directory not empty on attempt to delete: %s",
1493 Text_shellsafe(path, sfe, 0));
1494 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1495 ret= 0; goto ex;
1496 }
1497 }
1498 }
1499 }
1500
1501 if(((void *) root_dir) == ((void *) victim_node))
1502 {ret= 2; goto ex;}
1503
1504 if(xorriso->request_to_abort)
1505 {ret= 3; goto ex;}
1506 boss_node= iso_node_get_parent(victim_node);
1507 Xorriso_process_msg_queues(xorriso,0);
1508 if(boss_node==NULL) {
1509 sprintf(xorriso->info_text,
1510 "Cannot find parent node of %s in loaded ISO image",
1511 Text_shellsafe(path, sfe, 0));
1512 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1513 ret= 0; goto ex;
1514 }
1515
1516 while((xorriso->do_reassure==1 || (xorriso->do_reassure==2 && !(flag&4)))
1517 && !xorriso->request_not_to_ask) {
1518 /* ls -ld */
1519 Xorriso_ls_filev(xorriso, xorriso->wdi, 1, &path, (off_t) 0, 1|2|8);
1520 if(is_dir) /* du -s */
1521 Xorriso_ls_filev(xorriso, xorriso->wdi, 1, &path, (off_t) 0, 2|4);
1522 if(flag&8)
1523 sprintf(xorriso->info_text,
1524 "File exists. Remove ? n= keep old, y= remove, x= abort, @= stop asking\n");
1525 else
1526 sprintf(xorriso->info_text,
1527 "Remove above file ? n= keep it, y= remove it, x= abort, @= stop asking\n");
1528 Xorriso_info(xorriso, 4);
1529 ret= Xorriso_request_confirmation(xorriso, 1|2|4|16);
1530 if(ret<=0)
1531 goto ex;
1532 if(xorriso->request_to_abort) {
1533 sprintf(xorriso->info_text,
1534 "Removal operation aborted by user before file: %s",
1535 Text_shellsafe(path, sfe, 0));
1536 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1537 ret= 3; goto ex;
1538 }
1539 if(ret==3)
1540 continue;
1541 if(ret==6) /* yes */
1542 break;
1543 if(ret==4) { /* yes, do not ask again */
1544 xorriso->request_not_to_ask= 1;
1545 break;
1546 }
1547 if(ret==1) { /* no */
1548 sprintf(xorriso->info_text, "Kept in existing state: %s",
1549 Text_shellsafe(path, sfe, 0));
1550 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1551 ret= 3; goto ex;
1552 }
1553 }
1554
1555 if(!(flag & 64))
1556 Xorriso_invalidate_di_item(xorriso, victim_node, 0);
1557
1558 #ifdef Libisofs_iso_dir_iter_sufficienT
1559
1560 if(boss_iter!=NULL) {
1561 ret= iso_dir_iter_remove((IsoDirIter *) boss_iter);
1562 if(ret<0)
1563 ret= -1;
1564 } else
1565 ret= iso_node_remove(victim_node);
1566
1567 #else /* ! Libisofs_iso_dir_iter_sufficienT */
1568
1569 ret= iso_node_remove(victim_node);
1570
1571 #endif /* Libisofs_iso_dir_iter_sufficienT */
1572
1573 Xorriso_process_msg_queues(xorriso,0);
1574 if(ret<0) {
1575 Xorriso_report_iso_error(xorriso, path, ret, "Cannot remove node", 0,
1576 "FATAL", 1);
1577 sprintf(xorriso->info_text,
1578 "Internal failure to remove %s from loaded ISO image",
1579 Text_shellsafe(path, sfe, 0));
1580 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
1581 ret= -1; goto ex;
1582 }
1583
1584 if(flag&16)
1585 xorriso->pacifier_count++;
1586 Xorriso_set_change_pending(xorriso, 0);
1587 ret= 1+!!is_dir;
1588 ex:;
1589 if(sfe!=NULL)
1590 free(sfe);
1591 if(sub_path!=NULL)
1592 free(sub_path);
1593 Xorriso_findi_iter(xorriso, (IsoDir *) victim_node, &mem, &iter,
1594 &node_array, &node_count, &node_idx, &node, (1u<<31));
1595 return(ret);
1596 }
1597
1598
1599 int Xorriso_overwrite_dest(struct XorrisO *xorriso, void *boss_iter,
1600 char *eff_dest, int dest_ret, char *activity,
1601 int flag)
1602 {
1603 int ret;
1604
1605 if(dest_ret==2 && xorriso->do_overwrite!=1) {
1606 sprintf(xorriso->info_text, "%s: May not overwrite directory: ", activity);
1607 Text_shellsafe(eff_dest, xorriso->info_text, 1);
1608 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1609 return(0);
1610 } else if (dest_ret==1 && !xorriso->do_overwrite) {
1611 sprintf(xorriso->info_text, "%s: May not overwrite: ", activity);
1612 Text_shellsafe(eff_dest, xorriso->info_text, 1);
1613 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1614 return(0);
1615 } else if(dest_ret>0) {
1616 ret= Xorriso_rmi(xorriso, boss_iter, (off_t) 0, eff_dest, 1|8);
1617 if(ret<=0)
1618 return(0);
1619 if(ret==3) {
1620 sprintf(xorriso->info_text, "%s: User revoked removal of: ", activity);
1621 Text_shellsafe(eff_dest, xorriso->info_text, 1);
1622 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
1623 return(0);
1624 }
1625 }
1626 return(1);
1627 }
1628
1629
1630 /* @param boss_iter Opaque handle to be forwarded to actions in ISO image
1631 Set to NULL if calling this function from outside ISO world
1632 @param flag bit0= silently ignore attempt of renaming to same path
1633 and return 2
1634 */
1635 int Xorriso_rename(struct XorrisO *xorriso, void *boss_iter,
1636 char *origin, char *dest, int flag)
1637 {
1638 int ret, ol, dest_ret;
1639 char *eff_dest= NULL, *dir_adr= NULL, *cpt;
1640 char *leafname, *eff_origin= NULL, *old_leafname;
1641 IsoImage *volume;
1642 IsoDir *origin_dir, *dest_dir;
1643 IsoNode *node, *iso_node;
1644
1645 Xorriso_alloc_meM(eff_dest, char, SfileadrL);
1646 Xorriso_alloc_meM(dir_adr, char, SfileadrL);
1647 Xorriso_alloc_meM(eff_origin, char, SfileadrL);
1648
1649 #ifndef Libisofs_iso_dir_iter_sufficienT
1650 /* Ticket 127: A80301 - A80302
1651 I do not not deem IsoDirIter safe for node list manipulations.
1652 The parameter boss_iter once was intended to allow such but
1653 has now been downgraded to a mere check for eventual programming bugs.
1654 */
1655 if(boss_iter!=NULL) {
1656 sprintf(xorriso->info_text,
1657 "Program error: Xorriso_rename() was requested to delete iterated node ");
1658 Text_shellsafe(origin, xorriso->info_text, 1);
1659 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
1660 {ret= -1; goto ex;}
1661 }
1662 #endif /* Libisofs_iso_dir_iter_sufficienT */
1663
1664 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, origin, eff_origin, 0);
1665 if(ret<=0)
1666 goto ex;
1667 dest_ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest,1);
1668 if(dest_ret<0)
1669 {ret= dest_ret; goto ex;}
1670 if(dest_ret==0) { /* obtain eff_dest address despite it does not exist */
1671 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest, 2);
1672 if(ret<=0)
1673 goto ex;
1674 }
1675
1676 /* Prevent that destination is a subordinate of origin
1677 (that would be a black hole plopping out of the universe) */
1678 ol= strlen(eff_origin);
1679 if(ol==0) {
1680 sprintf(xorriso->info_text, "May not rename root directory");
1681 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1682 {ret= 0; goto ex;}
1683 } else if(strcmp(eff_origin, eff_dest)==0) {
1684 if(flag & 1)
1685 {ret= 2; goto ex;}
1686 sprintf(xorriso->info_text, "Ignored attempt to rename ");
1687 Text_shellsafe(eff_origin, xorriso->info_text, 1);
1688 strcat(xorriso->info_text, " to itself");
1689 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
1690 {ret= 0; goto ex;}
1691 } else if(strncmp(eff_origin, eff_dest, ol)==0 &&
1692 (eff_dest[ol]==0 || eff_dest[ol]=='/')) {
1693 sprintf(xorriso->info_text, "May not rename ");
1694 Text_shellsafe(eff_origin, xorriso->info_text, 1);
1695 strcat(xorriso->info_text, " to its own sub address ");
1696 Text_shellsafe(eff_dest, xorriso->info_text, 1 | 2);
1697 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1698 {ret= 0; goto ex;}
1699 }
1700
1701 /* Check whether destination exists and may be not overwritable */
1702 ret= Xorriso_overwrite_dest(xorriso, boss_iter,
1703 eff_dest, dest_ret, "Renaming", 0);
1704 if(ret <= 0)
1705 goto ex;
1706
1707 /* Ensure existence of destination directory */
1708 strcpy(dir_adr, eff_dest);
1709 cpt= strrchr(dir_adr, '/');
1710 if(cpt==NULL)
1711 cpt= dir_adr+strlen(dir_adr);
1712 *cpt= 0;
1713 if(dir_adr[0]!=0) {
1714 ret= Xorriso_graft_in(xorriso, boss_iter, NULL, dir_adr,
1715 (off_t) 0, (off_t) 0, 1);
1716 if(ret<=0)
1717 goto ex;
1718 }
1719
1720 /* Move node */
1721 ret= Xorriso_get_volume(xorriso, &volume, 0);
1722 if(ret<=0)
1723 goto ex;
1724 Xorriso_node_from_path(xorriso, volume, dir_adr, &iso_node, 0);
1725 dest_dir= (IsoDir *) iso_node;
1726 strcpy(dir_adr, eff_origin);
1727 cpt= strrchr(dir_adr, '/');
1728 if(cpt==NULL)
1729 cpt= dir_adr+strlen(dir_adr);
1730 *cpt= 0;
1731 Xorriso_node_from_path(xorriso, volume, dir_adr, &iso_node, 0);
1732 origin_dir= (IsoDir *) iso_node;
1733 Xorriso_node_from_path(xorriso, volume, eff_origin, &node, 0);
1734 if(dest_dir==NULL || origin_dir==NULL || node==NULL) {
1735 Xorriso_process_msg_queues(xorriso,0);
1736 sprintf(xorriso->info_text,
1737 "Internal error on rename: confirmed node turns out as NULL");
1738 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
1739 {ret= -1; goto ex;}
1740 }
1741 ret= iso_node_take(node);
1742 if(ret<0) {
1743 Xorriso_process_msg_queues(xorriso,0);
1744 Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot take", 0, "FATAL",1);
1745 sprintf(xorriso->info_text,
1746 "Internal error on rename: failed to take node");
1747 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
1748 {ret= -1; goto ex;}
1749 }
1750 leafname= strrchr(eff_dest, '/');
1751 if(leafname==NULL)
1752 leafname= eff_dest;
1753 else
1754 leafname++;
1755
1756 old_leafname= (char *) iso_node_get_name(node);
1757 if(strcmp(leafname, old_leafname)!=0)
1758 ret= iso_image_set_node_name(volume, node, leafname, 1);
1759 else
1760 ret= 1;
1761 if(ret<0) {
1762 Xorriso_process_msg_queues(xorriso,0);
1763 Xorriso_report_iso_error(xorriso, eff_dest, ret, "Cannot set name", 0,
1764 "FAILURE", 1);
1765 ret= iso_dir_add_node(origin_dir, node, 0);
1766 Xorriso_process_msg_queues(xorriso,0);
1767 if(ret < 0)
1768 Xorriso_report_iso_error(xorriso, eff_origin, ret,
1769 "Cannot re-instate node at old path",
1770 0, "FAILURE", 1);
1771 {ret= -1; goto ex;}
1772 }
1773 Xorriso_process_msg_queues(xorriso,0);
1774 ret= iso_dir_add_node(dest_dir, node, 0);
1775 if(ret<0) {
1776 Xorriso_process_msg_queues(xorriso,0);
1777 Xorriso_report_iso_error(xorriso, eff_dest, 0, "Cannot add", 0, "FATAL", 1);
1778 sprintf(xorriso->info_text,
1779 "Internal error on rename: failed to insert node");
1780 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
1781 {ret= -1; goto ex;}
1782 }
1783 Xorriso_set_change_pending(xorriso, 0);
1784 ret= 1;
1785 ex:;
1786 Xorriso_free_meM(eff_dest);
1787 Xorriso_free_meM(dir_adr);
1788 Xorriso_free_meM(eff_origin);
1789 return(ret);
1790 }
1791
1792
1793 int Xorriso_cannot_clone(struct XorrisO *xorriso, char *eff_origin,
1794 char *eff_dest, int iso_error, int flag)
1795 {
1796 Xorriso_report_iso_error(xorriso, eff_dest, iso_error, "Cannot clone",
1797 0, "FAILURE", 1);
1798 sprintf(xorriso->info_text, "Failed to clone ");
1799 Text_shellsafe(eff_origin, xorriso->info_text, 1);
1800 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1801 return(0);
1802 }
1803
1804
1805 /* @param flag bit0= for iso_tree_clone() : merge directories
1806 bit1= do not issue NOTE message
1807 */
1808 int Xorriso_clone_tree(struct XorrisO *xorriso, void *boss_iter,
1809 char *origin, char *dest, int flag)
1810 {
1811 int ret, dest_ret, l;
1812 char *eff_dest= NULL, *eff_origin= NULL, *dir_adr= NULL;
1813 char *leafname;
1814 IsoImage *volume;
1815 IsoDir *new_parent;
1816 IsoNode *origin_node, *dir_node, *new_node;
1817
1818 Xorriso_alloc_meM(eff_dest, char, SfileadrL);
1819 Xorriso_alloc_meM(eff_origin, char, SfileadrL);
1820 Xorriso_alloc_meM(dir_adr, char, SfileadrL);
1821
1822 ret= Xorriso_get_volume(xorriso, &volume, 0);
1823 if(ret <= 0)
1824 goto ex;
1825
1826 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, origin, eff_origin, 0);
1827 if(ret<=0)
1828 goto ex;
1829 ret= Xorriso_node_from_path(xorriso, volume, eff_origin, &origin_node, 0);
1830 if(ret <= 0)
1831 goto ex;
1832
1833 dest_ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest,1);
1834 if(dest_ret<0)
1835 {ret= dest_ret; goto ex;}
1836 if(dest_ret > 0) {
1837 if(eff_dest[0] == 0)
1838 strcpy(eff_dest, "/");
1839 sprintf(xorriso->info_text,
1840 "Cloning: Copy address already exists: ");
1841 Text_shellsafe(eff_dest, xorriso->info_text, 1);
1842 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1843 {ret= 0; goto ex;}
1844 } else {
1845 /* obtain eff_dest address despite it does not exist */
1846 ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, dest, eff_dest, 2);
1847 if(ret<=0)
1848 goto ex;
1849 }
1850
1851 /* Obtain parent path and leaf name */
1852 strcpy(dir_adr, eff_dest);
1853 for(l= strlen(dir_adr); l > 0; ) {
1854 if(dir_adr[l - 1] == '/')
1855 dir_adr[--l]= 0;
1856 else
1857 break;
1858 }
1859 leafname= strrchr(dir_adr, '/');
1860 if(leafname == NULL) {
1861 leafname= dir_adr;
1862 if (leafname[0] == 0) {
1863 Xorriso_msgs_submit(xorriso, 0, "Empty file name as clone destination",
1864 0, "FAILURE", 0);
1865 {ret= 0; goto ex;}
1866 }
1867 } else {
1868 *leafname= 0;
1869 leafname++;
1870 if(dir_adr[0] != 0) {
1871 /* Ensure existence of destination directory */
1872 ret= Xorriso_graft_in(xorriso, boss_iter, NULL, dir_adr,
1873 (off_t) 0, (off_t) 0, 1);
1874 if(ret <= 0)
1875 goto ex;
1876 }
1877 }
1878
1879 ret= Xorriso_node_from_path(xorriso, volume, dir_adr, &dir_node, 0);
1880 if(ret <= 0)
1881 goto ex;
1882 new_parent= (IsoDir *) dir_node;
1883
1884 ret = iso_image_tree_clone(volume, origin_node, new_parent, leafname,
1885 &new_node, (flag & 1) | 2);
1886 Xorriso_process_msg_queues(xorriso,0);
1887 if(ret < 0) {
1888 Xorriso_cannot_clone(xorriso, eff_origin, eff_dest, ret, 0);
1889 {ret= 0; goto ex;}
1890 }
1891 Xorriso_set_change_pending(xorriso, 0);
1892 if(!(flag & 2)) {
1893 strcpy(xorriso->info_text, "Cloned in ISO image: ");
1894 Text_shellsafe(eff_origin, xorriso->info_text, 1);
1895 strcat(xorriso->info_text, " to ");
1896 Text_shellsafe(eff_dest, xorriso->info_text, 1 | 2);
1897 strcat(xorriso->info_text, "\n");
1898 Xorriso_info(xorriso, 0);
1899 }
1900 ret= 1;
1901 ex:;
1902 Xorriso_free_meM(eff_dest);
1903 Xorriso_free_meM(eff_origin);
1904 Xorriso_free_meM(dir_adr);
1905 return(ret);
1906 }
1907
1908
1909 int Xorriso_clone_under(struct XorrisO *xorriso, char *origin, char *dest,
1910 int flag)
1911 {
1912 int ret, pass;
1913 char *eff_dest= NULL, *eff_origin= NULL, *namept;
1914 IsoDir *origin_dir, *dest_dir;
1915 IsoDirIter *iter= NULL;
1916 IsoNode *origin_node, *new_node;
1917 IsoImage *volume;
1918
1919 Xorriso_alloc_meM(eff_dest, char, SfileadrL);
1920 Xorriso_alloc_meM(eff_origin, char, SfileadrL);
1921
1922 ret= Xorriso_get_volume(xorriso, &volume, 0);
1923 if(ret <= 0)
1924 goto ex;
1925 ret= Xorriso_dir_from_path(xorriso, "Copy source", origin, &origin_dir, 0);
1926 if(ret <= 0)
1927 goto ex;
1928 ret= Xorriso_dir_from_path(xorriso, "Copy destination", dest, &dest_dir, 0);
1929 if(ret <= 0)
1930 goto ex;
1931
1932 for(pass= 0; pass < 2; pass++) {
1933 ret= iso_dir_get_children(origin_dir, &iter);
1934 if(ret < 0) {
1935 Xorriso_cannot_create_iter(xorriso, ret, 0);
1936 {ret= -1; goto ex;}
1937 }
1938 Xorriso_process_msg_queues(xorriso,0);
1939
1940 while(iso_dir_iter_next(iter, &origin_node) == 1) {
1941 namept= (char *) iso_node_get_name(origin_node);
1942 sprintf(eff_origin, "%s/%s", origin, namept);
1943 sprintf(eff_dest, "%s/%s", dest, namept);
1944 if(pass == 0) {
1945 ret= Xorriso_node_from_path(xorriso, volume, eff_dest, &new_node, 1);
1946 if(ret < 0)
1947 goto ex;
1948 if(ret > 0) {
1949 sprintf(xorriso->info_text, "Cloning: Copy address already exists: ");
1950 Text_shellsafe(eff_dest, xorriso->info_text, 1);
1951 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
1952 ret= 0; goto ex;
1953 }
1954 } else {
1955 ret = iso_image_tree_clone(volume, origin_node, dest_dir, namept,
1956 &new_node, 1 | 2);
1957 Xorriso_process_msg_queues(xorriso,0);
1958 if(ret < 0) {
1959 Xorriso_cannot_clone(xorriso, eff_origin, eff_dest, ret, 0);
1960 ret= 0; goto ex;
1961 }
1962 }
1963 }
1964 iso_dir_iter_free(iter);
1965 iter= NULL;
1966 }
1967 Xorriso_set_change_pending(xorriso, 0);
1968 ret= 1;
1969 ex:;
1970 if(iter != NULL)
1971 iso_dir_iter_free(iter);
1972 Xorriso_free_meM(eff_dest);
1973 Xorriso_free_meM(eff_origin);
1974 Xorriso_process_msg_queues(xorriso,0);
1975 return(ret);
1976 }
1977
1978
1979 int Xorriso_set_st_mode(struct XorrisO *xorriso, char *in_path,
1980 mode_t mode_and, mode_t mode_or, int flag)
1981 {
1982 mode_t mode= 0;
1983 int ret;
1984 IsoNode *node;
1985 char *path= NULL;
1986
1987 Xorriso_alloc_meM(path, char, SfileadrL);
1988 ret= Xorriso_get_node_by_path(xorriso, in_path, path, &node, 0);
1989 if(ret<=0)
1990 goto ex;
1991 mode= iso_node_get_permissions(node);
1992 mode= (mode & mode_and) | mode_or;
1993 iso_node_set_permissions(node, mode);
1994 iso_node_set_ctime(node, time(NULL));
1995 sprintf(xorriso->info_text,"Permissions now: %-5.5o ",
1996 (unsigned int) (mode & 0xffff));
1997 Text_shellsafe(path, xorriso->info_text, 1);
1998 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
1999 Xorriso_set_change_pending(xorriso, 0);
2000 Xorriso_process_msg_queues(xorriso,0);
2001 ret= 1;
2002 ex:;
2003 Xorriso_free_meM(path);
2004 return(ret);
2005 }
2006
2007
2008 int Xorriso_set_uid(struct XorrisO *xorriso, char *in_path, uid_t uid,
2009 int flag)
2010 {
2011 int ret;
2012 IsoNode *node;
2013
2014 ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0);
2015 if(ret<=0)
2016 return(ret);
2017 iso_node_set_uid(node, uid);
2018 iso_node_set_ctime(node, time(NULL));
2019 Xorriso_set_change_pending(xorriso, 0);
2020 Xorriso_process_msg_queues(xorriso,0);
2021 return(1);
2022 }
2023
2024
2025 int Xorriso_set_gid(struct XorrisO *xorriso, char *in_path, gid_t gid,
2026 int flag)
2027 {
2028 int ret;
2029 IsoNode *node;
2030
2031 ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0);
2032 if(ret<=0)
2033 return(ret);
2034 iso_node_set_gid(node, gid);
2035 iso_node_set_ctime(node, time(NULL));
2036 Xorriso_set_change_pending(xorriso, 0);
2037 Xorriso_process_msg_queues(xorriso,0);
2038 return(1);
2039 }
2040
2041
2042 /* @parm flag bit0= atime, bit1= ctime, bit2= mtime, bit8=no auto ctime */
2043 int Xorriso_set_time(struct XorrisO *xorriso, char *in_path, time_t t,
2044 int flag)
2045 {
2046 int ret;
2047 IsoNode *node;
2048
2049 ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0);
2050 if(ret<=0)
2051 return(ret);
2052 if(flag&1)
2053 iso_node_set_atime(node, t);
2054 if(flag&2)
2055 iso_node_set_ctime(node, t);
2056 if(flag&4)
2057 iso_node_set_mtime(node, t);
2058 if(!(flag&(2|256)))
2059 iso_node_set_ctime(node, time(NULL));
2060 Xorriso_set_change_pending(xorriso, 0);
2061 Xorriso_process_msg_queues(xorriso,0);
2062 return(1);
2063 }
2064
2065
2066 /*
2067 Apply the effect of mkisofs -r to a single node
2068 */
2069 int Xorriso_mkisofs_lower_r(struct XorrisO *xorriso, IsoNode *node, int flag)
2070 {
2071 mode_t perms;
2072
2073 perms= iso_node_get_permissions(node);
2074 iso_node_set_uid(node, (uid_t) 0);
2075 iso_node_set_gid(node, (gid_t) 0);
2076 perms|= S_IRUSR | S_IRGRP | S_IROTH;
2077 perms&= ~(S_IWUSR | S_IWGRP | S_IWOTH);
2078 if(perms & (S_IXUSR | S_IXGRP | S_IXOTH))
2079 perms|= (S_IXUSR | S_IXGRP | S_IXOTH);
2080 perms&= ~(S_ISUID | S_ISGID | S_ISVTX);
2081 iso_node_set_permissions(node, perms);
2082 return(1);
2083 }
2084
2085
2086 /* @param node Opaque handle to IsoNode which is to be manipulated
2087 instead of path if it is not NULL.
2088 @param path is used as address if node is NULL.
2089 @param access_text "access" ACL in long text form
2090 @param default_text "default" ACL in long text form
2091 @param flag bit0= do not warn of root directory if not capable of AAIP
2092 @return >0 success , <=0 failure
2093 */
2094 int Xorriso_setfacl(struct XorrisO *xorriso, void *in_node, char *path,
2095 char *access_text, char *default_text, int flag)
2096 {
2097 int ret;
2098 IsoNode *node;
2099
2100 node= (IsoNode *) in_node;
2101 if(node == NULL) {
2102 ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
2103 if(ret<=0)
2104 goto ex;
2105 }
2106 ret= iso_node_set_acl_text(node, access_text, default_text, 4);
2107 Xorriso_process_msg_queues(xorriso,0);
2108 if(ret <= 0) {
2109 Xorriso_report_iso_error(xorriso, "", ret,
2110 "Error when setting ACL to image node",
2111 0, "FAILURE", 1);
2112 if(path != NULL && path[0] != 0) {
2113 strcpy(xorriso->info_text, "Error with setting ACL of ");
2114 Text_shellsafe(path, xorriso->info_text, 1);
2115 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2116 }
2117 ret= 0; goto ex;
2118 }
2119 Xorriso_set_change_pending(xorriso, 0);
2120 ret= 1;
2121 ex:;
2122 return(ret);
2123 }
2124
2125
2126 /* @param in_node Opaque handle to IsoNode which is to be manipulated
2127 instead of path if it is not NULL.
2128 @param path is used as address if node is NULL.
2129 @param num_attrs Number of attributes
2130 @param names Array of pointers to 0 terminated name strings
2131 @param value_lengths Array of byte lengths for each attribute payload
2132 @param values Array of pointers to the attribute payload bytes
2133 @param flag bit0= Do not maintain eventual existing ACL of the node
2134 bit1= Do not clear the existing attribute list
2135 bit2= Delete the attributes with the given names
2136 bit3= Allow non-user attributes.
2137 bit4= do not warn of root if incapable of AAIP
2138 @return >0 success , <=0 failure
2139 */
2140 int Xorriso_setfattr(struct XorrisO *xorriso, void *in_node, char *path,
2141 size_t in_num_attrs, char **in_names,
2142 size_t *in_value_lengths, char **in_values, int flag)
2143 {
2144 int ret, block_isofs= 0, in_original= 1;
2145 size_t i, j, num_attrs;
2146 IsoNode *node;
2147 char **names, **values;
2148 size_t *value_lengths;
2149
2150 num_attrs= in_num_attrs;
2151 names= in_names;
2152 value_lengths= in_value_lengths;
2153 values= in_values;
2154
2155 node= (IsoNode *) in_node;
2156 if(node == NULL) {
2157 ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
2158 if(ret<=0)
2159 goto ex;
2160 }
2161 if((xorriso->do_aaip & 1024) && !(flag & 8)) {
2162 flag|= 8;
2163 block_isofs= 1;
2164 for(i= 0; i < in_num_attrs; i++) {
2165 if(strncmp(in_names[i], "isofs.", 6) == 0) {
2166 if(in_original) {
2167 strcpy(xorriso->info_text,
2168 "Attempt to set xattr from namespace \"isofs\" to ");
2169 Text_shellsafe(path, xorriso->info_text, 1);
2170 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
2171 ret= Xorriso_eval_problem_status(xorriso, 0, 0);
2172 if(ret < 0) {
2173 ret= 0; goto ex;
2174 }
2175 /* Switch to copy mode and omit isofs names */
2176 Xorriso_alloc_meM(names, char *, num_attrs);
2177 Xorriso_alloc_meM(value_lengths, size_t, num_attrs);
2178 Xorriso_alloc_meM(values, char *, num_attrs);
2179 in_original= 0;
2180 for(j= 0; j < i; j++) {
2181 names[j]= in_names[j];
2182 value_lengths[j]= in_value_lengths[j];
2183 values[j]= in_values[j];
2184 }
2185 num_attrs= i;
2186 }
2187 } else if(!in_original) {
2188 names[num_attrs]= in_names[i];
2189 value_lengths[num_attrs]= in_value_lengths[i];
2190 values[num_attrs]= in_values[i];
2191 num_attrs++;
2192 }
2193 }
2194 }
2195 if(num_attrs <= 0) {
2196 ret= 1; goto ex;
2197 }
2198
2199 ret= iso_node_set_attrs(node, num_attrs, names, value_lengths, values,
2200 (flag & (1 | 2 | 4 | 8)) | (block_isofs << 4));
2201 Xorriso_process_msg_queues(xorriso,0);
2202 if(ret <= 0) {
2203 Xorriso_report_iso_error(xorriso, "", ret,
2204 "Error when setting ACL and xattr to image node",
2205 0, "FAILURE", 1);
2206 if(path != NULL && path[0] != 0) {
2207 strcpy(xorriso->info_text, "Error with setting xattr of ");
2208 Text_shellsafe(path, xorriso->info_text, 1);
2209 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2210 }
2211 ret= 0; goto ex;
2212 }
2213 Xorriso_set_change_pending(xorriso, 0);
2214 ret= 1;
2215 ex:;
2216 Xorriso_process_msg_queues(xorriso, 0);
2217 if(!in_original) {
2218 Xorriso_free_meM(names);
2219 Xorriso_free_meM(value_lengths);
2220 Xorriso_free_meM(values);
2221 }
2222 return(ret);
2223 }
2224
2225
2226 /*
2227 @param flag bit0= use parameters dev,ino rather than disk_path
2228 bit1= compare attribute rather than setting it
2229 return: 0=dev,ino match, 1=mismatch, 2=no node attribute
2230 -1=error
2231 bit5= if not bit0:
2232 transfer dev,inode from eventual link target
2233 bit7= omit dev check mit bit1
2234 */
2235 int Xorriso_record_dev_inode(struct XorrisO *xorriso, char *disk_path,
2236 dev_t dev, ino_t ino,
2237 void *in_node, char *iso_path, int flag)
2238 {
2239 size_t l, di_l= 0;
2240 int i, ret;
2241 dev_t hdev;
2242 ino_t hino;
2243 char buf[66], *bufpt, *wpt, *di= NULL;
2244 static char *name= "isofs.di";
2245 struct stat stbuf;
2246
2247 if(!(flag & 1)) {
2248 if(flag & 32) {
2249 if(stat(disk_path, &stbuf) == -1)
2250 return(-1);
2251 } else {
2252 if(lstat(disk_path, &stbuf) == -1)
2253 return(-1);
2254 }
2255 dev= stbuf.st_dev;
2256 ino= stbuf.st_ino;
2257 }
2258
2259 wpt= buf;
2260 hdev= dev;
2261 for(i= 0; hdev != 0; i++)
2262 hdev= hdev >> 8;
2263 l= i;
2264 *(wpt++)= l;
2265 for(i= 0; i < (int) l; i++)
2266 *(wpt++)= dev >> (8 * (l - i - 1));
2267 hino= ino;
2268 for(i= 0; hino != 0; i++)
2269 hino= hino >> 8;
2270 l= i;
2271 *(wpt++)= l;
2272 for(i= 0; i < (int) l; i++)
2273 *(wpt++)= ino >> (8 * (l - i - 1));
2274 l= wpt - buf;
2275 bufpt= buf;
2276
2277 if(flag & 2) {
2278 /* Compare node attribute with bufpt,l */
2279 ret= Xorriso_get_attr_value(xorriso, in_node, iso_path,
2280 "isofs.di", &di_l, &di, 0);
2281 if(ret < 0)
2282 goto ex;
2283 if(ret == 0)
2284 {ret= 2; goto ex;}
2285 if(flag & 128) {
2286 if(di_l <= 0)
2287 {ret= 1; goto ex;}
2288 hino= 0;
2289 for(i= di[0] + 2; i < (int) di_l && i - di[0] - 2 < di[(int) di[0] + 1];
2290 i++)
2291 hino= (hino << 8) | ((unsigned char *) di)[i];
2292 if(hino != ino)
2293 {ret= 1; goto ex;}
2294 } else {
2295 if(l != di_l)
2296 {ret= 1; goto ex;}
2297 for(i= 0; i < (int) l; i++)
2298 if(di[i] != buf[i])
2299 {ret= 1; goto ex;}
2300 }
2301 ret= 0;
2302 } else {
2303 ret= Xorriso_setfattr(xorriso, in_node, iso_path,
2304 (size_t) 1, &name, &l, &bufpt, 2 | 8);
2305 }
2306 ex:;
2307 if(di != NULL)
2308 free(di);
2309 return(ret);
2310 }
2311
2312
2313 /* @return see Xorriso_update_interpreter()
2314 */
2315 int Xorriso_widen_hardlink(struct XorrisO *xorriso, void * boss_iter,
2316 IsoNode *node,
2317 char *abs_path, char *iso_prefix, char *disk_prefix,
2318 int flag)
2319 {
2320 int ret= 0, idx, low, high, i, do_widen= 0, compare_result= 0;
2321 char *disk_path;
2322
2323 Xorriso_alloc_meM(disk_path, char, SfileadrL);
2324
2325 /* Lookup all di_array instances of node */
2326 if(LIBISO_ISDIR(node))
2327 {ret= 3; goto ex;}
2328 ret= Xorriso_search_di_range(xorriso, node, &idx, &low, &high, 2);
2329 if(ret <= 0)
2330 {ret= 3; goto ex;}
2331 /* Check and reset di_do_widen bits */
2332 for(i= low; i <= high; i++) {
2333 if(node != xorriso->di_array[i]) /* might be NULL */
2334 continue;
2335 if(xorriso->di_do_widen[i / 8] & (1 << (i % 8)))
2336 do_widen= 1;
2337 xorriso->di_do_widen[i / 8]&= ~(1 << (i % 8));
2338 }
2339 if(idx < 0 || !do_widen)
2340 {ret= 3; goto ex;}
2341
2342 ret= Xorriso_pfx_disk_path(xorriso, abs_path, iso_prefix, disk_prefix,
2343 disk_path, 0);
2344 if(ret <= 0)
2345 goto ex;
2346 ret= Sfile_type(disk_path, 1);
2347 if(ret < 0)
2348 {ret= 3; goto ex;} /* does not exist on disk */
2349
2350 /* >>> compare_result bit17 = is_split */;
2351
2352 ret= Xorriso_update_interpreter(xorriso, boss_iter, NULL,
2353 compare_result, disk_path, abs_path, 1);
2354 if(ret <= 0)
2355 goto ex;
2356 ex:;
2357 Xorriso_free_meM(disk_path);
2358 return(ret);
2359 }
2360
2361
2362 int Xorriso_set_hidden(struct XorrisO *xorriso, void *in_node, char *path,
2363 int hide_state, int flag)
2364 {
2365 int ret, hide_attrs= 0;
2366 IsoNode *node;
2367
2368 node= (IsoNode *) in_node;
2369 if(node == NULL) {
2370 ret= Xorriso_get_node_by_path(xorriso, path, NULL, &node, 0);
2371 if(ret<=0)
2372 return(ret);
2373 }
2374 if(hide_state) {
2375 hide_attrs|= LIBISO_HIDE_BUT_WRITE;
2376 if(hide_state & 1)
2377 hide_attrs|= LIBISO_HIDE_ON_RR;
2378 if(hide_state & 2)
2379 hide_attrs|= LIBISO_HIDE_ON_JOLIET;
2380 if(hide_state & 4)
2381 hide_attrs|= LIBISO_HIDE_ON_HFSPLUS;
2382 }
2383 iso_node_set_hidden(node, hide_attrs);
2384 return(1);
2385 }
2386
2387
2388 /* @param flag bit0= increase only upper estimation
2389 */
2390 int Xorriso_estimate_file_size(struct XorrisO *xorriso, struct FindjoB *job,
2391 char *basename, mode_t st_mode, off_t st_size, int flag)
2392 {
2393 off_t upper, lower, size;
2394
2395 lower = 3 * strlen(basename) + 34; /* >>> + minimum RR ? */
2396 upper = 3 * strlen(basename) + 2048;
2397 if(S_ISREG(st_mode)) {
2398 size= ((st_size + (off_t) 2047) / (off_t) 2048) * (off_t) 2048;
2399 lower+= size;
2400 upper+= size;
2401 } else if(S_ISDIR(st_mode)) {
2402 upper+= 4096;
2403 }
2404 job->estim_upper_size+= upper;
2405 if(!(flag & 1))
2406 job->estim_lower_size+= lower;
2407 return(1);
2408 }
2409
2410
2411 /* @param flag bit0= do not compare but print input and back converted name
2412 */
2413 int Xorriso_test_outchar(struct XorrisO *xorriso, void *node_pt,
2414 int name_space, int flag)
2415 {
2416 IsoNode *node;
2417 char *result= NULL, *name, *back= NULL;
2418 int ret, relax_mem;
2419 size_t result_len, back_len, i;
2420 struct isoburn_imgen_opts *sopts= NULL;
2421
2422 relax_mem= xorriso->relax_compliance;
2423
2424 node= (IsoNode *) node_pt;
2425 ret= isoburn_igopt_new(&sopts, 0);
2426 if(ret<=0) {
2427 Xorriso_process_msg_queues(xorriso, 0);
2428 ret= -1; goto ex;
2429 }
2430 if(!(flag & 1))
2431 xorriso->relax_compliance|= isoburn_igopt_omit_version_numbers;
2432 ret= Xorriso_make_iso_write_opts(xorriso, NULL, sopts, 0);
2433 if(ret <= 0) {
2434 ret= -1; goto ex;
2435 }
2436
2437 if(iso_node_get_type(node) == LIBISO_DIR)
2438 name_space |= 256;
2439 name_space|= 512; /* no error messages */
2440
2441 name= (char *) iso_node_get_name(node);
2442 if(name == NULL) {
2443 ret= 1; goto ex;
2444 }
2445 ret= isoburn_conv_name_chars(sopts, name, strlen(name), &result, &result_len,
2446 name_space);
2447 if(ret <= 0) {
2448 Xorriso_process_msg_queues(xorriso, 0);
2449 if(flag & 1)
2450 goto print_outname;
2451 ret= 0; goto ex;
2452 }
2453
2454 /* Convert back and compare with original */
2455 ret= isoburn_conv_name_chars(sopts, result, result_len, &back, &back_len,
2456 name_space | (1 << 15));
2457 if(ret <= 0) {
2458 Xorriso_process_msg_queues(xorriso, 0);
2459 if(flag & 1)
2460 goto print_outname;
2461 ret= 0; goto ex;
2462 }
2463 if(flag & 1) {
2464 print_outname:;
2465 Text_shellsafe(name, xorriso->result_line, 0);
2466 strcat(xorriso->result_line, "\n");
2467 Xorriso_result(xorriso, 0);
2468 if(back == NULL)
2469 strcpy(xorriso->result_line, "(file name conversion error)");
2470 else
2471 Text_shellsafe(back, xorriso->result_line, 0);
2472 strcat(xorriso->result_line, "\n");
2473 Xorriso_result(xorriso, 0);
2474 strcpy(xorriso->result_line, "--\n");
2475 Xorriso_result(xorriso, 0);
2476 } else {
2477 for(i= 0; i < back_len; i++)
2478 if(name[i] != back[i])
2479 {ret= 0; goto ex;}
2480 if(name[i] != 0)
2481 {ret= 0; goto ex;}
2482 }
2483
2484 ret= 1;
2485 ex:;
2486 isoburn_igopt_destroy(&sopts, 0);
2487 if(result != NULL)
2488 free(result);
2489 if(back != NULL)
2490 free(back);
2491 xorriso->relax_compliance= relax_mem;
2492 return(ret);
2493 }
2494
2495
2496 int Xorriso_set_to_mtime(struct XorrisO *xorriso, char *show_path,
2497 IsoNode *node, int flag)
2498 {
2499 time_t t;
2500
2501 t= iso_node_get_mtime(node);
2502 iso_node_set_atime(node, t);
2503 iso_node_set_ctime(node, t);
2504 Xorriso_set_change_pending(xorriso, 0);
2505 return(1);
2506 }
2507
2508
2509 int Xorriso_cannot_create_iter(struct XorrisO *xorriso, int iso_error,int flag)
2510 {
2511 Xorriso_process_msg_queues(xorriso,0);
2512 Xorriso_report_iso_error(xorriso, "", iso_error, "Cannot create iter", 0,
2513 "FATAL", 1);
2514 sprintf(xorriso->info_text, "Cannot create IsoDirIter object");
2515 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
2516 return(1);
2517 }
2518
2519
2520 /* The caller shall make no assumptions about the meaning of iter, node_array,
2521 node_count, node_idx ! They are just opaque handles for which the caller
2522 provides the memory of proper type.
2523 @param flag bit0= initialize iteration
2524 bit1= action needs full freedom of object manipulation
2525 bit2= action needs LBA sorted iteration
2526 bit31= end iteration (mandatory !)
2527 */
2528 int Xorriso_findi_iter(struct XorrisO *xorriso, IsoDir *dir_node, off_t *mem,
2529 IsoDirIter **iter,
2530 IsoNode ***node_array, int *node_count, int *node_idx,
2531 IsoNode **iterated_node, int flag)
2532 {
2533 int ret, i;
2534 IsoNode *node;
2535 off_t new_mem= 0;
2536 char mem_text[80], limit_text[80];
2537
2538 if(flag&1) {
2539 *node_array= NULL;
2540 *node_count= -1;
2541 *node_idx= 0;
2542 *iter= NULL;
2543 ret= iso_dir_get_children(dir_node, iter);
2544 if(ret<0) {
2545 cannot_iter:;
2546 Xorriso_cannot_create_iter(xorriso, ret, 0);
2547 return(-1);
2548 }
2549 if((flag&2)|(flag&4)) {
2550 /* copy list of nodes and prepare soft iterator */
2551 *node_count= 0;
2552 while(iso_dir_iter_next(*iter, &node) == 1)
2553 (*node_count)++;
2554 iso_dir_iter_free(*iter);
2555 *iter= NULL;
2556
2557 new_mem= ((*node_count)+1) * sizeof(IsoNode *);
2558 if(new_mem > xorriso->temp_mem_limit) {
2559 Sfile_scale((double) new_mem, mem_text, 5,1e4, 0);
2560 Sfile_scale((double) xorriso->temp_mem_limit, limit_text, 5,1e4, 0);
2561 sprintf(xorriso->info_text,
2562 "Stacked directory snapshots exceed -temp_mem_limit (%s > %s)",
2563 mem_text, limit_text);
2564 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
2565 *node_count= -1;
2566 return(-1);
2567 }
2568 (*node_array)= (IsoNode **) calloc((*node_count)+1, sizeof(IsoNode *));
2569 if(*node_array == NULL) {
2570 sprintf(xorriso->info_text,
2571 "Could not allocate inode list of %.f bytes",
2572 ((double) (*node_count)+1) * (double) sizeof(IsoNode *));
2573 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
2574 *node_count= -1;
2575 return(-1);
2576 }
2577 *mem= new_mem;
2578 ret= iso_dir_get_children(dir_node, iter);
2579 if(ret<0)
2580 goto cannot_iter;
2581 while(iso_dir_iter_next(*iter, &node) == 1 && *node_idx < *node_count) {
2582 (*node_array)[*node_idx]= node;
2583 iso_node_ref(node);
2584 (*node_idx)++;
2585 }
2586 iso_dir_iter_free(*iter);
2587 *iter= NULL;
2588 *node_count= *node_idx;
2589 *node_idx= 0;
2590 if((flag&4) && *node_count>1)
2591 qsort(*node_array, *node_count, sizeof(IsoNode *),
2592 Xorriso__node_lba_cmp);
2593 }
2594 }
2595
2596 if(flag&(1u<<31)) {
2597 if(*node_count>=0 && *node_array!=NULL) {
2598 for(i= 0; i<*node_count; i++)
2599 iso_node_unref((*node_array)[i]);
2600 free(*node_array);
2601 *node_array= NULL;
2602 *node_count= -1;
2603 *node_idx= 0;
2604 } else {
2605 if(*iter!=NULL)
2606 iso_dir_iter_free(*iter);
2607 *iter= NULL;
2608 }
2609 }
2610
2611 if(flag&(1|(1u<<31)))
2612 return(1);
2613 if(*node_count>=0) {
2614 /* return next node_array element */
2615 if(*node_idx>=*node_count)
2616 return(0);
2617 *iterated_node= (*node_array)[*node_idx];
2618 (*node_idx)++;
2619 } else {
2620 ret= iso_dir_iter_next(*iter, iterated_node);
2621 return(ret == 1);
2622 }
2623 return(1);
2624 }
2625
2626
2627 /* @param flag bit0= not a command parameter (directory iteration or recursion)
2628 bit1= do not count deleted files with rm and rm_r
2629 @return <=0 error,
2630 1=ok
2631 2=ok, node has been deleted,
2632 3=ok, do not dive into directory (e.g. because it is a split file)
2633 4=ok, end findjob gracefully
2634 */
2635 int Xorriso_findi_action(struct XorrisO *xorriso, struct FindjoB *job,
2636 IsoDirIter *boss_iter, off_t boss_mem,
2637 char *abs_path, char *show_path,
2638 IsoNode *node, int depth, int flag)
2639 {
2640 int ret= 0, type, action= 0, hflag, deleted= 0, no_dive= 0, i, bless_idx;
2641 int unbless= 0;
2642 uid_t user= 0;
2643 gid_t group= 0;
2644 time_t date= 0;
2645 mode_t mode_or= 0, mode_and= ~1;
2646 char *target, *text_2, *iso_prefix, md5[16], *basename, bless_code[17];
2647 char crtp[10];
2648 struct FindjoB *subjob;
2649 struct stat dir_stbuf, stbuf;
2650 void *xinfo;
2651 struct iso_hfsplus_xinfo_data *hfsplus_xinfo;
2652 size_t value_length;
2653 char *value;
2654
2655 action= Findjob_get_action_parms(job, &target, &text_2, &user, &group,
2656 &mode_and, &mode_or, &type, &date, &subjob, 0);
2657 if(action<0)
2658 action= 0;
2659 job->match_count++;
2660
2661 hflag= 16*!(flag&2);
2662 ret= 1;
2663 if(action==1) { /* rm (including rmdir) */
2664 ret= Xorriso_fake_stbuf(xorriso, abs_path, &dir_stbuf, &node, 1);
2665 if(ret>0) {
2666 if(S_ISDIR(dir_stbuf.st_mode))
2667 hflag= 2;
2668 ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, hflag);
2669 deleted= 1;
2670 }
2671 } else if(action==2) { /* rm_r */
2672 ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, 1|hflag);
2673 deleted= 1;
2674 } else if(action==3) {
2675
2676 /* >>> mv target */;
2677
2678 } else if(action==4) { /* chown */
2679 ret= Xorriso_set_uid(xorriso, abs_path, user, 0);
2680 } else if(action==5) { /* chgrp */
2681 ret= Xorriso_set_gid(xorriso, abs_path, group, 0);
2682 } else if(action==6) { /* chmod */
2683 ret= Xorriso_set_st_mode(xorriso, abs_path, mode_and, mode_or, 0);
2684 } else if(action==7) { /* alter_date */
2685 ret= Xorriso_set_time(xorriso, abs_path, date, type&7);
2686 } else if(action==8) { /* lsdl */
2687 ret= Xorriso_ls_filev(xorriso, "", 1, &abs_path, (off_t) 0, 1|2|8);
2688 } else if(action>=9 && action<=13) { /* actions which have own findjobs */
2689 Findjob_set_start_path(subjob, abs_path, 0);
2690 ret= Xorriso_findi(xorriso, subjob, boss_iter, boss_mem, NULL,
2691 abs_path, &dir_stbuf, depth, 1);
2692 } else if(action==14 || action==17 || action == 41) {
2693 /* compare , update , update_merge */
2694 Findjob_get_start_path(job, &iso_prefix, 0);
2695 ret= Xorriso_find_compare(xorriso, (void *) boss_iter, (void *) node,
2696 abs_path, iso_prefix, target,
2697 (action == 17 || action == 41)
2698 | ((flag&1)<<1) | ((action == 41) << 2));
2699 if(ret==2)
2700 deleted= 1;
2701 if(ret==3)
2702 no_dive= 1;
2703 if(ret>=0)
2704 ret= 1;
2705 } else if(action==16 || action==18) { /* not_in_iso , add_missing */
2706 ;
2707 } else if(action == 21) { /* report_damage */
2708 ret= Xorriso_report_damage(xorriso, show_path, node, 0);
2709 } else if(action == 22) {
2710 ret= Xorriso_report_lba(xorriso, show_path, node,
2711 &job->last_data_file_block, 0);
2712 } else if(action == 23) { /* internal: memorize path of last matching node */
2713 ret= Findjob_set_found_path(job, show_path, 0);
2714 } else if(action == 24) {
2715 ret= Xorriso_getfacl(xorriso, (void *) node, show_path, NULL, 0);
2716 } else if(action == 25) {
2717 if(target == NULL || target[0] || text_2 == NULL || text_2[0])
2718 ret= Xorriso_setfacl(xorriso, (void *) node, show_path, target, text_2,0);
2719 } else if(action == 26) {
2720 ret= Xorriso_getfattr(xorriso, (void *) node, show_path, NULL, 0);
2721 } else if(action == 27) {
2722 ret= Xorriso_path_setfattr(xorriso, (void *) node, show_path,
2723 target, strlen(text_2), text_2, 0);
2724 } else if(action == 28) { /* set_filter */
2725 ret= Xorriso_set_filter(xorriso, (void *) node, show_path, target, 1 | 2);
2726 } else if(action == 29 || action == 52) { /* show_stream , show_stream_id */
2727 ret= Xorriso_show_stream(xorriso, (void *) node, show_path, (action == 52));
2728 } else if(action == 30) { /* internal: count */
2729 xorriso->node_counter++;
2730 } else if(action == 31) { /* internal: register */
2731 if(xorriso->node_counter < xorriso->node_array_size) {
2732 xorriso->node_array[xorriso->node_counter++]= (void *) node;
2733 iso_node_ref(node); /* In case node gets deleted from tree during
2734 the lifetime of xorriso->node_array */
2735 }
2736 } else if(action == 32) { /* internal: widen_hardlinks disk_equiv */
2737 Findjob_get_start_path(job, &iso_prefix, 0);
2738 ret= Xorriso_widen_hardlink(xorriso, (void *) boss_iter, node, abs_path,
2739 iso_prefix, target, 0);
2740 if(ret==2)
2741 deleted= 1;
2742 } else if(action == 33) { /* get_any_xattr */
2743 ret= Xorriso_getfattr(xorriso, (void *) node, show_path, NULL, 8);
2744 } else if(action == 34) { /* get_md5 */
2745 ret= Xorriso_get_md5(xorriso, (void *) node, show_path, md5, 0);
2746 if(ret >= 0)
2747 ret= 1;
2748 } else if(action == 35) { /* check_md5 */
2749 ret= Xorriso_check_md5(xorriso, (void *) node, show_path, 2);
2750 if(ret == 0)
2751 xorriso->find_check_md5_result|= 1;
2752 else if(ret < 0)
2753 xorriso->find_check_md5_result|= 2;
2754 else if(ret == 1)
2755 xorriso->find_check_md5_result|= 8;
2756 else if(ret == 2)
2757 xorriso->find_check_md5_result|= 4;
2758 if(ret >= 0)
2759 ret= 1;
2760 } else if(action == 36) { /* make_md5 */
2761 ret= Xorriso_make_md5(xorriso, (void *) node, show_path, 0);
2762 if(ret >= 0)
2763 ret= 1;
2764 } else if(action == 37) { /* mkisofs_r */
2765 ret= Xorriso_mkisofs_lower_r(xorriso, node, 0);
2766 } else if(action == 38) { /* sort_weight */
2767 iso_node_set_sort_weight(node, type);
2768 Xorriso_set_change_pending(xorriso, 0);
2769 } else if(action == 39) { /* hide */
2770 Xorriso_set_hidden(xorriso, node, NULL, type, 0);
2771 } else if(action == 40) { /* estimate_size */
2772 basename= strrchr(abs_path, '/');
2773 if(basename != NULL)
2774 basename++;
2775 else
2776 basename= abs_path;
2777 ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
2778 if(ret > 0)
2779 ret= Xorriso_estimate_file_size(xorriso, job, basename, stbuf.st_mode,
2780 stbuf.st_size, 0);
2781 } else if(action == 42) { /* rm_merge */
2782 ret= Xorriso_mark_update_merge(xorriso, show_path, node, 2 | 4);
2783 if(ret == 2) {
2784 ret= Xorriso_rmi(xorriso, boss_iter, boss_mem, abs_path, 1|hflag);
2785 sprintf(xorriso->info_text, "Deleted ");
2786 Text_shellsafe(show_path, xorriso->info_text, 1);
2787 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
2788 deleted= 1;
2789 }
2790 } else if(action == 43) { /* clear_merge */
2791 ret= Xorriso_mark_update_merge(xorriso, show_path, node, 2 | 4);
2792 } else if(action == 44) { /* list_extattr */
2793 ret= Xorriso_list_extattr(xorriso, (void *) node, show_path, show_path,
2794 target, 0);
2795 } else if(action == 45) { /* set_hfs_crtp */
2796 ret= Xorriso_hfsplus_file_creator_type(xorriso, show_path, (void *) node,
2797 target, text_2, 0);
2798
2799 } else if(action == 46) { /* get_hfs_crtp */
2800 ret= iso_node_get_xinfo(node, iso_hfsplus_xinfo_func, &xinfo);
2801 if(ret < 0) {
2802 Xorriso_process_msg_queues(xorriso, 0);
2803 ret= 0;
2804 } else if(ret == 1) {
2805 hfsplus_xinfo= (struct iso_hfsplus_xinfo_data *) xinfo;
2806 for(i= 0; i < 4; i++)
2807 xorriso->result_line[i]= hfsplus_xinfo->creator_code[i];
2808 xorriso->result_line[4]= ' ';
2809 for(i= 0; i < 4; i++)
2810 xorriso->result_line[5 + i]= hfsplus_xinfo->type_code[i];
2811 xorriso->result_line[9]= ' ';
2812 xorriso->result_line[10]= 0;
2813 Text_shellsafe(show_path, xorriso->result_line, 1);
2814 strcat(xorriso->result_line, "\n");
2815 Xorriso_result(xorriso, 0);
2816 }
2817 ret= 1;
2818 } else if(action == 47) { /* set_hfs_bless */
2819 if(strcmp(target, "none") == 0 ||
2820 strcmp(target, "n") == 0 || strcmp(target, "N") == 0) {
2821 ret= Xorriso_get_blessing(xorriso, node, &bless_idx, bless_code, 0);
2822 if(ret < 0)
2823 return(ret);
2824 if(ret == 0)
2825 return(1);
2826 unbless= 1;
2827 }
2828 ret= Xorriso_hfsplus_bless(xorriso, show_path, (void *) node, target, 0);
2829 /* If successful, end -find run gracefully */
2830 if(ret > 0) {
2831 if(unbless) {
2832 sprintf(xorriso->info_text, "HFS blessing '%s' revoked from ",
2833 bless_code);
2834 } else {
2835 sprintf(xorriso->info_text, "HFS blessing '%s' issued to ", target);
2836 }
2837 Text_shellsafe(show_path, xorriso->info_text, 1);
2838 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
2839 }
2840 if(!unbless)
2841 return(4);
2842 } else if(action == 48) { /* get_hfs_bless */
2843 ret= Xorriso_get_blessing(xorriso, node, &bless_idx, bless_code, 0);
2844 if (ret > 0) {
2845 sprintf(xorriso->result_line, "%-16.16s ", bless_code);
2846 Text_shellsafe(show_path, xorriso->result_line, 1);
2847 strcat(xorriso->result_line, "\n");
2848 Xorriso_result(xorriso, 0);
2849 } else if(ret == 0)
2850 ret= 1;
2851 } else if(action == 49) {
2852 /* internal: update creator, type, and blessings from persistent isofs.* */
2853 ret= Xorriso_get_attr_value(xorriso, node, show_path, "isofs.hx",
2854 &value_length, &value, 0);
2855 if(ret < 0)
2856 return(ret);
2857 if(ret > 0) {
2858 if(value_length >= 10) {
2859 ret= Xorriso_hfsplus_file_creator_type(xorriso, show_path,
2860 (void *) node,
2861 value + 2, value + 6, 4);
2862 } else
2863 ret= 1;
2864 free(value);
2865 if(ret <= 0)
2866 return(ret);
2867 }
2868 ret= Xorriso_get_attr_value(xorriso, node, show_path, "isofs.hb",
2869 &value_length, &value, 0);
2870 if(ret < 0)
2871 return(ret);
2872 if(ret > 0) {
2873 if(value_length >= 1) {
2874 bless_code[0]= value[0];
2875 bless_code[1]= 0;
2876 ret= Xorriso_hfsplus_bless(xorriso, show_path, (void *) node,
2877 bless_code, 0);
2878 } else
2879 ret= 1;
2880 free(value);
2881 if(ret <= 0)
2882 return(ret);
2883 }
2884 ret= 1;
2885
2886 } else if(action == 50) { /* print_outname */
2887 ret= Xorriso_test_outchar(xorriso, (void *) node, type, 1);
2888 if(ret <= 0)
2889 return(ret);
2890
2891 } else if(action == 51) { /* report_sections */
2892 ret= Xorriso_report_lba(xorriso, show_path, node,
2893 &job->last_data_file_block, 1);
2894
2895 } else if(action == 53) { /* internal: show_hfs_cmd */
2896 ret= Xorriso_get_blessing(xorriso, node, &bless_idx, bless_code, 0);
2897 if (ret > 0) {
2898 if(xorriso->show_hfs_cmd_flag & 2) {
2899 sprintf(xorriso->result_line, "-hfs-bless-by %s ", bless_code);
2900 Text_shellsafe(show_path, xorriso->result_line, 1);
2901 } else {
2902 sprintf(xorriso->result_line, "-find ");
2903 Text_shellsafe(show_path, xorriso->result_line, 1);
2904 sprintf(xorriso->result_line + strlen(xorriso->result_line),
2905 " -exec set_hfs_bless %s --", bless_code);
2906 }
2907 ret= Xorriso_record_cmd_line(xorriso, xorriso->result_line,
2908 xorriso->show_hfs_cmds,
2909 &xorriso->show_hfs_cmd_count,
2910 (xorriso->show_hfs_cmd_flag & 1));
2911 if(ret <= 0)
2912 return(ret);
2913 }
2914 ret= iso_node_get_xinfo(node, iso_hfsplus_xinfo_func, &xinfo);
2915 if(ret < 0) {
2916 Xorriso_process_msg_queues(xorriso, 0);
2917 ret= 0;
2918 } else if(ret == 1) {
2919 hfsplus_xinfo= (struct iso_hfsplus_xinfo_data *) xinfo;
2920 for(i= 0; i < 4; i++)
2921 crtp[i]= hfsplus_xinfo->creator_code[i];
2922 crtp[4]= ' ';
2923 for(i= 0; i < 4; i++)
2924 crtp[5 + i]= hfsplus_xinfo->type_code[i];
2925 crtp[9]= 0;
2926 if(xorriso->show_hfs_cmd_flag & 2) {
2927 sprintf(xorriso->result_line, "-hfsplus-file-creator-type %s ", crtp);
2928 Text_shellsafe(show_path, xorriso->result_line, 1);
2929 } else {
2930 sprintf(xorriso->result_line, "-find ");
2931 Text_shellsafe(show_path, xorriso->result_line, 1);
2932 sprintf(xorriso->result_line + strlen(xorriso->result_line),
2933 " -exec set_hfs_crtp %s --", crtp);
2934 }
2935 ret= Xorriso_record_cmd_line(xorriso, xorriso->result_line,
2936 xorriso->show_hfs_cmds,
2937 &xorriso->show_hfs_cmd_count,
2938 (xorriso->show_hfs_cmd_flag & 1));
2939 if(ret <= 0)
2940 return(ret);
2941 }
2942 ret= 1;
2943
2944 } else if(action == 54 || action == 56) { /* internal: truncate_name */
2945 ret= Xorriso_truncate_uniquely(xorriso, xorriso->file_name_limit,
2946 node, abs_path, show_path,
2947 2 * (action == 56));
2948
2949 } else if(action == 55 || action == 57) {
2950 /* internal: unique_trunc_test length (in type) */
2951 ret= Xorriso_truncate_uniquely(xorriso, type, node, abs_path, show_path,
2952 1 | (2 * (action == 57)));
2953
2954 } else if(action == 58) { /* internal: last_data_file_block */
2955 ret= Xorriso_report_lba(xorriso, show_path, node,
2956 &job->last_data_file_block, 2);
2957
2958 } else if(action == 59) { /* set_to_mtime */
2959 ret= Xorriso_set_to_mtime(xorriso, show_path, node, 0);
2960
2961 } else { /* includes : 15 in_iso */
2962 Xorriso_esc_filepath(xorriso, show_path, xorriso->result_line, 0);
2963 strcat(xorriso->result_line, "\n");
2964 Xorriso_result(xorriso, 0);
2965 ret= 1;
2966 }
2967 if(ret<=0)
2968 return(ret);
2969 if(deleted)
2970 return(2);
2971 if(no_dive)
2972 return(3);
2973 return(1);
2974 }
2975
2976
2977 /* flag bit0= perform -disk_path rather than -disk_name
2978 bit0= use_pattern
2979 */
2980 int Exprtest_match_disk_name(struct XorrisO *xorriso, struct ExprtesT *ftest,
2981 IsoNode *node, int flag)
2982
2983 {
2984 int ret;
2985 char *disk_path= NULL, *npt;
2986 regmatch_t name_match;
2987 char *arg1;
2988 void *arg2;
2989
2990 Xorriso_alloc_meM(disk_path, char, SfileadrL);
2991
2992 ret= Xorriso_retrieve_disk_path(xorriso, node, disk_path, 0);
2993 if(ret <= 0)
2994 {ret= 0; goto ex;}
2995 if(flag & 1) {
2996 if(strcmp(disk_path, ftest->arg1) == 0)
2997 {ret= 1; goto ex;}
2998 {ret= 0; goto ex;}
2999 }
3000 arg1= (char *) ftest->arg1;
3001 arg2= ftest->arg2;
3002 npt= strrchr(disk_path, '/');
3003 if(npt != NULL)
3004 npt++;
3005 else
3006 npt= disk_path;
3007 if(flag & 2) {
3008 ret= ! regexec(arg2, npt, 1, &name_match, 0);
3009 } else {
3010 ret= (strcmp(arg1, npt) == 0);
3011 }
3012 ex:;
3013 Xorriso_free_meM(disk_path);
3014 return(ret);
3015 }
3016
3017
3018 int Exprtest_match(struct XorrisO *xorriso, struct ExprtesT *ftest,
3019 void *node_pt, char *name, char *path,
3020 struct stat *boss_stbuf, struct stat *stbuf, int flag)
3021 /*
3022 return:
3023 <0 = error
3024 0 = does not match
3025 1 = does match
3026 2 = immediate decision : does not match
3027 3 = immediate decision : does match
3028 */
3029 {
3030 int value=0, ret, start_lba, end_lba, bless_idx;
3031 int lba_count, *file_end_lbas= NULL, *file_start_lbas= NULL, i, mask;
3032 void *arg1, *arg2;
3033 char ft, *decision, md5[16], bless_code[17];
3034 regmatch_t name_match;
3035 off_t damage_start, damage_end, size, *section_sizes= NULL;
3036 void *xinfo_dummy;
3037 IsoNode *node;
3038 IsoStream *stream;
3039 struct iso_hfsplus_xinfo_data *hfsplus_xinfo;
3040
3041 if(ftest == NULL)
3042 return(1);
3043
3044 node= (IsoNode *) node_pt;
3045 arg1= ftest->arg1;
3046 arg2= ftest->arg2;
3047
3048 if(node == NULL) {
3049 switch(ftest->test_type) {
3050 case 0: case 1: case 2: case 4: case 11: case 12: case 13:
3051 case 22: case 23: case 25: case 26:
3052 /* Tests which need no node parameter */
3053 break;
3054 default:
3055 value= 0;
3056 goto ex;
3057 }
3058 }
3059
3060 switch(ftest->test_type) {
3061 case 0: /* -false */
3062 value= 0;
3063
3064 break; case 1: /* -name *arg1 (regex in *arg2) */
3065 if (ftest->boss->use_pattern) {
3066 ret= regexec(arg2, name, 1, &name_match, 0);
3067 value= !ret;
3068 } else {
3069 value= (strcmp((char *) arg1, name) == 0);
3070 }
3071
3072 break; case 2: /* -type *arg1 */
3073 value= 1;
3074 ft= *((char *) arg1);
3075 if(ft!=0) {
3076 if(S_ISBLK(stbuf->st_mode)) {
3077 if(ft!='b')
3078 value= 0;
3079 } else if(S_ISCHR(stbuf->st_mode)) {
3080 if(ft!='c')
3081 value= 0;
3082 } else if(S_ISDIR(stbuf->st_mode)) {
3083 if(ft=='m') {
3084 if(node != NULL)
3085 value= 0;
3086 else if(boss_stbuf==NULL)
3087 value= 0;
3088 else if(boss_stbuf->st_dev == stbuf->st_dev)
3089 value= 0;
3090 } else if(ft!='d')
3091 value= 0;
3092 } else if(S_ISFIFO(stbuf->st_mode)) {
3093 if(ft!='p')
3094 value= 0;
3095 } else if(S_ISREG(stbuf->st_mode)) {
3096 if(ft!='f' && ft!='-')
3097 value= 0;
3098 } else if(((stbuf->st_mode)&S_IFMT)==S_IFLNK) {
3099 if(ft!='l')
3100 value= 0;
3101 } else if(((stbuf->st_mode)&S_IFMT)==S_IFSOCK) {
3102 if(ft!='s')
3103 value= 0;
3104 } else if((flag & 1) && ((stbuf->st_mode) & S_IFMT) == Xorriso_IFBOOT) {
3105 if(ft!='e' || node == NULL)
3106 value= 0;
3107 } else {
3108 if(ft!='X')
3109 value= 0;
3110 }
3111 }
3112
3113 break; case 3: /* -damaged */;
3114 value= Xorriso_file_eval_damage(xorriso, node, &damage_start, &damage_end,
3115 0);
3116 if(value > 0)
3117 value= 1;
3118
3119 break; case 4: /* -lba_range *arg1 *arg2 */
3120 value= 1;
3121 start_lba= *((int *) ftest->arg1);
3122 end_lba= *((int *) ftest->arg2);
3123 if(node == NULL) {
3124 value= !(start_lba >= 0);
3125 goto ex;
3126 }
3127 ret= Xorriso__start_end_lbas(node, &lba_count, &file_start_lbas,
3128 &file_end_lbas, §ion_sizes, &size, 0);
3129 if(ret <= 0) {
3130 if(ret < 0)
3131 Xorriso_process_msg_queues(xorriso, 0);
3132 if(start_lba >= 0)
3133 value= 0;
3134 } else {
3135 for(i= 0; i < lba_count; i++) {
3136 if(start_lba >= 0) {
3137 if(file_end_lbas[i] < start_lba || file_start_lbas[i] > end_lba)
3138 value= 0;
3139 } else {
3140 if(file_end_lbas[i] >= -start_lba && file_start_lbas[i] <= -end_lba)
3141 value= 0;
3142 }
3143 }
3144 }
3145
3146 break; case 5: /* -has_acl */
3147 ret = Xorriso_getfacl(xorriso, (void *) node, "", NULL, 2);
3148 if(ret <= 0) {
3149 value= -1;
3150 Xorriso_process_msg_queues(xorriso, 0);
3151 goto ex;
3152 }
3153 value= (ret == 1);
3154
3155 break; case 6: /* -has_xattr */
3156 case 14: /* -has_any_xattr */
3157 ret = Xorriso_getfattr(xorriso, (void *) node, "", NULL,
3158 64 | (8 * (ftest->test_type == 14)));
3159 if(ret < 0) {
3160 value= -1;
3161 Xorriso_process_msg_queues(xorriso, 0);
3162 goto ex;
3163 }
3164 value= (ret > 0);
3165
3166 break; case 7: /* -has_aaip */
3167 ret= iso_node_get_xinfo(node, aaip_xinfo_func, &xinfo_dummy);
3168 if(ret < 0) {
3169 value= -1;
3170 Xorriso_process_msg_queues(xorriso, 0);
3171 goto ex;
3172 }
3173 value= (ret > 0);
3174
3175 break; case 8: /* -has_filter */
3176 value= 0;
3177 if(LIBISO_ISREG(node)) {
3178 stream= iso_file_get_stream((IsoFile *) node);
3179 if(iso_stream_get_input_stream(stream, 0) != NULL)
3180 value= 1;
3181 }
3182
3183 break; case 9: /* -wanted_node arg1 (for internal use) */
3184 value= (((IsoNode *) arg1) == node);
3185
3186 break; case 10: /* -pending_data */
3187 value= 1;
3188 if(!LIBISO_ISREG(node)) {
3189 value= 0;
3190 } else {
3191 ret= Xorriso__file_start_lba(node, &start_lba, 0);
3192 if(ret > 0 && start_lba >= 0)
3193 value= 0;
3194 }
3195
3196 break; case 11: /* -decision */
3197 value= 2;
3198 decision= (char *) arg1;
3199 if(strcmp(decision, "yes") == 0 || strcmp(decision, "true") == 0)
3200 value= 3;
3201
3202 break; case 12: /* -prune */
3203 value= 1;
3204 ftest->boss->prune= 1;
3205
3206 break; case 13: /* -wholename *arg1 (regex in *arg2) */
3207 if (ftest->boss->use_pattern) {
3208 ret= regexec(arg2, path, 1, &name_match, 0);
3209 value= !ret;
3210 } else {
3211 value= (strcmp(arg1, path) == 0);
3212 }
3213
3214 break; case 15: /* -has_md5 */
3215 ret= Xorriso_get_md5(xorriso, node, path, md5, 1);
3216 value= (ret > 0);
3217
3218 break; case 16: /* -disk_name *arg1 (regex in *arg2) */
3219 value= !! Exprtest_match_disk_name(xorriso, ftest, node,
3220 2 * (ftest->boss->use_pattern));
3221
3222 break; case 17: /* -hidden int *arg1 */
3223 value= 1;
3224 ret= iso_node_get_hidden(node);
3225 mask= *((int *) arg1) & 3;
3226 if((!!(mask & 1)) ^ (!!(ret & LIBISO_HIDE_ON_RR)))
3227 value= 0;
3228 if((!!(mask & 2)) ^ (!!(ret & LIBISO_HIDE_ON_JOLIET)))
3229 value= 0;
3230 if((!!(mask & 3)) ^ (!!(ret & LIBISO_HIDE_ON_HFSPLUS)))
3231 value= 0;
3232
3233 break; case 18: /* -has_hfs_crtp char *creator char *type */
3234 ret= iso_node_get_xinfo(node, iso_hfsplus_xinfo_func, &xinfo_dummy);
3235 value= 0;
3236 if(ret < 0) {
3237 Xorriso_process_msg_queues(xorriso, 0);
3238 ret= 0;
3239 } else if(ret == 1) {
3240 hfsplus_xinfo= (struct iso_hfsplus_xinfo_data *) xinfo_dummy;
3241 if((strlen(arg1) == 1 ||
3242 (strncmp(arg1, (char *) hfsplus_xinfo->creator_code, 4) == 0 &&
3243 strlen(arg1) == 4)) &&
3244 (strlen(arg2) == 1 ||
3245 (strncmp(arg2, (char *) hfsplus_xinfo->type_code, 4) == 0 &&
3246 strlen(arg2) == 4)))
3247 value= 1;
3248 }
3249
3250 break; case 19: /* -has_hfs_bless int bless_index */
3251 value= 0;
3252 ret= Xorriso_get_blessing(xorriso, node, &bless_idx, bless_code, 0);
3253 if (ret > 0) {
3254 if(*((int *) arg1) == (int) ISO_HFSPLUS_BLESS_MAX ||
3255 *((int *) arg1) == bless_idx)
3256 value= 1;
3257 }
3258
3259 break; case 20: /* -disk_path */
3260 value= !! Exprtest_match_disk_name(xorriso, ftest, node,
3261 1 | 2 * (ftest->boss->use_pattern));
3262
3263 break; case 21: /* -bad_outname */
3264 ret= Xorriso_test_outchar(xorriso, node, *((int *) arg1), 0);
3265 if(ret < 0) {
3266 value= -1;
3267 goto ex;
3268 }
3269 value= !ret; /* Xorriso_test_outchar() returns 1 for good and 0 for bad */
3270
3271 break; case 22: /* -use_pattern */
3272 ftest->boss->use_pattern= (strcmp(arg1, "off") != 0);
3273 value= 1;
3274
3275 break; case 23: /* -or_use_pattern */
3276 ftest->boss->use_pattern= (strcmp(arg1, "off") != 0);
3277 value= 0;
3278
3279 break; case 24: /* -name_limit_blocker */
3280 ret= Xorriso_truncate_uniquely(xorriso, *((int *) arg1), node, path, path,
3281 1 | 4);
3282 value= (ret == 0);
3283
3284 break; case 25: /* -maxdepth */
3285 value= (ftest->boss->depth <= *((int *) arg1));
3286
3287 break; case 26: /* -mindepth */
3288 value= (ftest->boss->depth >= *((int *) arg1));
3289
3290 break; default:
3291
3292 /* >>> complain about unknown test type */;
3293
3294 value= -1;
3295
3296 }
3297
3298 ex:;
3299 if(ftest->invert && value<=1 && value>=0)
3300 value= !value;
3301 if(file_start_lbas != NULL)
3302 free((char *) file_start_lbas);
3303 if(file_end_lbas != NULL)
3304 free((char *) file_end_lbas);
3305 if(section_sizes != NULL)
3306 free((char *) section_sizes);
3307 return(value);
3308 }
3309
3310
3311 /* @return <0 = error , 0 = no match , 1 = match */
3312 int Xorriso_findi_test(struct XorrisO *xorriso, struct FindjoB *job,
3313 IsoNode *node, char *name, char *path,
3314 struct stat *boss_stbuf, struct stat *stbuf,
3315 int depth, int flag)
3316 {
3317 int ret;
3318
3319 job->prune= 0;
3320 ret= Findjob_test_2(xorriso, job, node, name, path, boss_stbuf, stbuf, 1);
3321 if(ret <= 0)
3322 return(ret);
3323 return(1);
3324 }
3325
3326
3327 int Xorriso_findi_headline(struct XorrisO *xorriso, struct FindjoB *job,
3328 int flag)
3329 {
3330 int action;
3331
3332 action= Findjob_get_action(job, 0);
3333 if(action == 21) { /* report_damage */
3334 sprintf(xorriso->result_line, "Report layout: %8s , %8s , %8s , %s\n",
3335 "at byte", "Range", "Filesize", "ISO image path");
3336 Xorriso_result(xorriso, 0);
3337 } else if(action == 22 || action == 51) { /* report_lba, report_sections */
3338 sprintf(xorriso->result_line,
3339 "Report layout: %2s , %8s , %8s , %8s , %s\n",
3340 "xt", "Startlba", "Blocks", action == 22 ? "Filesize" : "Sectsize",
3341 "ISO image path");
3342 Xorriso_result(xorriso, 0);
3343 }
3344 return(1);
3345 }
3346
3347
3348 /* @param flag bit0= recursion
3349 bit1= do not count deleted files with rm and rm_r
3350 bit2= do not dive into split file directories
3351 (implicitly given with actions 14=compare and 17=update)
3352 @return <=0 error, 1= ok , 2= dir node and path has been deleted
3353 4= end gracefully
3354 */
3355 int Xorriso_findi(struct XorrisO *xorriso, struct FindjoB *job,
3356 void *boss_iter, off_t boss_mem,
3357 void *dir_node_generic, char *dir_path,
3358 struct stat *dir_stbuf, int depth, int flag)
3359 {
3360 int ret, action= 0, hflag, deleted= 0, no_dive= 0;
3361 IsoDirIter *iter= NULL;
3362 IsoDir *dir_node= NULL;
3363 IsoNode *node, *iso_node;
3364 IsoImage *volume= NULL;
3365 struct stat stbuf;
3366 char *name;
3367 off_t mem;
3368 IsoNode **node_array= NULL;
3369 int node_count= 0, node_idx;
3370 char *path= NULL, *abs_path= NULL;
3371
3372 job->depth= depth;
3373
3374 if(xorriso->request_to_abort)
3375 {ret= 0; goto ex;}
3376
3377 path= malloc(SfileadrL);
3378 abs_path= malloc(SfileadrL);
3379 if(path==NULL || abs_path==NULL) {
3380 Xorriso_no_malloc_memory(xorriso, &path, 0);
3381 {ret= -1; goto ex;}
3382 }
3383
3384 action= Findjob_get_action(job, 0);
3385 if(action<0)
3386 action= 0;
3387 if(!(flag & 1)) {
3388 Xorriso_findi_headline(xorriso, job, 0);
3389 job->last_data_file_block= 0;
3390 }
3391
3392 dir_node= (IsoDir *) dir_node_generic;
3393 if(dir_node==NULL) {
3394 ret= Xorriso_get_volume(xorriso, &volume, 0);
3395 if(ret<=0)
3396 {ret= -1; goto ex;}
3397 ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, dir_path, path, 1|2|4);
3398 if(ret<=0)
3399 goto ex;
3400 ret= Xorriso_node_from_path(xorriso, volume, path, &iso_node, 0);
3401 dir_node= (IsoDir *) iso_node;
3402 if(ret<=0)
3403 {ret= 0; goto ex;}
3404 ret= Xorriso_fake_stbuf(xorriso, "", dir_stbuf, &iso_node, 1);
3405 if(ret<=0)
3406 goto ex;
3407
3408 name= strrchr(dir_path, '/');
3409 if(name==NULL)
3410 name= dir_path;
3411 else
3412 name++;
3413
3414 ret= Xorriso_findi_test(xorriso, job, iso_node, name, path, NULL, dir_stbuf,
3415 depth, 0);
3416 if(ret<0)
3417 goto ex;
3418 if(job->prune)
3419 no_dive= 1;
3420 if(ret>0) {
3421 iso_node_ref(iso_node); /* protect from real disposal */
3422 ret= Xorriso_findi_action(xorriso, job,
3423 (IsoDirIter *) boss_iter, boss_mem,
3424 path, dir_path, iso_node, depth,
3425 flag&(1|2));
3426 deleted= (iso_node_get_parent(iso_node) == NULL); /* still in tree ? */
3427 iso_node_unref(iso_node); /* eventually do real disposal */
3428 if(xorriso->request_to_abort)
3429 {ret= 0; goto ex;}
3430 if(ret == 4)
3431 goto ex;
3432 if(ret<=0)
3433 goto ex;
3434 if(ret==2 || deleted) {
3435 /* re-determine dir_node in case it has a new persona */
3436 ret= Xorriso_node_from_path(xorriso, volume, path, &iso_node, 1);
3437 if(ret==0) {
3438 deleted= 1;
3439 {ret= 2; goto ex;}
3440 }
3441 if(ret<0)
3442 {ret= 0; goto ex;}
3443 dir_node= (IsoDir *) iso_node;
3444 ret= Xorriso_fake_stbuf(xorriso, "", dir_stbuf, &iso_node, 1);
3445 if(ret<=0)
3446 goto ex;
3447 }
3448 if(ret==3)
3449 no_dive= 1;
3450 }
3451 }
3452 if(no_dive || !LIBISO_ISDIR((IsoNode *) dir_node))
3453 {ret= 1; goto ex;}
3454 if(action == 14 || action == 17 || (flag & 4))
3455 if(Xorriso_is_split(xorriso, dir_path, (IsoNode *) dir_node, 1)>0)
3456 {ret= 1; goto ex;}
3457
3458 mem= boss_mem;
3459 hflag= 1;
3460 if(action==1 || action==2 || action==3 || action==17 || action == 28 ||
3461 action == 32 || action == 41 || action == 42)
3462 hflag|= 2; /* need freedom to manipulate image */
3463 if(action==14 || action==17 || action == 28 || action == 35 || action == 36 ||
3464 action == 41)
3465 hflag|= 4; /* need LBA sorted iteration for good data reading performance */
3466 ret= Xorriso_findi_iter(xorriso, dir_node, &mem,
3467 &iter, &node_array, &node_count, &node_idx,
3468 &node, hflag);
3469 if(ret<=0)
3470 goto ex;
3471 job->depth++;
3472 while(1) {
3473 ret= Xorriso_findi_iter(xorriso, dir_node, &mem, &iter,
3474 &node_array, &node_count, &node_idx, &node, 0);
3475 if(ret<0)
3476 goto ex;
3477 if(ret==0)
3478 break;
3479 name= (char *) iso_node_get_name(node);
3480 ret= Xorriso_make_abs_adr(xorriso, dir_path, name, path, 4);
3481 if(ret<=0)
3482 goto ex;
3483 ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
3484 if(ret<0)
3485 goto ex;
3486 if(ret==0)
3487 continue;
3488
3489 /* ??? This seems to be redundant with the single test above
3490 ??? Should i dive in unconditionally and leave out test and action here ?
3491 ??? Then do above test unconditionally ?
3492 --- Seems that the current configuration represents the special
3493 handling of the find start path with mount points. Dangerous to change.
3494 */
3495
3496 ret= Xorriso_findi_test(xorriso, job, node, name, path, dir_stbuf, &stbuf,
3497 depth, 0);
3498 if(ret<0)
3499 goto ex;
3500 if(job->prune)
3501 no_dive= 1;
3502 if(ret>0) {
3503 ret= Xorriso_make_abs_adr(xorriso, xorriso->wdi, path, abs_path, 1|2|4);
3504 if(ret<=0)
3505 goto ex;
3506 ret= Xorriso_findi_action(xorriso, job, iter, mem,
3507 abs_path, path, node, depth, 1|(flag&2));
3508 if(xorriso->request_to_abort)
3509 {ret= 0; goto ex;}
3510 if(ret == 4)
3511 goto ex;
3512 if(ret==2) { /* node has been deleted */
3513 /* re-determine node in case it has a new persona */
3514 if(volume==NULL) {
3515 ret= Xorriso_get_volume(xorriso, &volume, 0);
3516 if(ret<=0)
3517 {ret= -1; goto ex;}
3518 }
3519 ret= Xorriso_node_from_path(xorriso, volume, abs_path, &node, 1);
3520 if(ret==0)
3521 continue;
3522 if(ret<0)
3523 {ret= 0; goto ex;}
3524 ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1);
3525 if(ret<0)
3526 goto ex;
3527 if(ret==0)
3528 continue;
3529 }
3530 no_dive= (ret==3);
3531 if(ret<=0) {
3532 if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
3533 goto ex;
3534 }
3535 }
3536
3537 if(S_ISDIR(stbuf.st_mode) && !no_dive) {
3538 ret= Xorriso_findi(xorriso, job, (void *) iter, mem,
3539 (void *) node, path, &stbuf, depth+1, flag|1);
3540 if(ret<0)
3541 goto ex;
3542 if(xorriso->request_to_abort)
3543 {ret= 0; goto ex;}
3544 if(ret == 4)
3545 goto ex;
3546 }
3547 }
3548
3549 ret= 1;
3550 ex:;
3551 job->depth= depth;
3552 if(path!=NULL)
3553 free(path);
3554 if(abs_path!=NULL)
3555 free(abs_path);
3556 Xorriso_process_msg_queues(xorriso,0);
3557
3558 Xorriso_findi_iter(xorriso, dir_node, &mem, &iter, &node_array, &node_count,
3559 &node_idx, &node, (1u<<31));
3560 if(ret<=0)
3561 return(ret);
3562 if(deleted)
3563 return(2);
3564 return(1);
3565 }
3566
3567
3568 /* @param flag bit0= do not dive into trees
3569 bit1= do not perform job->action on resulting node array
3570 bit2= do not free node_array after all actions are done
3571 */
3572 int Xorriso_findi_sorted(struct XorrisO *xorriso, struct FindjoB *job,
3573 off_t boss_mem, int filec, char **filev, int flag)
3574 {
3575 int i, ret, find_flag= 0;
3576 struct FindjoB array_job, *proxy_job= NULL, *hindmost= NULL, *hmboss= NULL;
3577 struct stat dir_stbuf;
3578 IsoNode *node;
3579 char *abs_path= NULL;
3580 off_t mem_needed= 0;
3581
3582 array_job.start_path= NULL;
3583
3584 Xorriso_alloc_meM(abs_path, char, SfileadrL);
3585
3586 if(job->action == 14 || job->action == 17)
3587 find_flag|= 4;
3588 if(job->action>=9 && job->action<=13) { /* actions which have own findjobs */
3589 /* array_job replaces the hindmost job in the chain */
3590 for(hindmost= job; hindmost->subjob != NULL; hindmost= hindmost->subjob)
3591 hmboss= hindmost;
3592 if(hmboss == NULL)
3593 {ret= -1; goto ex;}
3594 memcpy(&array_job, hindmost, sizeof(struct FindjoB));
3595 hmboss->subjob= &array_job;
3596 proxy_job= job;
3597 } else {
3598 memcpy(&array_job, job, sizeof(struct FindjoB));
3599 proxy_job= &array_job;
3600 hindmost= job;
3601 }
3602 array_job.start_path= NULL; /* is owned by the original, not by array_job */
3603
3604 /* Count matching nodes */
3605 Xorriso_destroy_node_array(xorriso, 0);
3606 array_job.action= 30; /* internal: count */
3607 for(i= 0; i < filec; i++) {
3608 if(flag & 1) {
3609 xorriso->node_counter++;
3610 continue;
3611 }
3612 ret= Findjob_set_start_path(proxy_job, filev[i], 0);
3613 if(ret <= 0)
3614 goto ex;
3615 ret= Xorriso_findi(xorriso, proxy_job, NULL, boss_mem, NULL,
3616 filev[i], &dir_stbuf, 0, find_flag);
3617 if(ret <= 0)
3618 goto ex;
3619 }
3620 if(xorriso->node_counter <= 0)
3621 {ret= 1; goto ex;}
3622
3623 mem_needed= boss_mem + xorriso->node_counter * sizeof(IsoNode *);
3624 if(!(flag &1)) {
3625 ret= Xorriso_check_temp_mem_limit(xorriso, mem_needed, 0);
3626 if(ret <= 0) {
3627 /* Memory curbed : Perform unsorted find jobs */
3628 if(hmboss != NULL)
3629 hmboss->subjob= hindmost;
3630 for(i= 0; i < filec; i++) {
3631 ret= Findjob_set_start_path(job, filev[i], 0);
3632 if(ret <= 0)
3633 goto ex;
3634 ret= Xorriso_findi(xorriso, job, NULL, boss_mem, NULL,
3635 filev[i], &dir_stbuf, 0, find_flag);
3636 if(ret <= 0)
3637 if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
3638 goto ex;
3639 }
3640 {ret= 1; goto ex;}
3641 }
3642 }
3643
3644 /* Copy matching nodes into allocated array */
3645 ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit, 0, 0);
3646 if(ret <= 0)
3647 goto ex;
3648 array_job.action= 31; /* internal: register */
3649 xorriso->node_counter= 0;
3650 for(i= 0; i < filec; i++) {
3651 if(flag & 1) {
3652 ret= Xorriso_get_node_by_path(xorriso, filev[i], NULL, &node, 0);
3653 if(ret <= 0)
3654 goto ex;
3655 if(xorriso->node_counter < xorriso->node_array_size) {
3656 xorriso->node_array[xorriso->node_counter++]= (void *) node;
3657 iso_node_ref(node);
3658 }
3659 continue;
3660 }
3661 ret= Findjob_set_start_path(proxy_job, filev[i], 0);
3662 if(ret <= 0)
3663 goto ex;
3664 ret= Xorriso_findi(xorriso, proxy_job, NULL, mem_needed, NULL,
3665 filev[i], &dir_stbuf, 0, find_flag);
3666 if(ret <= 0)
3667 goto ex;
3668 }
3669
3670 Xorriso_sort_node_array(xorriso, 0);
3671 if(flag & 2)
3672 {ret= 1; goto ex;}
3673
3674 /* Perform job->action on xorriso->node_array */
3675
3676 /* Headlines of actions report_damage , report_lba */;
3677 Xorriso_findi_headline(xorriso, job, 0);
3678
3679 for(i= 0; i < xorriso->node_counter; i++) {
3680 node= xorriso->node_array[i];
3681 ret= Xorriso_path_from_node(xorriso, node, abs_path, 0);
3682 if(ret < 0)
3683 goto ex;
3684 if(ret == 0)
3685 continue; /* node is deleted from tree meanwhile */
3686
3687 ret= Xorriso_findi_action(xorriso, hindmost, NULL, (off_t) 0,
3688 abs_path, abs_path, node, 0, 1);
3689 if(ret <= 0 || xorriso->request_to_abort)
3690 if(Xorriso_eval_problem_status(xorriso, ret, 1|2)<0)
3691 goto ex;
3692 if(ret == 4) /* end gracefully */
3693 break;
3694 }
3695
3696 ret= 1;
3697 ex:;
3698 if(!(flag & (2 | 4)))
3699 Xorriso_destroy_node_array(xorriso, 0);
3700 if(hmboss != NULL)
3701 hmboss->subjob= hindmost;
3702 if(array_job.start_path != NULL)
3703 free(array_job.start_path);
3704 Xorriso_free_meM(abs_path);
3705 return(ret);
3706 }
3707
3708
3709 int Xorriso_all_node_array(struct XorrisO *xorriso, int addon_nodes, int flag)
3710 {
3711 int ret;
3712 struct FindjoB *job= NULL;
3713 struct stat dir_stbuf;
3714
3715 ret= Findjob_new(&job, "/", 0);
3716 if(ret<=0) {
3717 Xorriso_no_findjob(xorriso, "xorriso", 0);
3718 {ret= -1; goto ex;}
3719 }
3720 Findjob_set_action_target(job, 30, NULL, 0);
3721 Xorriso_destroy_node_array(xorriso, 0);
3722 ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
3723 &dir_stbuf, 0, 0);
3724 if(ret <= 0)
3725 goto ex;
3726 ret= Xorriso_new_node_array(xorriso, xorriso->temp_mem_limit, addon_nodes, 0);
3727 if(ret <= 0)
3728 goto ex;
3729 Findjob_set_action_target(job, 31, NULL, 0);
3730 ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
3731 &dir_stbuf, 0, 0);
3732 if(ret <= 0)
3733 goto ex;
3734 ret= 1;
3735 ex:;
3736 Findjob_destroy(&job, 0);
3737 return(ret);
3738 }
3739
3740
3741 int Xorriso_perform_acl_from_list(struct XorrisO *xorriso, char *file_path,
3742 char *uid, char *gid, char *acl, int flag)
3743 {
3744 int ret, zero= 0;
3745 uid_t uid_number;
3746 gid_t gid_number;
3747
3748 /* Set group and owner */
3749 if(gid[0]) {
3750 ret= Xorriso_convert_gidstring(xorriso, gid, &gid_number, 0);
3751 if(ret<=0)
3752 return(ret);
3753 ret= Xorriso_set_gid(xorriso, file_path, gid_number, 0);
3754 if(ret<=0)
3755 return(ret);
3756 }
3757 if(uid[0]) {
3758 ret= Xorriso_convert_uidstring(xorriso, uid, &uid_number, 0);
3759 if(ret<=0)
3760 return(ret);
3761 ret= Xorriso_set_uid(xorriso, file_path, uid_number, 0);
3762 if(ret<=0)
3763 return(ret);
3764 }
3765 ret= Xorriso_option_setfacli(xorriso, acl, 1, &file_path, &zero, 0);
3766 if(ret <= 0)
3767 return(ret);
3768 return(1);
3769 }
3770
3771
3772 /*
3773 @param flag bit0= do not perform setfattr but only check input
3774 */
3775 int Xorriso_path_setfattr(struct XorrisO *xorriso, void *in_node, char *path,
3776 char *name, size_t value_length, char *value, int flag)
3777 {
3778 int ret, hflag;
3779 size_t num_attrs= 1;
3780 char *name_pt;
3781
3782 hflag= 2;
3783 name_pt= name;
3784 if(name[0] == 0) {
3785 sprintf(xorriso->info_text,
3786 "-setfattr: Empty attribute name is not allowed");
3787 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
3788 return(0);
3789 } else if(strcmp(name, "--remove-all") == 0) {
3790 if(value[0]) {
3791 sprintf(xorriso->info_text,
3792 "-setfattr: Value is not empty with pseudo name --remove-all");
3793 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
3794 return(0);
3795 }
3796 num_attrs= 0;
3797 hflag= 0;
3798 } else if(name[0] == '-') {
3799 name_pt++;
3800 hflag|= 4;
3801 } else if(name[0] == '=' || name[0] == '+') {
3802 name_pt++;
3803 }
3804 if(flag & 1)
3805 return(1);
3806 ret= Xorriso_setfattr(xorriso, in_node, path,
3807 num_attrs, &name_pt, &value_length, &value, hflag);
3808 return(ret);
3809 }
3810
3811
3812 /* Warning: The text content of lst gets mangled by 0s and unescaping.
3813 */
3814 int Xorriso_perform_attr_from_list(struct XorrisO *xorriso, char *path,
3815 struct Xorriso_lsT *lst_start, int flag)
3816 {
3817 int ret, eaten;
3818 char *valuept, *ept, *line, **names= NULL, **values= NULL;
3819 size_t num_attr= 0, *value_lengths= NULL, v_len;
3820 struct Xorriso_lsT *lst;
3821
3822 for(lst= lst_start; lst != NULL; lst= Xorriso_lst_get_next(lst, 0))
3823 num_attr++;
3824 if(num_attr == 0) {
3825 ret= Xorriso_setfattr(xorriso, NULL, path, num_attr, NULL, NULL, NULL, 0);
3826 goto ex;
3827 }
3828
3829 names= calloc(num_attr, sizeof(char *));
3830 if(names == NULL) {
3831 Xorriso_no_malloc_memory(xorriso, NULL, 0);
3832 ret= -1; goto ex;
3833 }
3834 value_lengths= calloc(num_attr, sizeof(size_t));
3835 if(value_lengths== NULL) {
3836 Xorriso_no_malloc_memory(xorriso, NULL, 0);
3837 ret= -1; goto ex;
3838 }
3839 values= calloc(num_attr, sizeof(char *));
3840 if(values== NULL) {
3841 Xorriso_no_malloc_memory(xorriso, NULL, 0);
3842 ret= -1; goto ex;
3843 }
3844
3845 num_attr= 0;
3846 for(lst= lst_start; lst != NULL; lst= Xorriso_lst_get_next(lst, 0)) {
3847 line= Xorriso_lst_get_text(lst, 0);
3848 ept= strchr(line, '=');
3849 if(ept == NULL)
3850 continue;
3851 /* Split into name and content */;
3852 *ept= 0;
3853 valuept= ept + 1;
3854
3855 /* Strip quotes from value */
3856 v_len= strlen(valuept);
3857 if(v_len < 2 || *valuept != '"' || *(valuept + v_len - 1) != '"')
3858 continue;
3859 *valuept= 0;
3860 *(valuept + v_len - 1)= 0;
3861 valuept++;
3862 v_len-= 2;
3863
3864 /* Unescape backslashes , values eventually with 0-bytes */
3865 ret= Sfile_bsl_interpreter(line, strlen(line), &eaten, 0);
3866 if(ret <= 0)
3867 continue;
3868 ret= Sfile_bsl_interpreter(valuept, (int) v_len, &eaten, 2);
3869 if(ret <= 0)
3870 continue;
3871
3872 names[num_attr]= line;
3873 values[num_attr]= valuept;
3874 value_lengths[num_attr]= v_len - eaten;
3875 num_attr++;
3876 }
3877 ret= Xorriso_setfattr(xorriso, NULL, path, num_attr, names,
3878 value_lengths, values, 0);
3879 ex:;
3880 if(names != NULL)
3881 free(names);
3882 if(value_lengths != NULL)
3883 free(value_lengths);
3884 if(values != NULL)
3885 free(values);
3886 return(ret);
3887 }
3888
3889
3890 int Xorriso__mark_update_xinfo(void *data, int flag)
3891 {
3892 /* data is an int disguised as pointer. It does not point to memory. */
3893 return(1);
3894 }
3895
3896
3897 int Xorriso__mark_update_cloner(void *old_data, void **new_data, int flag)
3898 {
3899 *new_data= NULL;
3900 if(flag)
3901 return(ISO_XINFO_NO_CLONE);
3902 if(old_data == NULL)
3903 return(0);
3904 /* data is an int disguised as pointer. It does not point to memory. */
3905 *new_data= old_data;
3906 return(0);
3907 }
3908
3909
3910 /* @param flag bit0= found on disk
3911 bit1= inquire visit-found status:
3912 1=not visited, 2=not found, 3=found
3913 bit2= with bit1: delete xinfo before returning status
3914 */
3915 int Xorriso_mark_update_merge(struct XorrisO *xorriso, char *path,
3916 void *in_node, int flag)
3917 {
3918 int ret;
3919 void *xipt= NULL;
3920 IsoNode *node;
3921
3922 if(in_node == NULL) {
3923 ret= Xorriso_node_from_path(xorriso, NULL, path, &node, 0);
3924 if(ret <= 0)
3925 return(ret);
3926 } else
3927 node= (IsoNode *) in_node;
3928 ret= iso_node_get_xinfo(node, Xorriso__mark_update_xinfo, &xipt);
3929 if(ret < 0) {
3930 Xorriso_process_msg_queues(xorriso,0);
3931 Xorriso_report_iso_error(xorriso, "", ret,
3932 "Error when looking for update_merge xinfo",
3933 0, "FAILURE", 1);
3934 return(0);
3935 }
3936 if(flag & 2) { /* Inquire status and optionally delete xinfo */
3937 if(ret == 0)
3938 return(1);
3939 if(flag & 4) {
3940 ret= iso_node_remove_xinfo(node, Xorriso__mark_update_xinfo);
3941 if(ret < 0) {
3942 Xorriso_process_msg_queues(xorriso,0);
3943 Xorriso_report_iso_error(xorriso, "", ret,
3944 "Error when removing update_merge xinfo",
3945 0, "FAILURE", 1);
3946 return(0);
3947 }
3948 }
3949 if(((char *) &xipt)[0])
3950 return(3);
3951 return(2);
3952 }
3953 /* xipt is a byte value disguised as void pointer */
3954 if(ret == 1) {
3955 if(((char *) &xipt)[0])
3956 return(1);
3957 if(!(flag & 1))
3958 return(1);
3959 } else
3960 ((char *) &xipt)[0]= 0;
3961 if(flag & 1)
3962 ((char *) &xipt)[0]= 1;
3963 ret= iso_node_remove_xinfo(node, Xorriso__mark_update_xinfo);
3964 if(ret < 0)
3965 goto set_error;
3966 ret= iso_node_add_xinfo(node, Xorriso__mark_update_xinfo, xipt);
3967 if(ret <= 0) {
3968 set_error:;
3969 Xorriso_process_msg_queues(xorriso,0);
3970 Xorriso_report_iso_error(xorriso, "", ret,
3971 "Error when trying to set update_merge xinfo",
3972 0, "FAILURE", 1);
3973 return(0);
3974 }
3975 return(1);
3976 }
3977
3978
3979 /* flag bit0= in case of error talk of "overwrite" rather than "remove"
3980 */
3981 static int Xorriso_remove_hfsplus_crtp(struct XorrisO *xorriso, IsoNode *node,
3982 char *path, int flag)
3983 {
3984 int ret;
3985 char *msg, buf[10], *bufpt;
3986 size_t l;
3987 static char *name= "isofs.hx";
3988
3989 ret= iso_node_remove_xinfo(node, iso_hfsplus_xinfo_func);
3990 Xorriso_process_msg_queues(xorriso, 0);
3991 if(ret < 0) {
3992 if(flag & 1)
3993 msg= "Cannot overwrite HFS+ creator and type of ISO node";
3994 else
3995 msg= "Cannot remove HFS+ creator and type of ISO node";
3996 Xorriso_report_iso_error(xorriso, path, ret, msg, 0, "FAILURE", 1);
3997 return(0);
3998 }
3999 /* Delete isofs.hx attribute */
4000 bufpt= buf;
4001
4002 /* >>> ??? check whether there is isofs.hx attached ? */;
4003
4004 ret= Xorriso_setfattr(xorriso, node, path,
4005 (size_t) 1, &name, &l, &bufpt, 4 | 8);
4006 return(ret);
4007 }
4008
4009
4010 static int Xorriso_set_hfsplus_crtp(struct XorrisO *xorriso, IsoNode *node,
4011 char *path, char *creator, char *hfs_type,
4012 int flag)
4013 {
4014 struct iso_hfsplus_xinfo_data *hfs_data= NULL;
4015 char buf[10], *bufpt;
4016 size_t l;
4017 int ret;
4018 static char *name= "isofs.hx";
4019
4020 /* Register as non-persistent xinfo */
4021 hfs_data= iso_hfsplus_xinfo_new(0);
4022 if(hfs_data == NULL) {
4023 Xorriso_no_malloc_memory(xorriso, NULL, 0);
4024 return(-1);
4025 }
4026 memcpy(hfs_data->creator_code, creator, 4);
4027 memcpy(hfs_data->type_code, hfs_type, 4);
4028 ret= iso_node_add_xinfo(node, iso_hfsplus_xinfo_func, (void *) hfs_data);
4029 Xorriso_process_msg_queues(xorriso, 0);
4030 if(ret < 0) {
4031 Xorriso_report_iso_error(xorriso, path, ret,
4032 "Cannot attach HFS+ creator and type to ISO node", 0, "FAILURE", 1);
4033 goto failure;
4034 } else if(ret == 0) {
4035 strcat(xorriso->info_text,
4036 "Program error: iso_node_add_xinfo refuses to attach HFS+ creator and type");
4037 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
4038 goto failure;
4039 }
4040
4041 /* Register as persistent attribute isofs.hx */
4042 bufpt= buf;
4043 l= 10;
4044 buf[0]= 1;
4045 buf[1]= 0;
4046 memcpy(buf + 2, creator, 4);
4047 memcpy(buf + 6, hfs_type, 4);
4048 ret= Xorriso_setfattr(xorriso, node, path,
4049 (size_t) 1, &name, &l, &bufpt, 2 | 8);
4050 if(ret <= 0)
4051 goto failure;
4052 Xorriso_set_change_pending(xorriso, 0);
4053 return(1);
4054
4055 failure:
4056 if(hfs_data != NULL)
4057 iso_hfsplus_xinfo_func(hfs_data, 1);
4058 return(0);
4059 }
4060
4061
4062 /* @param flag bit0= only check creator and hfs_type for compliance.
4063 bit1= with bit0: check for search rather than for setting
4064 bit2= copy 2 times 4 bytes without any check
4065 */
4066 int Xorriso_hfsplus_file_creator_type(struct XorrisO *xorriso, char *path,
4067 void *in_node,
4068 char *creator, char *hfs_type, int flag)
4069 {
4070 int ret;
4071 IsoNode *node;
4072
4073 if(in_node == NULL && !(flag & 1)) {
4074 ret= Xorriso_node_from_path(xorriso, NULL, path, &node, 0);
4075 if(ret <= 0)
4076 return(ret);
4077 } else
4078 node= (IsoNode *) in_node;
4079 if(flag & 4) {
4080 ;
4081 } else if((creator[0] == 0 && hfs_type[0] == 0) ||
4082 strcmp(creator, "--delete") == 0) {
4083 if(flag & 2) {
4084 strcpy(xorriso->info_text,
4085 "Attempt to use HFS+ file pseudo-creator '--delete' for searching");
4086 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
4087 strcpy(xorriso->info_text,
4088 "Suitable are strings of length 4 or length 1");
4089 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
4090 return(0);
4091 }
4092 if(flag & 1)
4093 return(1);
4094 ret= Xorriso_remove_hfsplus_crtp(xorriso, node, path, 0);
4095 if(ret < 0)
4096 return(ret);
4097 return(1);
4098 } else if((strlen(creator) != 4 && !(strlen(creator) == 1 &&
4099 (flag & 3) == 3)) ||
4100 (strlen(hfs_type) != 4 && !(strlen(hfs_type) == 1 &&
4101 (flag & 3) == 3))) {
4102 if(flag & 2) {
4103 strcpy(xorriso->info_text,
4104 "HFS+ file creator code or type code for searching are not exactly 1 or 4 characters long");
4105 } else {
4106 strcpy(xorriso->info_text,
4107 "HFS+ file creator code or type code are not exactly 4 characters long");
4108 }
4109 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
4110 return(0);
4111 }
4112 if(flag & 1)
4113 return(1);
4114
4115 ret= Xorriso_remove_hfsplus_crtp(xorriso, node, path, 1);
4116 if(ret <= 0)
4117 return(ret);
4118 ret= Xorriso_set_hfsplus_crtp(xorriso, node, path, creator, hfs_type, 0);
4119 if(ret <= 0)
4120 return(ret);
4121 return(1);
4122 }
4123
4124
4125 /*
4126 @param node
4127 If node is NULL and path is empty, then the blessing will be
4128 revoked from any node which bears it.
4129 @param flag
4130 Bitfield for control purposes.
4131 bit0= Revoke blessing if node != NULL bears it.
4132 bit1= Revoke any blessing of the node, regardless of parameter
4133 blessing. If node is NULL, then revoke all blessings.
4134 bit2= Only check parameter blessing.
4135 Return blessing index + 1 instead of issuing the blessing.
4136 bit3= With bit2:
4137 Allow blessing "any" and map to index ISO_HFSPLUS_BLESS_MAX.
4138 Elsewise, blessing "none" is mapped to ISO_HFSPLUS_BLESS_MAX.
4139 */
4140 int Xorriso_hfsplus_bless(struct XorrisO *xorriso, char *path,
4141 void *in_node, char *blessing, int flag)
4142 {
4143 int ret, bless_max;
4144 IsoNode *node, **blessed_nodes;
4145 IsoImage *volume= NULL;
4146 enum IsoHfsplusBlessings bless_code = ISO_HFSPLUS_BLESS_MAX; /* = invalid */
4147 char *hb = "";
4148 size_t l= 0;
4149 static char *name= "isofs.hb";
4150
4151 if(strcmp(blessing, "ppc_bootdir") == 0 ||
4152 strcmp(blessing, "p") == 0 || strcmp(blessing, "P") == 0) {
4153 bless_code= ISO_HFSPLUS_BLESS_PPC_BOOTDIR;
4154 hb= "p";
4155 } else if(strcmp(blessing, "intel_bootfile") == 0 ||
4156 strcmp(blessing, "i") == 0 || strcmp(blessing, "I") == 0) {
4157 bless_code= ISO_HFSPLUS_BLESS_INTEL_BOOTFILE;
4158 hb= "i";
4159 } else if(strcmp(blessing, "show_folder") == 0 ||
4160 strcmp(blessing, "s") == 0 || strcmp(blessing, "S") == 0) {
4161 bless_code= ISO_HFSPLUS_BLESS_SHOWFOLDER;
4162 hb= "s";
4163 } else if(strcmp(blessing, "os9_folder") == 0 ||
4164 strcmp(blessing, "9") == 0) {
4165 bless_code= ISO_HFSPLUS_BLESS_OS9_FOLDER;
4166 hb= "9";
4167 } else if(strcmp(blessing, "osx_folder") == 0 ||
4168 strcmp(blessing, "x") == 0 || strcmp(blessing, "X") == 0) {
4169 bless_code= ISO_HFSPLUS_BLESS_OSX_FOLDER;
4170 hb= "x";
4171 } else if((!(flag & 8)) && (strcmp(blessing, "none") == 0 ||
4172 strcmp(blessing, "n") == 0 || strcmp(blessing, "N") == 0)) {
4173 bless_code= ISO_HFSPLUS_BLESS_MAX;
4174 flag |= 2;
4175 } else if((flag & 8) && (flag & 4) &&
4176 (strcmp(blessing, "any") == 0 ||
4177 strcmp(blessing, "a") == 0 || strcmp(blessing, "A") == 0)) {
4178 bless_code= ISO_HFSPLUS_BLESS_MAX;
4179 } else {
4180 sprintf(xorriso->info_text, "Unknown blessing type ");
4181 Text_shellsafe(blessing, xorriso->info_text, 1);
4182 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
4183 return(0);
4184 }
4185 if(flag & 4)
4186 return(1 + bless_code);
4187
4188 if(in_node == NULL && path[0]) {
4189 ret= Xorriso_node_from_path(xorriso, NULL, path, &node, 0);
4190 if(ret <= 0)
4191 return(ret);
4192 } else
4193 node= (IsoNode *) in_node;
4194 ret= Xorriso_get_volume(xorriso, &volume, 0);
4195 if(ret <= 0)
4196 return(ret);
4197
4198 if(!(flag & 2)) {
4199 /* Remove persistent bless mark from current bearer */
4200 ret= iso_image_hfsplus_get_blessed(volume, &blessed_nodes, &bless_max, 0);
4201 Xorriso_process_msg_queues(xorriso, 0);
4202 if(ret < 0) {
4203 Xorriso_report_iso_error(xorriso, "", ret,
4204 "Error when trying to bless a file",
4205 0, "FAILURE", 1);
4206 return(0);
4207 }
4208 if((int) bless_code < bless_max) {
4209 if(blessed_nodes[(int) bless_code] != NULL) {
4210 ret= Xorriso_setfattr(xorriso, blessed_nodes[(int) bless_code], "",
4211 (size_t) 1, &name, &l, &hb, 4 | 8);
4212 if(ret <= 0)
4213 return(ret);
4214 }
4215 }
4216 }
4217
4218 /* Bless node */
4219 ret= iso_image_hfsplus_bless(volume, bless_code, node, flag & 3);
4220 Xorriso_process_msg_queues(xorriso, 0);
4221 if(ret == 0 && path[0]) {
4222 if((flag & 3)) {
4223 sprintf(xorriso->info_text,
4224 "Attempt to revoke blessing of unblessed file");
4225 } else {
4226 sprintf(xorriso->info_text,
4227 "Multiple blessing to same file or inappropriate file type");
4228 }
4229 if(path[0]) {
4230 strcat(xorriso->info_text, ": ");
4231 Text_shellsafe(path, xorriso->info_text, 1);
4232 }
4233 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
4234 return(0);
4235 } else if (ret < 0) {
4236 Xorriso_report_iso_error(xorriso, "", ret,
4237 "Error when trying to bless a file",
4238 0, "FAILURE", 1);
4239 return(0);
4240 }
4241
4242 /* Attach persistent AAIP bless mark to node */
4243 if(!(flag & 3)) {
4244 l= 1;
4245 ret= Xorriso_setfattr(xorriso, node, path, (size_t) 1, &name, &l, &hb,
4246 2 | 8);
4247 if(ret <= 0)
4248 return(ret);
4249 }
4250
4251 Xorriso_set_change_pending(xorriso, 0);
4252 return(1);
4253 }
4254
4255
4256 int Xorriso_get_blessing(struct XorrisO *xorriso, IsoNode *node,
4257 int *bless_idx, char bless_code[17], int flag)
4258 {
4259 IsoNode **blessed_nodes;
4260 int bless_max, ret, i;
4261
4262 if(xorriso->in_volset_handle == NULL)
4263 return(0);
4264
4265 ret= iso_image_hfsplus_get_blessed((IsoImage *) xorriso->in_volset_handle,
4266 &blessed_nodes, &bless_max, 0);
4267 Xorriso_process_msg_queues(xorriso, 0);
4268 if(ret < 0) {
4269 Xorriso_report_iso_error(xorriso, "", ret,
4270 "Error when trying to inquire HFS+ file blessings",
4271 0, "FAILURE", 1);
4272 return(-1);
4273 }
4274 for(i= 0; i < bless_max; i++) {
4275 if(blessed_nodes[i] == node) {
4276 switch (i) {
4277 case ISO_HFSPLUS_BLESS_PPC_BOOTDIR:
4278 strcpy(bless_code, "ppc_bootdir");
4279 break; case ISO_HFSPLUS_BLESS_INTEL_BOOTFILE:
4280 strcpy(bless_code, "intel_bootfile");
4281 break; case ISO_HFSPLUS_BLESS_SHOWFOLDER:
4282 strcpy(bless_code, "show_folder");
4283 break; case ISO_HFSPLUS_BLESS_OS9_FOLDER:
4284 strcpy(bless_code, "os9_folder");
4285 break; case ISO_HFSPLUS_BLESS_OSX_FOLDER:
4286 strcpy(bless_code, "osx_folder");
4287 break; default:
4288 strcpy(bless_code, "unknown_blessing");
4289 }
4290 *bless_idx= i;
4291 return(1);
4292 }
4293 }
4294 return(0);
4295 }
4296
4297
4298 /* @param flag bit0= use file addresses as search patterns
4299 */
4300 int Xorriso_apply_sort_file(struct XorrisO *xorriso, char *path, int flag)
4301 {
4302 int ret, linecount= 0, filec= 0, zero, i;
4303 FILE *fp= NULL;
4304 char *sret, *line= NULL, *spt, *tpt, *patterns[1], **filev= NULL;
4305 char *sort_weight_args[4];
4306 off_t mem= 0;
4307 IsoImage *volume;
4308
4309 Xorriso_alloc_meM(line, char, SfileadrL);
4310
4311 ret= Xorriso_get_volume(xorriso, &volume, 0);
4312 if(ret<=0)
4313 goto ex;
4314
4315 ret= Xorriso_afile_fopen(xorriso, path, "rb", &fp, 2);
4316 if(ret <= 0)
4317 {ret= 0; goto ex;}
4318 while(1) {
4319 sret= Sfile_fgets_n(line, SfileadrL - 1, fp, 0);
4320 if(sret == NULL) {
4321 if(ferror(fp))
4322 {ret= 0; goto ex;}
4323 break;
4324 }
4325 linecount++;
4326
4327 /* Find first space or tab */
4328 spt= strchr(line, ' ');
4329 tpt= strchr(line, '\t');
4330 if(spt == NULL || (tpt != NULL && tpt < spt))
4331 spt= tpt;
4332 if(spt == NULL) {
4333 sprintf(xorriso->info_text,
4334 "No space or tab character found in line %d of sort weight file ",
4335 linecount);
4336 Text_shellsafe(path, xorriso->info_text, 1);
4337 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
4338 ret= 0; goto ex;
4339 }
4340 *spt= 0;
4341
4342 patterns[0]= spt + 1;
4343 if(flag & 1) {
4344 /* Obtain list of matching files */
4345 ret= Xorriso_expand_pattern(xorriso, 1, patterns, 0,
4346 &filec, &filev, &mem, 4);
4347 if(ret <= 0)
4348 {ret= 0; goto ex;}
4349 } else {
4350 filec= 1;
4351 }
4352
4353 /* Apply weight to file or directory tree */
4354 for(i= 0; i < filec; i++) {
4355 zero= 0;
4356 if(flag & 1) {
4357 sort_weight_args[0]= filev[i];
4358 } else {
4359 sort_weight_args[0]= patterns[0];
4360 }
4361 sort_weight_args[1]= "-exec";
4362 sort_weight_args[2]= "sort_weight";
4363 sort_weight_args[3]= line;
4364 ret= Xorriso_option_find(xorriso, 4, sort_weight_args, &zero, 2);
4365 if(ret <= 0)
4366 {ret= 0; goto ex;}
4367 }
4368 if(flag & 1)
4369 Sfile_destroy_argv(&filec, &filev, 0);
4370 }
4371 ret= 1;
4372 ex:
4373 if(fp != NULL)
4374 fclose(fp);
4375 Xorriso_free_meM(line);
4376 Sfile_destroy_argv(&filec, &filev, 0);
4377 return(ret);
4378 }
4379
4380
4381 /* @param flag bit0= tolerate truncated files of old length
4382 and mangle collisions
4383 */
4384 int Xorriso_set_file_name_limit(struct XorrisO *xorriso, int value, int flag)
4385 {
4386 int ret;
4387 IsoImage *volume= NULL;
4388 struct FindjoB *job= NULL;
4389 struct stat dir_stbuf;
4390
4391 ret= Xorriso_get_volume(xorriso, &volume, 1);
4392 if(ret < 0)
4393 goto ex;
4394 if (ret == 1 && volume != NULL) {
4395 /* Check whether there are non-refreshable truncated names */
4396 ret= Findjob_new(&job, "/", 0);
4397 if(ret<=0) {
4398 Xorriso_no_findjob(xorriso, "xorriso", 0);
4399 {ret= -1; goto ex;}
4400 }
4401 Findjob_set_action_type(job, 55 + 2 * (flag & 1), value, 0);
4402 xorriso->find_unique_trunc_result= 2;
4403 ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
4404 &dir_stbuf, 0, 0);
4405 if(ret < 0)
4406 goto ex;
4407 xorriso->request_to_abort= 0;
4408 if(xorriso->find_unique_trunc_result == 0 && !(flag & 1)) {
4409 Xorriso_msgs_submit(xorriso, 0,
4410 "-file_name_limit may not be changed because truncated files exist or collisions would occur",
4411 0, "SORRY", 0);
4412 ret= 0; goto ex;
4413 }
4414
4415 xorriso->file_name_limit= value;
4416 iso_image_set_truncate_mode(volume, 1, value);
4417
4418 /* truncations are necessary */;
4419 if(xorriso->find_unique_trunc_result == 1) {
4420 Findjob_set_action_type(job, 54 + 2 * (flag & 1),
4421 xorriso->file_name_limit, 0);
4422 xorriso->find_unique_trunc_result= 2;
4423 ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
4424 &dir_stbuf, 0, 0);
4425 if(ret < 0)
4426 goto ex;
4427 if(xorriso->find_unique_trunc_result == 0) {
4428
4429 /* >>> Did not work . What to do ? */;
4430
4431 }
4432 }
4433 }
4434 xorriso->file_name_limit= value;
4435 ret= 1;
4436 ex:;
4437 Findjob_destroy(&job, 0);
4438 return(ret);
4439 }
4440
4441
4442 /* @param flag bit0= test for uniqueness, do not change name
4443 bit1= tolerate existing truncated names and mangle collisions
4444 bit2= be silent about non-uniquely truncatables
4445 do not set xorriso->request_to_abort
4446 */
4447 int Xorriso_truncate_uniquely(struct XorrisO *xorriso, int length,
4448 IsoNode *node, char *abs_path, char *show_path,
4449 int flag)
4450 {
4451 int ret, l, i;
4452 unsigned int mangleno;
4453 char *