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
iso_imported_sa_new(struct iso_imported_sys_area ** boots,int flag)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
iso_imported_sa_unref(struct iso_imported_sys_area ** boots,int flag)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 */
iso_image_new(const char * name,IsoImage ** image)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 */
iso_image_ref(IsoImage * image)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 */
iso_image_unref(IsoImage * image)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
iso_image_free_checksums(IsoImage * image,int flag)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 */
iso_image_attach_data(IsoImage * image,void * data,void (* give_up)(void *))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 */
iso_image_get_attached_data(IsoImage * image)329 void *iso_image_get_attached_data(IsoImage *image)
330 {
331 return image->user_data;
332 }
333
iso_image_get_root(const IsoImage * image)334 IsoDir *iso_image_get_root(const IsoImage *image)
335 {
336 return image->root;
337 }
338
iso_image_set_volset_id(IsoImage * image,const char * volset_id)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
iso_image_get_volset_id(const IsoImage * image)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
iso_image_set_volume_id(IsoImage * image,const char * volume_id)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
iso_image_get_volume_id(const IsoImage * image)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
iso_image_set_publisher_id(IsoImage * image,const char * publisher_id)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
iso_image_get_publisher_id(const IsoImage * image)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
iso_image_set_data_preparer_id(IsoImage * image,const char * data_preparer_id)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
iso_image_get_data_preparer_id(const IsoImage * image)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
iso_image_set_system_id(IsoImage * image,const char * system_id)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
iso_image_get_system_id(const IsoImage * image)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
iso_image_set_application_id(IsoImage * image,const char * application_id)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
iso_image_get_application_id(const IsoImage * image)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
iso_image_set_copyright_file_id(IsoImage * image,const char * copyright_file_id)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
iso_image_get_copyright_file_id(const IsoImage * image)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
iso_image_set_abstract_file_id(IsoImage * image,const char * abstract_file_id)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
iso_image_get_abstract_file_id(const IsoImage * image)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
iso_image_set_biblio_file_id(IsoImage * image,const char * biblio_file_id)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
iso_image_get_biblio_file_id(const IsoImage * image)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
iso_image_set_pvd_times(IsoImage * image,char * creation_time,char * modification_time,char * expiration_time,char * effective_time)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
iso_image_get_pvd_times(IsoImage * image,char ** creation_time,char ** modification_time,char ** expiration_time,char ** effective_time)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
iso_image_set_app_use(IsoImage * image,const char * app_use_data,int count)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
iso_image_get_msg_id(IsoImage * image)508 int iso_image_get_msg_id(IsoImage *image)
509 {
510 return image->id;
511 }
512
iso_image_get_system_area(IsoImage * img,char system_area_data[32768],int * options,int flag)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
dir_update_size(IsoImage * image,IsoDir * dir)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
iso_image_update_sizes(IsoImage * image)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
iso_image_set_ignore_aclea(IsoImage * image,int what)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
iso_image_get_ignore_aclea(IsoImage * image)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
img_register_ino(IsoImage * image,IsoNode * node,int flag)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 */
img_collect_inos(IsoImage * image,IsoDir * dir,int flag)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 */
img_give_ino_number(IsoImage * image,int flag)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
img_update_ino(IsoImage * image,IsoNode * node,int flag)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 */
img_make_inos(IsoImage * image,IsoDir * dir,int flag)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 */
iso_image_get_session_md5(IsoImage * image,uint32_t * start_lba,uint32_t * end_lba,char md5[16],int flag)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
iso_image_set_checksums(IsoImage * image,char * checksum_array,uint32_t start_lba,uint32_t end_lba,uint32_t idx_count,int flag)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
iso_image_generator_is_running(IsoImage * image)855 int iso_image_generator_is_running(IsoImage *image)
856 {
857 return image->generator_is_running;
858 }
859
860
861 /* API */
iso_image_add_mips_boot_file(IsoImage * image,char * path,int flag)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 */
iso_image_get_mips_boot_files(IsoImage * image,char * paths[15],int flag)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 */
iso_image_give_up_mips_boot(IsoImage * image,int flag)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
unset_blessing(IsoImage * img,unsigned int idx)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 */
iso_image_hfsplus_bless(IsoImage * img,enum IsoHfsplusBlessings blessing,IsoNode * node,int flag)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 */
iso_image_hfsplus_get_blessed(IsoImage * img,IsoNode *** blessed_nodes,int * bless_max,int flag)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 */
iso_image_set_sparc_core(IsoImage * img,IsoFile * sparc_core,int flag)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 */
iso_image_get_sparc_core(IsoImage * img,IsoFile ** sparc_core,int flag)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 */
hppa_palo_set_path(IsoImage * img,char * path,char ** target,char * what,int flag)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 */
iso_image_set_hppa_palo(IsoImage * img,char * cmdline,char * bootloader,char * kernel_32,char * kernel_64,char * ramdisk,int flag)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 */
iso_image_get_hppa_palo(IsoImage * img,char ** cmdline,char ** bootloader,char ** kernel_32,char ** kernel_64,char ** ramdisk)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 */
iso_image_set_alpha_boot(IsoImage * img,char * boot_loader_path,int flag)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 */
iso_image_get_alpha_boot(IsoImage * img,char ** boot_loader_path)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 */
iso_image_set_truncate_mode(IsoImage * img,int mode,int length)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 */
iso_image_get_truncate_mode(IsoImage * img,int * mode,int * length)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 */
iso_image_truncate_name(IsoImage * image,const char * name,char ** namept,int flag)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 */
iso_image_was_blind_attrs(IsoImage * image,int flag)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
iso_dir_zisofs_discard_bpt(IsoDir * dir,int flag)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 */
iso_image_zisofs_discard_bpt(IsoImage * image,int flag)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
1213