"Fossies" - the Fresh Open Source Software Archive 
Member "xorriso-1.5.4/libisofs/image.c" (30 Jan 2021, 34473 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 "image.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 * Copyright (c) 2007 Vreixo Formoso
3 * Copyright (c) 2009 - 2015 Thomas Schmitt
4 *
5 * This file is part of the libisofs project; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License version 2
7 * or later as published by the Free Software Foundation.
8 * See COPYING file for details.
9 */
10
11 #ifdef HAVE_CONFIG_H
12 #include "../config.h"
13 #endif
14
15 #include "libisofs.h"
16 #include "image.h"
17 #include "node.h"
18 #include "messages.h"
19 #include "eltorito.h"
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24
25
26 int iso_imported_sa_new(struct iso_imported_sys_area **boots, int flag)
27 {
28 struct iso_imported_sys_area *b;
29
30 *boots = NULL;
31 b = calloc(1, sizeof(struct iso_imported_sys_area));
32 if (b == NULL)
33 return ISO_OUT_OF_MEM;
34
35 b->mbr_req = NULL;
36 b->apm_req = NULL;
37
38 b->gpt_req = NULL;
39 b->gpt_backup_comments = NULL;
40
41 b->mips_boot_file_paths = NULL;
42 b->mips_vd_entries = NULL;
43
44 b->sparc_disc_label = NULL;
45 b->sparc_core_node = NULL;
46 b->sparc_entries = NULL;
47
48 b->hppa_cmdline = NULL;
49 b->hppa_bootloader = NULL;
50 b->hppa_kernel_32 = NULL;
51 b->hppa_kernel_64 = NULL;
52 b->hppa_ramdisk = NULL;
53
54 b->alpha_boot_image = NULL;
55
56 *boots = b;
57 return 1;
58 }
59
60 int iso_imported_sa_unref(struct iso_imported_sys_area **boots, int flag)
61 {
62 int i;
63 struct iso_imported_sys_area *b;
64
65 b = *boots;
66 if (b == NULL)
67 return 2;
68 if (b->refcount > 0)
69 b->refcount--;
70 if (b->refcount > 0)
71 return 2;
72
73 if (b->mbr_req != NULL) {
74 for (i = 0; i < b->mbr_req_count; i++)
75 LIBISO_FREE_MEM(b->mbr_req[i]);
76 LIBISO_FREE_MEM(b->mbr_req);
77 }
78 if (b->apm_req != NULL) {
79 for (i = 0; i < b->apm_req_count; i++)
80 LIBISO_FREE_MEM(b->apm_req[i]);
81 LIBISO_FREE_MEM(b->apm_req);
82 }
83 if (b->gpt_req != NULL) {
84 for (i = 0; i < b->gpt_req_count; i++)
85 LIBISO_FREE_MEM(b->gpt_req[i]);
86 LIBISO_FREE_MEM(b->gpt_req);
87 }
88 LIBISO_FREE_MEM(b->gpt_backup_comments);
89
90 if (b->mips_boot_file_paths != NULL) {
91 for (i = 0; i < b->num_mips_boot_files; i++)
92 LIBISO_FREE_MEM(b->mips_boot_file_paths[i]);
93 LIBISO_FREE_MEM(b->mips_boot_file_paths);
94 }
95 if (b->mips_vd_entries != NULL) {
96 for (i = 0; i < b->num_mips_boot_files; i++)
97 LIBISO_FREE_MEM(b->mips_vd_entries[i]);
98 LIBISO_FREE_MEM(b->mips_vd_entries);
99 }
100 LIBISO_FREE_MEM(b->mipsel_boot_file_path);
101
102 LIBISO_FREE_MEM(b->sparc_disc_label);
103 if (b->sparc_core_node != NULL)
104 iso_node_unref((IsoNode *) b->sparc_core_node);
105 LIBISO_FREE_MEM(b->sparc_entries);
106
107 LIBISO_FREE_MEM(b->hppa_cmdline);
108 LIBISO_FREE_MEM(b->hppa_bootloader);
109 LIBISO_FREE_MEM(b->hppa_kernel_32);
110 LIBISO_FREE_MEM(b->hppa_kernel_64);
111 LIBISO_FREE_MEM(b->hppa_ramdisk);
112 LIBISO_FREE_MEM(b->alpha_boot_image);
113 LIBISO_FREE_MEM(b);
114 *boots = NULL;
115 return 1;
116 }
117
118
119 /**
120 * Create a new image, empty.
121 *
122 * The image will be owned by you and should be unref() when no more needed.
123 *
124 * @param name
125 * Name of the image. This will be used as volset_id and volume_id.
126 * @param image
127 * Location where the image pointer will be stored.
128 * @return
129 * 1 success, < 0 error
130 */
131 int iso_image_new(const char *name, IsoImage **image)
132 {
133 int res, i;
134 IsoImage *img;
135
136 if (image == NULL) {
137 return ISO_NULL_POINTER;
138 }
139
140 img = calloc(1, sizeof(IsoImage));
141 if (img == NULL) {
142 return ISO_OUT_OF_MEM;
143 }
144
145 /* local filesystem will be used by default */
146 res = iso_local_filesystem_new(&(img->fs));
147 if (res < 0) {
148 free(img);
149 return ISO_OUT_OF_MEM;
150 }
151
152 /* use basic builder as default */
153 res = iso_node_basic_builder_new(&(img->builder));
154 if (res < 0) {
155 iso_filesystem_unref(img->fs);
156 free(img);
157 return ISO_OUT_OF_MEM;
158 }
159
160 /* fill image fields */
161 res = iso_node_new_root(&img->root);
162 if (res < 0) {
163 iso_node_builder_unref(img->builder);
164 iso_filesystem_unref(img->fs);
165 free(img);
166 return res;
167 }
168 img->refcount = 1;
169 img->id = iso_message_id++;
170
171 if (name != NULL) {
172 img->volset_id = strdup(name);
173 img->volume_id = strdup(name);
174 }
175 memset(img->application_use, 0, 512);
176 img->system_area_data = NULL;
177 img->system_area_options = 0;
178 img->num_mips_boot_files = 0;
179 for (i = 0; i < 15; i++)
180 img->mips_boot_file_paths[i] = NULL;
181 img->sparc_core_node = NULL;
182 img->hppa_cmdline= NULL;
183 img->hppa_bootloader = NULL;
184 img->hppa_kernel_32 = NULL;
185 img->hppa_kernel_64 = NULL;
186 img->hppa_ramdisk = NULL;
187 img->alpha_boot_image = NULL;
188 img->import_src = NULL;
189 img->builder_ignore_acl = 1;
190 img->builder_ignore_ea = 1;
191 img->truncate_mode = 1;
192 img->truncate_length = LIBISOFS_NODE_NAME_MAX;
193 img->truncate_buffer[0] = 0;
194 img->inode_counter = 0;
195 img->used_inodes = NULL;
196 img->used_inodes_start = 0;
197 img->checksum_start_lba = 0;
198 img->checksum_end_lba = 0;
199 img->checksum_idx_count = 0;
200 img->checksum_array = NULL;
201 img->generator_is_running = 0;
202 for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
203 img->hfsplus_blessed[i] = NULL;
204 img->collision_warnings = 0;
205 img->imported_sa_info = NULL;
206 img->blind_on_local_get_attrs = 0;
207
208 *image = img;
209 return ISO_SUCCESS;
210 }
211
212 /**
213 * Increments the reference counting of the given image.
214 */
215 void iso_image_ref(IsoImage *image)
216 {
217 ++image->refcount;
218 }
219
220 /**
221 * Decrements the reference counting of the given image.
222 * If it reaches 0, the image is free, together with its tree nodes (whether
223 * their refcount reach 0 too, of course).
224 */
225 void iso_image_unref(IsoImage *image)
226 {
227 int nexcl, i;
228
229 if (--image->refcount == 0) {
230 /* we need to free the image */
231
232 if (image->user_data_free != NULL) {
233 /* free attached data */
234 image->user_data_free(image->user_data);
235 }
236 for (nexcl = 0; nexcl < image->nexcludes; ++nexcl) {
237 free(image->excludes[nexcl]);
238 }
239 free(image->excludes);
240 for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
241 if (image->hfsplus_blessed[i] != NULL)
242 iso_node_unref(image->hfsplus_blessed[i]);
243 iso_node_unref((IsoNode*)image->root);
244 iso_node_builder_unref(image->builder);
245 iso_filesystem_unref(image->fs);
246 el_torito_boot_catalog_free(image->bootcat);
247 iso_image_give_up_mips_boot(image, 0);
248 if (image->sparc_core_node != NULL)
249 iso_node_unref((IsoNode *) image->sparc_core_node);
250 iso_image_set_hppa_palo(image, NULL, NULL, NULL, NULL, NULL, 1);
251 if (image->alpha_boot_image != NULL)
252 free(image->alpha_boot_image);
253 if (image->import_src != NULL)
254 iso_data_source_unref(image->import_src);
255 free(image->volset_id);
256 free(image->volume_id);
257 free(image->publisher_id);
258 free(image->data_preparer_id);
259 free(image->system_id);
260 free(image->application_id);
261 free(image->copyright_file_id);
262 free(image->abstract_file_id);
263 free(image->biblio_file_id);
264 free(image->creation_time);
265 free(image->modification_time);
266 free(image->expiration_time);
267 free(image->effective_time);
268 if (image->used_inodes != NULL)
269 free(image->used_inodes);
270 if (image->system_area_data != NULL)
271 free(image->system_area_data);
272 iso_image_free_checksums(image, 0);
273 iso_imported_sa_unref(&(image->imported_sa_info), 0);
274 free(image);
275 }
276 }
277
278
279 int iso_image_free_checksums(IsoImage *image, int flag)
280 {
281 image->checksum_start_lba = 0;
282 image->checksum_end_lba = 0;
283 image->checksum_idx_count = 0;
284 if (image->checksum_array != NULL)
285 free(image->checksum_array);
286 image->checksum_array = NULL;
287 return 1;
288 }
289
290
291 /**
292 * Attach user defined data to the image. Use this if your application needs
293 * to store addition info together with the IsoImage. If the image already
294 * has data attached, the old data will be freed.
295 *
296 * @param data
297 * Pointer to application defined data that will be attached to the
298 * image. You can pass NULL to remove any already attached data.
299 * @param give_up
300 * Function that will be called when the image does not need the data
301 * any more. It receives the data pointer as an argumente, and eventually
302 * causes data to be free. It can be NULL if you don't need it.
303 */
304 int iso_image_attach_data(IsoImage *image, void *data, void (*give_up)(void*))
305 {
306 if (image == NULL) {
307 return ISO_NULL_POINTER;
308 }
309
310 if (image->user_data != NULL) {
311 /* free previously attached data */
312 if (image->user_data_free != NULL) {
313 image->user_data_free(image->user_data);
314 }
315 image->user_data = NULL;
316 image->user_data_free = NULL;
317 }
318
319 if (data != NULL) {
320 image->user_data = data;
321 image->user_data_free = give_up;
322 }
323 return ISO_SUCCESS;
324 }
325
326 /**
327 * The the data previously attached with iso_image_attach_data()
328 */
329 void *iso_image_get_attached_data(IsoImage *image)
330 {
331 return image->user_data;
332 }
333
334 IsoDir *iso_image_get_root(const IsoImage *image)
335 {
336 return image->root;
337 }
338
339 void iso_image_set_volset_id(IsoImage *image, const char *volset_id)
340 {
341 free(image->volset_id);
342 image->volset_id = strdup(volset_id);
343 }
344
345 const char *iso_image_get_volset_id(const IsoImage *image)
346 {
347 if (image->volset_id == NULL)
348 return "";
349 return image->volset_id;
350 }
351
352 void iso_image_set_volume_id(IsoImage *image, const char *volume_id)
353 {
354 free(image->volume_id);
355 image->volume_id = strdup(volume_id);
356 }
357
358 const char *iso_image_get_volume_id(const IsoImage *image)
359 {
360 if (image->volume_id == NULL)
361 return "";
362 return image->volume_id;
363 }
364
365 void iso_image_set_publisher_id(IsoImage *image, const char *publisher_id)
366 {
367 free(image->publisher_id);
368 image->publisher_id = strdup(publisher_id);
369 }
370
371 const char *iso_image_get_publisher_id(const IsoImage *image)
372 {
373 if (image->publisher_id == NULL)
374 return "";
375 return image->publisher_id;
376 }
377
378 void iso_image_set_data_preparer_id(IsoImage *image,
379 const char *data_preparer_id)
380 {
381 free(image->data_preparer_id);
382 image->data_preparer_id = strdup(data_preparer_id);
383 }
384
385 const char *iso_image_get_data_preparer_id(const IsoImage *image)
386 {
387 if (image->data_preparer_id == NULL)
388 return "";
389 return image->data_preparer_id;
390 }
391
392 void iso_image_set_system_id(IsoImage *image, const char *system_id)
393 {
394 free(image->system_id);
395 image->system_id = strdup(system_id);
396 }
397
398 const char *iso_image_get_system_id(const IsoImage *image)
399 {
400 if (image->system_id == NULL)
401 return "";
402 return image->system_id;
403 }
404
405 void iso_image_set_application_id(IsoImage *image, const char *application_id)
406 {
407 free(image->application_id);
408 image->application_id = strdup(application_id);
409 }
410
411 const char *iso_image_get_application_id(const IsoImage *image)
412 {
413 if (image->application_id == NULL)
414 return "";
415 return image->application_id;
416 }
417
418 void iso_image_set_copyright_file_id(IsoImage *image,
419 const char *copyright_file_id)
420 {
421 free(image->copyright_file_id);
422 image->copyright_file_id = strdup(copyright_file_id);
423 }
424
425 const char *iso_image_get_copyright_file_id(const IsoImage *image)
426 {
427 if (image->copyright_file_id == NULL)
428 return "";
429 return image->copyright_file_id;
430 }
431
432 void iso_image_set_abstract_file_id(IsoImage *image,
433 const char *abstract_file_id)
434 {
435 free(image->abstract_file_id);
436 image->abstract_file_id = strdup(abstract_file_id);
437 }
438
439 const char *iso_image_get_abstract_file_id(const IsoImage *image)
440 {
441 if (image->abstract_file_id == NULL)
442 return "";
443 return image->abstract_file_id;
444 }
445
446 void iso_image_set_biblio_file_id(IsoImage *image, const char *biblio_file_id)
447 {
448 free(image->biblio_file_id);
449 image->biblio_file_id = strdup(biblio_file_id);
450 }
451
452 const char *iso_image_get_biblio_file_id(const IsoImage *image)
453 {
454 if (image->biblio_file_id == NULL)
455 return "";
456 return image->biblio_file_id;
457 }
458
459 int iso_image_set_pvd_times(IsoImage *image,
460 char *creation_time, char *modification_time,
461 char *expiration_time, char *effective_time)
462 {
463 if (creation_time == NULL || modification_time == NULL ||
464 expiration_time == NULL || effective_time == NULL)
465 return ISO_NULL_POINTER;
466 image->creation_time = calloc(18, 1); /* Surely including a trailing 0 */
467 image->modification_time = calloc(18, 1);
468 image->expiration_time = calloc(18, 1);
469 image->effective_time = calloc(18, 1);
470 if (image->creation_time == NULL || image->modification_time == NULL ||
471 image->expiration_time == NULL || image->effective_time == NULL)
472 return ISO_OUT_OF_MEM;
473 /* (If the string is too short, a non-zero timezone will not be stored) */
474 strncpy(image->creation_time, creation_time, 17);
475 strncpy(image->modification_time, modification_time, 17);
476 strncpy(image->expiration_time, expiration_time, 17);
477 strncpy(image->effective_time, effective_time, 17);
478 return ISO_SUCCESS;
479 }
480
481 int iso_image_get_pvd_times(IsoImage *image,
482 char **creation_time, char **modification_time,
483 char **expiration_time, char **effective_time)
484 {
485 if (image->creation_time == NULL || image->modification_time == NULL ||
486 image->expiration_time == NULL || image->effective_time == NULL)
487 return ISO_NULL_POINTER;
488 *creation_time = image->creation_time;
489 *modification_time = image->modification_time;
490 *expiration_time = image->expiration_time;
491 *effective_time = image->effective_time;
492 return ISO_SUCCESS;
493 }
494
495 void iso_image_set_app_use(IsoImage *image, const char *app_use_data,
496 int count)
497 {
498 if (count < 0)
499 count= 0;
500 else if(count > 512)
501 count= 512;
502 if (count > 0)
503 memcpy(image->application_use, app_use_data, count);
504 if (count < 512)
505 memset(image->application_use + count, 0, 512 - count);
506 }
507
508 int iso_image_get_msg_id(IsoImage *image)
509 {
510 return image->id;
511 }
512
513 int iso_image_get_system_area(IsoImage *img, char system_area_data[32768],
514 int *options, int flag)
515 {
516 *options = img->system_area_options;
517 if (img->system_area_data == NULL)
518 return 0;
519 memcpy(system_area_data, img->system_area_data, 32768);
520 return 1;
521 }
522
523 static
524 int dir_update_size(IsoImage *image, IsoDir *dir)
525 {
526 IsoNode *pos;
527 int ret;
528
529 #ifdef Libisofs_update_sizes_abortablE
530 char *path= NULL;
531 IsoStream *base_stream;
532 int cancel_ret, ret;
533 uint32_t lba;
534 #endif
535
536 pos = dir->children;
537 while (pos) {
538 if (pos->type == LIBISO_FILE) {
539 ret = iso_stream_update_size(ISO_FILE(pos)->stream);
540 } else if (pos->type == LIBISO_DIR) {
541 /* recurse */
542 ret = dir_update_size(image, ISO_DIR(pos));
543
544 #ifdef Libisofs_update_sizes_abortablE
545 if (ret == ISO_CANCELED)
546 return ret; /* Message already issued by dir_update_size */
547 #endif
548
549 } else {
550 ret = 1;
551 }
552
553 #ifdef Libisofs_update_sizes_abortablE
554
555 /* This would report error and abort according to severity threshold.
556 But it is desirable to let the update_size crawler continue
557 its work after e.g. a file has vanished from hard disk.
558 So normally this macro case should be disabled.
559 */
560
561 if (ret < 0) {
562 cancel_ret = iso_msg_submit(image->id, ret, 0, NULL);
563 path = iso_tree_get_node_path(pos);
564 if (path != NULL) {
565 iso_msg_submit(image->id, ret, 0,
566 "ISO path : %s", path);
567 free(path);
568 }
569 /* Report source path with streams which do not come from
570 the loaded ISO filesystem */
571 if (pos->type == LIBISO_FILE &&
572 iso_node_get_old_image_lba(pos, &lba, 0) == 0) {
573 base_stream = iso_stream_get_input_stream(
574 ISO_FILE(pos)->stream, 1);
575 if (base_stream == NULL)
576 base_stream = ISO_FILE(pos)->stream;
577 path = iso_stream_get_source_path(base_stream, 0);
578 if (path != NULL) {
579 iso_msg_submit(image->id, ret, 0,
580 "Local path: %s", path);
581 free(path);
582 }
583 }
584 if (cancel_ret < 0)
585 return cancel_ret; /* cancel due error threshold */
586 }
587
588 #else
589
590 if (ret < 0)
591 ret = 1; /* ignore error */
592
593 #endif /* ! Libisofs_update_sizes_abortablE */
594
595 pos = pos->next;
596 }
597 return ISO_SUCCESS;
598 }
599
600 int iso_image_update_sizes(IsoImage *image)
601 {
602 if (image == NULL) {
603 return ISO_NULL_POINTER;
604 }
605
606 return dir_update_size(image, image->root);
607 }
608
609
610 void iso_image_set_ignore_aclea(IsoImage *image, int what)
611 {
612 image->builder_ignore_acl = (what & 1);
613 image->builder_ignore_ea = !!(what & 2);
614 image->builder_take_all_ea = !!(what & 8);
615 }
616
617
618 int iso_image_get_ignore_aclea(IsoImage *image)
619 {
620 return image->builder_ignore_acl |
621 (image->builder_ignore_ea << 1) |
622 (image->builder_take_all_ea << 3);
623 }
624
625
626 static
627 int img_register_ino(IsoImage *image, IsoNode *node, int flag)
628 {
629 int ret;
630 ino_t ino;
631 unsigned int fs_id;
632 dev_t dev_id;
633
634 ret = iso_node_get_id(node, &fs_id, &dev_id, &ino, 1);
635 if (ret < 0)
636 return ret;
637 if (ret > 0 && ino >= image->used_inodes_start &&
638 ino <= image->used_inodes_start + (ISO_USED_INODE_RANGE - 1)) {
639 /* without -1 : rollover hazard on 32 bit */
640 image->used_inodes[(ino - image->used_inodes_start) / 8]
641 |= (1 << (ino % 8));
642 }
643 return 1;
644 }
645
646
647 /* Collect the bitmap of used inode numbers in the range of
648 _ImageFsData.used_inodes_start + ISO_USED_INODE_RANGE
649 @param flag bit0= recursion is active
650 */
651 int img_collect_inos(IsoImage *image, IsoDir *dir, int flag)
652 {
653 int ret, register_dir = 1;
654 IsoDirIter *iter = NULL;
655 IsoNode *node;
656 IsoDir *subdir;
657
658 if (dir == NULL)
659 dir = image->root;
660 if (image->used_inodes == NULL) {
661 image->used_inodes = calloc(ISO_USED_INODE_RANGE / 8, 1);
662 if (image->used_inodes == NULL)
663 return ISO_OUT_OF_MEM;
664 } else if(!(flag & 1)) {
665 memset(image->used_inodes, 0, ISO_USED_INODE_RANGE / 8);
666 } else {
667 register_dir = 0;
668 }
669 if (register_dir) {
670 node = (IsoNode *) dir;
671 ret = img_register_ino(image, node, 0);
672 if (ret < 0)
673 return ret;
674 }
675
676 ret = iso_dir_get_children(dir, &iter);
677 if (ret < 0)
678 return ret;
679 while (iso_dir_iter_next(iter, &node) == 1 ) {
680 ret = img_register_ino(image, node, 0);
681 if (ret < 0)
682 goto ex;
683 if (iso_node_get_type(node) == LIBISO_DIR) {
684 subdir = (IsoDir *) node;
685 ret = img_collect_inos(image, subdir, flag | 1);
686 if (ret < 0)
687 goto ex;
688 }
689 }
690 ret = 1;
691 ex:;
692 if (iter != NULL)
693 iso_dir_iter_free(iter);
694 return ret;
695 }
696
697
698 /**
699 * A global counter for Rock Ridge inode numbers in the ISO image filesystem.
700 *
701 * On image import it gets maxed by the eventual inode numbers from PX
702 * entries. Up to the first 32 bit rollover it simply increments the counter.
703 * After the first rollover it uses a look ahead bitmap which gets filled
704 * by a full tree traversal. It covers the next inode numbers to come
705 * (somewhere between 1 and ISO_USED_INODE_RANGE which is quite many)
706 * and advances when being exhausted.
707 * @param image The image where the number shall be used
708 * @param flag bit0= reset count (Caution: image must get new inos then)
709 * @return
710 * Since 0 is used as default and considered self-unique,
711 * the value 0 should only be returned in case of error.
712 */
713 uint32_t img_give_ino_number(IsoImage *image, int flag)
714 {
715 int ret;
716 uint64_t new_ino, ino_idx;
717 static uint64_t limit = 0xffffffff;
718
719 if (flag & 1) {
720 image->inode_counter = 0;
721 if (image->used_inodes != NULL)
722 free(image->used_inodes);
723 image->used_inodes = NULL;
724 image->used_inodes_start = 0;
725 }
726 new_ino = ((uint64_t) image->inode_counter) + 1;
727 if (image->used_inodes == NULL) {
728 if (new_ino > 0 && new_ino <= limit) {
729 image->inode_counter = (uint32_t) new_ino;
730 return image->inode_counter;
731 }
732 }
733 /* Look for free number in used territory */
734 while (1) {
735 if (new_ino <= 0 || new_ino > limit ||
736 new_ino >= image->used_inodes_start + ISO_USED_INODE_RANGE ) {
737
738 /* Collect a bitmap of used inode numbers ahead */
739
740 image->used_inodes_start += ISO_USED_INODE_RANGE;
741 if (image->used_inodes_start > 0xffffffff ||
742 image->used_inodes_start <= 0)
743 image->used_inodes_start = 0;
744 ret = img_collect_inos(image, NULL, 0);
745 if (ret < 0)
746 goto return_result; /* >>> need error return value */
747
748 new_ino = image->used_inodes_start + !image->used_inodes_start;
749 }
750 ino_idx = (new_ino - image->used_inodes_start) / 8;
751 if (!(image->used_inodes[ino_idx] & (1 << (new_ino % 8)))) {
752 image->used_inodes[ino_idx] |= (1 << (new_ino % 8));
753 break;
754 }
755 new_ino++;
756 }
757 return_result:;
758 image->inode_counter = new_ino;
759 return image->inode_counter;
760 }
761
762
763 /* @param flag bit0= overwrite any ino, else only ino == 0
764 bit1= install inode with non-data, non-directory files
765 bit2= install inode with directories
766 */
767 static
768 int img_update_ino(IsoImage *image, IsoNode *node, int flag)
769 {
770 int ret;
771 ino_t ino;
772 unsigned int fs_id;
773 dev_t dev_id;
774
775 ret = iso_node_get_id(node, &fs_id, &dev_id, &ino, 1);
776 if (ret < 0)
777 return ret;
778 if (ret == 0)
779 ino = 0;
780 if (((flag & 1) || ino == 0) &&
781 (iso_node_get_type(node) == LIBISO_FILE || (flag & (2 | 4))) &&
782 ((flag & 4) || iso_node_get_type(node) != LIBISO_DIR)) {
783 ret = iso_node_set_unique_id(node, image, 0);
784 if (ret < 0)
785 return ret;
786 }
787 return 1;
788 }
789
790
791 /* @param flag bit0= overwrite any ino, else only ino == 0
792 bit1= install inode with non-data, non-directory files
793 bit2= install inode with directories
794 bit3= with bit2: install inode on parameter dir
795 */
796 int img_make_inos(IsoImage *image, IsoDir *dir, int flag)
797 {
798 int ret;
799 IsoDirIter *iter = NULL;
800 IsoNode *node;
801 IsoDir *subdir;
802
803 if (flag & 8) {
804 node = (IsoNode *) dir;
805 ret = img_update_ino(image, node, flag & 7);
806 if (ret < 0)
807 goto ex;
808 }
809 ret = iso_dir_get_children(dir, &iter);
810 if (ret < 0)
811 return ret;
812 while (iso_dir_iter_next(iter, &node) == 1) {
813 ret = img_update_ino(image, node, flag & 7);
814 if (ret < 0)
815 goto ex;
816 if (iso_node_get_type(node) == LIBISO_DIR) {
817 subdir = (IsoDir *) node;
818 ret = img_make_inos(image, subdir, flag & ~8);
819 if (ret < 0)
820 goto ex;
821 }
822 }
823 ret = 1;
824 ex:;
825 if (iter != NULL)
826 iso_dir_iter_free(iter);
827 return ret;
828 }
829
830
831 /* API */
832 int iso_image_get_session_md5(IsoImage *image, uint32_t *start_lba,
833 uint32_t *end_lba, char md5[16], int flag)
834 {
835 if (image->checksum_array == NULL || image->checksum_idx_count < 1)
836 return 0;
837 *start_lba = image->checksum_start_lba;
838 *end_lba = image->checksum_end_lba;
839 memcpy(md5, image->checksum_array, 16);
840 return ISO_SUCCESS;
841 }
842
843 int iso_image_set_checksums(IsoImage *image, char *checksum_array,
844 uint32_t start_lba, uint32_t end_lba,
845 uint32_t idx_count, int flag)
846 {
847 iso_image_free_checksums(image, 0);
848 image->checksum_array = checksum_array;
849 image->checksum_start_lba = start_lba;
850 image->checksum_end_lba = end_lba;
851 image->checksum_idx_count = idx_count;
852 return 1;
853 }
854
855 int iso_image_generator_is_running(IsoImage *image)
856 {
857 return image->generator_is_running;
858 }
859
860
861 /* API */
862 int iso_image_add_mips_boot_file(IsoImage *image, char *path, int flag)
863 {
864 if (image->num_mips_boot_files >= 15)
865 return ISO_BOOT_TOO_MANY_MIPS;
866 image->mips_boot_file_paths[image->num_mips_boot_files] = strdup(path);
867 if (image->mips_boot_file_paths[image->num_mips_boot_files] == NULL)
868 return ISO_OUT_OF_MEM;
869 image->num_mips_boot_files++;
870 return ISO_SUCCESS;
871 }
872
873 /* API */
874 int iso_image_get_mips_boot_files(IsoImage *image, char *paths[15], int flag)
875 {
876 int i;
877
878 for (i = 0; i < image->num_mips_boot_files; i++)
879 paths[i] = image->mips_boot_file_paths[i];
880 for (; i < 15; i++)
881 paths[i] = NULL;
882 return image->num_mips_boot_files;
883 }
884
885 /* API */
886 int iso_image_give_up_mips_boot(IsoImage *image, int flag)
887 {
888 int i;
889
890 for (i = 0; i < image->num_mips_boot_files; i++)
891 if (image->mips_boot_file_paths[i] != NULL) {
892 free(image->mips_boot_file_paths[i]);
893 image->mips_boot_file_paths[i] = NULL;
894 }
895 image->num_mips_boot_files = 0;
896 return ISO_SUCCESS;
897 }
898
899 static void unset_blessing(IsoImage *img, unsigned int idx)
900 {
901 if (img->hfsplus_blessed[idx] != NULL)
902 iso_node_unref(img->hfsplus_blessed[idx]);
903 img->hfsplus_blessed[idx] = NULL;
904 }
905
906 /* API */
907 int iso_image_hfsplus_bless(IsoImage *img, enum IsoHfsplusBlessings blessing,
908 IsoNode *node, int flag)
909 {
910 unsigned int i, ok = 0;
911
912 if (flag & 2) {
913 /* Delete any blessing */
914 for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) {
915 if (img->hfsplus_blessed[i] == node || node == NULL) {
916 unset_blessing(img, i);
917 ok = 1;
918 }
919 }
920 return ok;
921 }
922 if (blessing == ISO_HFSPLUS_BLESS_MAX)
923 return ISO_WRONG_ARG_VALUE;
924 if (flag & 1) {
925 /* Delete a particular blessing */
926 if (img->hfsplus_blessed[blessing] == node || node == NULL) {
927 unset_blessing(img, (unsigned int) blessing);
928 return 1;
929 }
930 return 0;
931 }
932
933 if (node == NULL) {
934 unset_blessing(img, (unsigned int) blessing);
935 return 1;
936 }
937
938 /* No two hats on one node */
939 for (i = 0; i < ISO_HFSPLUS_BLESS_MAX && node != NULL; i++)
940 if (i != blessing && img->hfsplus_blessed[i] == node)
941 return 0;
942 /* Enforce correct file type */
943 if (blessing == ISO_HFSPLUS_BLESS_INTEL_BOOTFILE) {
944 if (node->type != LIBISO_FILE)
945 return 0;
946 } else {
947 if (node->type != LIBISO_DIR)
948 return 0;
949 }
950
951 unset_blessing(img, (unsigned int) blessing);
952 img->hfsplus_blessed[blessing] = node;
953 if (node != NULL)
954 iso_node_ref(node);
955 return 1;
956 }
957
958
959 /* API */
960 int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
961 int *bless_max, int flag)
962 {
963 *blessed_nodes = img->hfsplus_blessed;
964 *bless_max = ISO_HFSPLUS_BLESS_MAX;
965 return 1;
966 }
967
968
969 /* API */
970 int iso_image_set_sparc_core(IsoImage *img, IsoFile *sparc_core, int flag)
971 {
972 if (img->sparc_core_node != NULL)
973 iso_node_unref((IsoNode *) img->sparc_core_node);
974 img->sparc_core_node = sparc_core;
975 if (sparc_core != NULL)
976 iso_node_ref((IsoNode *) sparc_core);
977 return 1;
978 }
979
980
981 /* API */
982 int iso_image_get_sparc_core(IsoImage *img, IsoFile **sparc_core, int flag)
983 {
984 *sparc_core = img->sparc_core_node;
985 return 1;
986 }
987
988
989 /* @param flag
990 bit0= Let NULL parameters free the corresponding image properties.
991 Else only the non-NULL parameters of this call have an effect.
992 */
993 static int hppa_palo_set_path(IsoImage *img, char *path, char **target,
994 char *what, int flag)
995 {
996 int ret, err;
997 IsoNode *node;
998 IsoFile *file;
999
1000 if (path == NULL && !(flag & 1))
1001 return ISO_SUCCESS;
1002 if (iso_clone_mgtd_mem(path, target, 0) < 0)
1003 return ISO_OUT_OF_MEM;
1004 if (path == NULL)
1005 return ISO_SUCCESS;
1006 ret = iso_tree_path_to_node(img, path, &node);
1007 if (ret < 0)
1008 return ret;
1009 if (ret == 0) {
1010 iso_msg_submit(img->id, ISO_BOOT_FILE_MISSING, 0,
1011 "Cannot find in ISO image: %s file '%s'", what, path);
1012 return ISO_BOOT_FILE_MISSING;
1013 }
1014 if (iso_node_get_type(node) != LIBISO_FILE) {
1015 err = ISO_HPPA_PALO_NOTREG;
1016 if (strncmp(what, "DEC Alpha", 9) == 0)
1017 err = ISO_ALPHA_BOOT_NOTREG;
1018 iso_msg_submit(img->id, err, 0,
1019 "%s file is not a data file: '%s'", what, path);
1020 return err;
1021 }
1022 file = (IsoFile *) node;
1023 if (!(file->explicit_weight || file->from_old_session))
1024 file->sort_weight = 2;
1025 return ISO_SUCCESS;
1026 }
1027
1028
1029 /* API */
1030 /* @param flag
1031 Bitfield for control purposes
1032 bit0= Let NULL parameters free the corresponding image properties.
1033 Else only the non-NULL parameters of this call have an effect.
1034 */
1035 int iso_image_set_hppa_palo(IsoImage *img, char *cmdline, char *bootloader,
1036 char *kernel_32, char *kernel_64, char *ramdisk,
1037 int flag)
1038 {
1039 int ret;
1040 static char *what = "HP-PA PALO";
1041
1042 if (cmdline != NULL || (flag & 1))
1043 if (iso_clone_mgtd_mem(cmdline, &(img->hppa_cmdline), 0) < 0)
1044 return ISO_OUT_OF_MEM;
1045 ret = hppa_palo_set_path(img, bootloader, &(img->hppa_bootloader), what,
1046 flag & 1);
1047 if (ret < 0)
1048 return ret;
1049 ret = hppa_palo_set_path(img, kernel_32, &(img->hppa_kernel_32), what,
1050 flag & 1);
1051 if (ret < 0)
1052 return ret;
1053 ret = hppa_palo_set_path(img, kernel_64, &(img->hppa_kernel_64), what,
1054 flag & 1);
1055 if (ret < 0)
1056 return ret;
1057 ret = hppa_palo_set_path(img, ramdisk, &(img->hppa_ramdisk), what,
1058 flag & 1);
1059 if (ret < 0)
1060 return ret;
1061 return ISO_SUCCESS;
1062 }
1063
1064
1065 /* API */
1066 int iso_image_get_hppa_palo(IsoImage *img, char **cmdline, char **bootloader,
1067 char **kernel_32, char **kernel_64, char **ramdisk)
1068 {
1069 *cmdline = img->hppa_cmdline;
1070 *bootloader = img->hppa_bootloader;
1071 *kernel_32 = img->hppa_kernel_32;
1072 *kernel_64 = img->hppa_kernel_64;
1073 *ramdisk = img->hppa_ramdisk;
1074 return ISO_SUCCESS;
1075 }
1076
1077
1078 /* API */
1079 int iso_image_set_alpha_boot(IsoImage *img, char *boot_loader_path, int flag)
1080 {
1081 int ret;
1082
1083 ret = hppa_palo_set_path(img, boot_loader_path, &(img->alpha_boot_image),
1084 "DEC Alpha Bootloader", 1);
1085 if (ret < 0)
1086 return ret;
1087 return ISO_SUCCESS;
1088 }
1089
1090
1091 /* API */
1092 int iso_image_get_alpha_boot(IsoImage *img, char **boot_loader_path)
1093 {
1094 *boot_loader_path = img->alpha_boot_image;
1095 return ISO_SUCCESS;
1096 }
1097
1098
1099 /* API */
1100 int iso_image_set_truncate_mode(IsoImage *img, int mode, int length)
1101 {
1102 if (mode < 0 || mode > 1)
1103 return ISO_WRONG_ARG_VALUE;
1104 if (length < 64 || length > LIBISOFS_NODE_NAME_MAX)
1105 return ISO_WRONG_ARG_VALUE;
1106 img->truncate_mode = mode;
1107 img->truncate_length = length;
1108 return ISO_SUCCESS;
1109 }
1110
1111 /* API */
1112 int iso_image_get_truncate_mode(IsoImage *img, int *mode, int *length)
1113 {
1114 *mode = img->truncate_mode;
1115 *length = img->truncate_length;
1116 return ISO_SUCCESS;
1117 }
1118
1119 /* Warning: Not thread-safe */
1120 int iso_image_truncate_name(IsoImage *image, const char *name, char **namept,
1121 int flag)
1122 {
1123 int ret;
1124
1125 if (name == NULL)
1126 return ISO_NULL_POINTER;
1127
1128 if ((int) strlen(name) <= image->truncate_length) {
1129 *namept = (char *) name;
1130 return ISO_SUCCESS;
1131 }
1132 *namept = image->truncate_buffer;
1133 if (name != image->truncate_buffer)
1134 strncpy(image->truncate_buffer, name, 4095);
1135 image->truncate_buffer[4095] = 0;
1136 ret = iso_truncate_rr_name(image->truncate_mode, image->truncate_length,
1137 image->truncate_buffer, 0);
1138 return ret;
1139 }
1140
1141
1142 /* API */
1143 int iso_image_was_blind_attrs(IsoImage *image, int flag)
1144 {
1145 int ret;
1146
1147 if (image == NULL)
1148 return ISO_NULL_POINTER;
1149 ret = image->blind_on_local_get_attrs;
1150 if (flag & 1)
1151 image->blind_on_local_get_attrs = 0;
1152 return ret;
1153 }
1154
1155
1156 /*
1157 * @param flag bit0= recursion is active
1158 */
1159 static
1160 int iso_dir_zisofs_discard_bpt(IsoDir *dir, int flag)
1161 {
1162 int ret;
1163 IsoDirIter *iter = NULL;
1164 IsoNode *node;
1165 IsoDir *subdir;
1166 IsoFile *file;
1167 IsoStream *stream;
1168
1169 ret = iso_dir_get_children(dir, &iter);
1170 if (ret < 0)
1171 return ret;
1172 while (iso_dir_iter_next(iter, &node) == 1) {
1173 if (iso_node_get_type(node) == LIBISO_DIR) {
1174 subdir = (IsoDir *) node;
1175 ret = iso_dir_zisofs_discard_bpt(subdir, flag | 1);
1176 if (ret < 0)
1177 goto ex;
1178 continue;
1179 }
1180 if (iso_node_get_type(node) != LIBISO_FILE)
1181 continue;
1182 file = (IsoFile *) node;
1183 stream = iso_file_get_stream(file);
1184 if (stream == NULL)
1185 continue;
1186 ret = iso_stream_zisofs_discard_bpt(stream, 0);
1187 if (ret < 0)
1188 goto ex;
1189 }
1190 ret = ISO_SUCCESS;
1191 ex:;
1192 if (iter != NULL)
1193 iso_dir_iter_free(iter);
1194 return ret;
1195 }
1196
1197
1198 /* API */
1199 int iso_image_zisofs_discard_bpt(IsoImage *image, int flag)
1200 {
1201 int ret;
1202 IsoDir *dir;
1203
1204 if (image == NULL)
1205 return ISO_NULL_POINTER;
1206 dir = image->root;
1207 if (dir == NULL)
1208 return ISO_SUCCESS;
1209 ret = iso_dir_zisofs_discard_bpt(dir, 0);
1210 return ret;
1211 }
1212