"Fossies" - the Fresh Open Source Software Archive

Member "libisofs-1.5.4/libisofs/image.c" (25 Oct 2020, 34473 Bytes) of package /linux/misc/libisofs-1.5.4.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 latest 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