From 2e99e1aac92b102e81381feca95d4bfaed4d9481 Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Tue, 19 Aug 2008 02:45:20 +0200 Subject: [PATCH] Add support for multisession on Level 3 images. --- libisofs/buffer.c | 44 ++++---- libisofs/ecma119.c | 64 ++++-------- libisofs/eltorito.c | 181 ++++++++++++++++---------------- libisofs/filesrc.c | 40 ++++++- libisofs/filesrc.h | 28 ++--- libisofs/iso1999.c | 122 +++++++++++----------- libisofs/joliet.c | 122 ++++++++++++---------- libisofs/node.c | 246 +++++++++++++++++++++++--------------------- libisofs/node.h | 111 ++++++++++---------- 9 files changed, 497 insertions(+), 461 deletions(-) diff --git a/libisofs/buffer.c b/libisofs/buffer.c index c59bad1..a5d528b 100644 --- a/libisofs/buffer.c +++ b/libisofs/buffer.c @@ -1,19 +1,19 @@ /* * Copyright (c) 2007 Vreixo Formoso - * - * This file is part of the libisofs project; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 as + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See COPYING file for details. */ /* * Synchronized ring buffer, works with a writer thread and a read thread. - * + * * TODO #00010 : optimize ring buffer * - write/read at the end of buffer requires a second mutex_lock, even if * there's enought space/data at the beginning * - pre-buffer for writes < BLOCK_SIZE - * + * */ #include "buffer.h" @@ -30,13 +30,13 @@ struct iso_ring_buffer { uint8_t *buf; - + /* * Max number of bytes in buffer */ size_t cap; - /* + /* * Number of bytes available. */ size_t size; @@ -45,11 +45,11 @@ struct iso_ring_buffer size_t rpos; size_t wpos; - /* + /* * flags to report if read or writer threads ends execution - * 0 not finished, 1 finished ok, 2 finish with error + * 0 not finished, 1 finished ok, 2 finish with error */ - unsigned int rend :2; + unsigned int rend :2; unsigned int wend :2; /* just for statistical purposes */ @@ -63,9 +63,9 @@ struct iso_ring_buffer /** * Create a new buffer. - * + * * The created buffer should be freed with iso_ring_buffer_free() - * + * * @param size * Number of blocks in buffer. You should supply a number >= 32, otherwise * size will be ignored and 32 will be used by default, which leads to a @@ -85,14 +85,14 @@ int iso_ring_buffer_new(size_t size, IsoRingBuffer **rbuf) if (buffer == NULL) { return ISO_OUT_OF_MEM; } - + buffer->cap = (size > 32 ? size : 32) * BLOCK_SIZE; buffer->buf = malloc(buffer->cap); if (buffer->buf == NULL) { free(buffer); return ISO_OUT_OF_MEM; } - + buffer->size = 0; buffer->wpos = 0; buffer->rpos = 0; @@ -126,7 +126,7 @@ void iso_ring_buffer_free(IsoRingBuffer *buf) /** * Write count bytes into buffer. It blocks until all bytes where written or * reader close the buffer. - * + * * @param buf * the buffer * @param data @@ -189,7 +189,7 @@ int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count) * bytes has been read. If the writer finishes before outputting enought * bytes, 0 (EOF) is returned, the number of bytes already read remains * unknown. - * + * * @return * 1 success, 0 EOF, < 0 error */ @@ -252,7 +252,7 @@ void iso_ring_buffer_writer_close(IsoRingBuffer *buf, int error) void iso_ring_buffer_reader_close(IsoRingBuffer *buf, int error) { pthread_mutex_lock(&buf->mutex); - + if (buf->rend) { /* reader already closed */ pthread_mutex_unlock(&buf->mutex); @@ -285,9 +285,9 @@ unsigned int iso_ring_buffer_get_times_empty(IsoRingBuffer *buf) /** * Get the status of the buffer used by a burn_source. - * + * * @param b - * A burn_source previously obtained with + * A burn_source previously obtained with * iso_image_create_burn_source(). * @param size * Will be filled with the total size of the buffer, in bytes @@ -302,7 +302,7 @@ unsigned int iso_ring_buffer_get_times_empty(IsoRingBuffer *buf) * 6="ended" : consumption has ended without input error * 7="aborted" : consumption has ended after input error */ -int iso_ring_buffer_get_status(struct burn_source *b, size_t *size, +int iso_ring_buffer_get_status(struct burn_source *b, size_t *size, size_t *free_bytes) { int ret; @@ -311,7 +311,7 @@ int iso_ring_buffer_get_status(struct burn_source *b, size_t *size, return ISO_NULL_POINTER; } buf = ((Ecma119Image*)(b->data))->buffer; - + /* get mutex */ pthread_mutex_lock(&buf->mutex); if (size) { @@ -322,7 +322,7 @@ int iso_ring_buffer_get_status(struct burn_source *b, size_t *size, } ret = (buf->rend ? 4 : 0) + (buf->wend + 1); - + pthread_mutex_unlock(&buf->mutex); return ret; } diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index 6107cd0..45f524a 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -241,7 +241,7 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id, uint32_t len; uint32_t block; uint8_t len_dr; /*< size of dir entry without SUSP fields */ - int multi_extend = 0; + int multi_extend = 0; uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id : (uint8_t*)node->iso_name; @@ -262,17 +262,9 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id, len = node->info.dir->len; block = node->info.dir->block; } else if (node->type == ECMA119_FILE) { - off_t size = iso_file_src_get_size(node->info.file) - - ((off_t)0xFFFFF800) * (off_t)extent; /* bytes in another extent */ - if (size > (off_t) 0xffffffff) { - /* 2097151 is the number of blocks needed to store 4 GB - 2048 */ - block = node->info.file->block + extent * 2097151; - len = 0xFFFFF800; - multi_extend = 1; - } else { - len = (uint32_t) size; - block = node->info.file->block; - } + block = node->info.file->sections[extent].block; + len = node->info.file->sections[extent].size; + multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1; } else { /* * for nodes other than files and dirs, we set both @@ -457,26 +449,27 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir) buf += len; for (i = 0; i < dir->info.dir->nchildren; i++) { + int section, nsections; Ecma119Node *child = dir->info.dir->children[i]; - int extent = 0; - do { + /* compute len of directory entry */ + fi_len = strlen(child->iso_name); + len = fi_len + 33 + (fi_len % 2 ? 0 : 1); + if (need_version_number(t, child)) { + len += 2; + } - /* compute len of directory entry */ - fi_len = strlen(child->iso_name); - len = fi_len + 33 + (fi_len % 2 ? 0 : 1); - if (need_version_number(t, child)) { - len += 2; + /* get the SUSP fields if rockridge is enabled */ + if (t->rockridge) { + ret = rrip_get_susp_fields(t, child, 0, 255 - len, &info); + if (ret < 0) { + return ret; } + len += info.suf_len; + } - /* get the SUSP fields if rockridge is enabled */ - if (t->rockridge) { - ret = rrip_get_susp_fields(t, child, 0, 255 - len, &info); - if (ret < 0) { - return ret; - } - len += info.suf_len; - } + nsections = (child->type == ECMA119_FILE) ? child->info.file->nsections : 1; + for (section = 0; section < nsections; ++section) { if ( (buf + len - buffer) > BLOCK_SIZE) { /* dir doesn't fit in current block */ @@ -488,22 +481,9 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir) buf = buffer; } /* write the directory entry in any case */ - write_one_dir_record(t, child, -1, buf, fi_len, &info, extent); + write_one_dir_record(t, child, -1, buf, fi_len, &info, section); buf += len; - - if (child->type == ECMA119_FILE) { - /* check if file is too big and need more extents */ - off_t size = iso_file_src_get_size(child->info.file) - - ((off_t)0xFFFFF800) * (off_t)extent; - if (size > (off_t) 0xffffffff) { - extent++; - } else { - break; - } - } else { - break; /* we only have a single extent */ - } - } while(1); /* loop for each extend */ + } } /* write the last block */ diff --git a/libisofs/eltorito.c b/libisofs/eltorito.c index 441b5c1..7462bea 100644 --- a/libisofs/eltorito.c +++ b/libisofs/eltorito.c @@ -1,8 +1,8 @@ /* * Copyright (c) 2007 Vreixo Formoso - * - * This file is part of the libisofs project; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 as + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See COPYING file for details. */ @@ -26,7 +26,7 @@ struct boot_info_table { uint8_t bi_file BP(5, 8); /* LBA of boot file */ uint8_t bi_length BP(9, 12); /* Length of boot file */ uint8_t bi_csum BP(13, 16); /* Checksum of boot file */ - uint8_t bi_reserved BP(17, 56); /* Reserved */ + uint8_t bi_reserved BP(17, 56); /* Reserved */ }; /** @@ -67,7 +67,7 @@ void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment) /** * Sets the number of sectors (512b) to be load at load segment during - * the initial boot procedure. This is only for no emulation boot images, + * the initial boot procedure. This is only for no emulation boot images, * and is a NOP for other image types. */ void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors) @@ -109,7 +109,7 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot) if (boot) { *boot = NULL; } - + /* check if the name is valid */ if (!iso_node_is_valid_name(name)) { return ISO_WRONG_ARG_VALUE; @@ -162,7 +162,7 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot) } -static +static int create_image(IsoImage *image, const char *image_path, enum eltorito_boot_media_type type, struct el_torito_boot_image **bootimg) @@ -182,18 +182,18 @@ int create_image(IsoImage *image, const char *image_path, if (ret == 0) { return ISO_NODE_DOESNT_EXIST; } - + if (imgfile->type != LIBISO_FILE) { return ISO_BOOT_IMAGE_NOT_VALID; } - + stream = ((IsoFile*)imgfile)->stream; - + /* we need to read the image at least two times */ if (!iso_stream_is_repeatable(stream)) { return ISO_BOOT_IMAGE_NOT_VALID; } - + switch (type) { case ELTORITO_FLOPPY_EMUL: switch (iso_stream_get_size(stream)) { @@ -211,9 +211,9 @@ int create_image(IsoImage *image, const char *image_path, "Invalid image size %d Kb. Must be one of 1.2, 1.44" "or 2.88 Mb", iso_stream_get_size(stream) / 1024); return ISO_BOOT_IMAGE_NOT_VALID; - break; + break; } - /* it seems that for floppy emulation we need to load + /* it seems that for floppy emulation we need to load * a single sector (512b) */ load_sectors = 1; break; @@ -222,7 +222,7 @@ int create_image(IsoImage *image, const char *image_path, size_t i; struct hard_disc_mbr mbr; int used_partition; - + /* read the MBR on disc and get the type of the partition */ ret = iso_stream_open(stream); if (ret < 0) { @@ -237,14 +237,14 @@ int create_image(IsoImage *image, const char *image_path, "Can't read MBR from image file."); return ret < 0 ? ret : ISO_FILE_READ_ERROR; } - + /* check valid MBR signature */ if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) { iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, "Invalid MBR. Wrong signature."); return ISO_BOOT_IMAGE_NOT_VALID; } - + /* ensure single partition */ used_partition = -1; for (i = 0; i < 4; ++i) { @@ -252,7 +252,7 @@ int create_image(IsoImage *image, const char *image_path, /* it's an used partition */ if (used_partition != -1) { iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, - "Invalid MBR. At least 2 partitions: %d and " + "Invalid MBR. At least 2 partitions: %d and " "%d, are being used\n", used_partition, i); return ISO_BOOT_IMAGE_NOT_VALID; } else @@ -262,15 +262,15 @@ int create_image(IsoImage *image, const char *image_path, partition_type = mbr.partition[used_partition].type; } boot_media_type = 4; - + /* only load the MBR */ load_sectors = 1; break; case ELTORITO_NO_EMUL: boot_media_type = 0; - break; + break; } - + boot = calloc(1, sizeof(struct el_torito_boot_image)); if (boot == NULL) { return ISO_OUT_OF_MEM; @@ -281,11 +281,11 @@ int create_image(IsoImage *image, const char *image_path, boot->type = boot_media_type; boot->load_size = load_sectors; boot->partition_type = partition_type; - + if (bootimg) { *bootimg = boot; } - + return ISO_SUCCESS; } @@ -298,14 +298,14 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path, struct el_torito_boot_catalog *catalog; ElToritoBootImage *boot_image= NULL; IsoBoot *cat_node= NULL; - + if (image == NULL || image_path == NULL || catalog_path == NULL) { return ISO_NULL_POINTER; } if (image->bootcat != NULL) { return ISO_IMAGE_ALREADY_BOOTABLE; } - + /* create the node for the catalog */ { IsoDir *parent; @@ -314,8 +314,8 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path, if (catdir == NULL) { return ISO_OUT_OF_MEM; } - - /* get both the dir and the name */ + + /* get both the dir and the name */ catname = strrchr(catdir, '/'); if (catname == NULL) { free(catdir); @@ -345,13 +345,13 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path, return ret; } } - + /* create the boot image */ ret = create_image(image, image_path, type, &boot_image); if (ret < 0) { goto boot_image_cleanup; } - + /* creates the catalog with the given image */ catalog = malloc(sizeof(struct el_torito_boot_catalog)); if (catalog == NULL) { @@ -362,13 +362,13 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path, catalog->node = cat_node; iso_node_ref((IsoNode*)cat_node); image->bootcat = catalog; - + if (boot) { *boot = boot_image; } - + return ISO_SUCCESS; - + boot_image_cleanup:; if (cat_node) { iso_node_take((IsoNode*)cat_node); @@ -383,32 +383,32 @@ boot_image_cleanup:; /** * Get El-Torito boot image of an ISO image, if any. - * + * * This can be useful, for example, to check if a volume read from a previous * session or an existing image is bootable. It can also be useful to get - * the image and catalog tree nodes. An application would want those, for + * the image and catalog tree nodes. An application would want those, for * example, to prevent the user removing it. - * + * * Both nodes are owned by libisofs and should not be freed. You can get your - * own ref with iso_node_ref(). You can can also check if the node is already - * on the tree by getting its parent (note that when reading El-Torito info - * from a previous image, the nodes might not be on the tree even if you haven't - * removed them). Remember that you'll need to get a new ref - * (with iso_node_ref()) before inserting them again to the tree, and probably + * own ref with iso_node_ref(). You can can also check if the node is already + * on the tree by getting its parent (note that when reading El-Torito info + * from a previous image, the nodes might not be on the tree even if you haven't + * removed them). Remember that you'll need to get a new ref + * (with iso_node_ref()) before inserting them again to the tree, and probably * you will also need to set the name or permissions. - * + * * @param image * The image from which to get the boot image. * @param boot - * If not NULL, it will be filled with a pointer to the boot image, if - * any. That object is owned by the IsoImage and should not be freed by + * If not NULL, it will be filled with a pointer to the boot image, if + * any. That object is owned by the IsoImage and should not be freed by * the user, nor dereferenced once the last reference to the IsoImage was * disposed via iso_image_unref(). - * @param imgnode + * @param imgnode * When not NULL, it will be filled with the image tree node. No extra ref * is added, you can use iso_node_ref() to get one if you need it. - * @param catnode - * When not NULL, it will be filled with the catnode tree node. No extra + * @param catnode + * When not NULL, it will be filled with the catnode tree node. No extra * ref is added, you can use iso_node_ref() to get one if you need it. * @return * 1 on success, 0 is the image is not bootable (i.e., it has no El-Torito @@ -423,7 +423,7 @@ int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot, if (image->bootcat == NULL) { return 0; } - + /* ok, image is bootable */ if (boot) { *boot = image->bootcat->image; @@ -438,8 +438,8 @@ int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot, } /** - * Removes the El-Torito bootable image. - * + * Removes the El-Torito bootable image. + * * The IsoBoot node that acts as placeholder for the catalog is also removed * for the image tree, if there. * If the image is not bootable (don't have el-torito boot image) this function @@ -449,13 +449,13 @@ void iso_image_remove_boot_image(IsoImage *image) { if (image == NULL || image->bootcat == NULL) return; - - /* - * remove catalog node from its parent - * (the reference will be disposed next) + + /* + * remove catalog node from its parent + * (the reference will be disposed next) */ iso_node_take((IsoNode*)image->bootcat->node); - + /* free boot catalog and image, including references to nodes */ el_torito_boot_catalog_free(image->bootcat); image->bootcat = NULL; @@ -464,11 +464,11 @@ void iso_image_remove_boot_image(IsoImage *image) void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat) { struct el_torito_boot_image *image; - + if (cat == NULL) { return; } - + image = cat->image; iso_node_unref((IsoNode*)image->image); free(image); @@ -486,19 +486,19 @@ struct catalog_stream int offset; /* -1 if stream is not openned */ }; -static void +static void write_validation_entry(uint8_t *buf) { size_t i; int checksum; - - struct el_torito_validation_entry *ve = + + struct el_torito_validation_entry *ve = (struct el_torito_validation_entry*)buf; ve->header_id[0] = 1; ve->platform_id[0] = 0; /* 0: 80x86, 1: PowerPC, 2: Mac */ ve->key_byte1[0] = 0x55; ve->key_byte2[0] = 0xAA; - + /* calculate the checksum, to ensure sum of all words is 0 */ checksum = 0; for (i = 0; i < sizeof(struct el_torito_validation_entry); i += 2) { @@ -515,9 +515,9 @@ static void write_section_entry(uint8_t *buf, Ecma119Image *t) { struct el_torito_boot_image *img; - struct el_torito_section_entry *se = + struct el_torito_section_entry *se = (struct el_torito_section_entry*)buf; - + img = t->catalog->image; se->boot_indicator[0] = img->bootable ? 0x88 : 0x00; @@ -525,7 +525,7 @@ write_section_entry(uint8_t *buf, Ecma119Image *t) iso_lsb(se->load_seg, img->load_seg, 2); se->system_type[0] = img->partition_type; iso_lsb(se->sec_count, img->load_size, 2); - iso_lsb(se->block, t->bootimg->block, 4); + iso_lsb(se->block, t->bootimg->sections[0].block, 4); } static @@ -536,13 +536,13 @@ int catalog_open(IsoStream *stream) return ISO_NULL_POINTER; } data = stream->data; - + if (data->offset != -1) { return ISO_FILE_ALREADY_OPENED; } - + memset(data->buffer, 0, BLOCK_SIZE); - + /* fill the buffer with the catalog contents */ write_validation_entry(data->buffer); @@ -561,7 +561,7 @@ int catalog_close(IsoStream *stream) return ISO_NULL_POINTER; } data = stream->data; - + if (data->offset == -1) { return ISO_FILE_NOT_OPENED; } @@ -587,11 +587,11 @@ int catalog_read(IsoStream *stream, void *buf, size_t count) return ISO_WRONG_ARG_VALUE; } data = stream->data; - + if (data->offset == -1) { return ISO_FILE_NOT_OPENED; } - + len = MIN(count, BLOCK_SIZE - data->offset); memcpy(buf, data->buffer + data->offset, len); return len; @@ -606,7 +606,7 @@ int catalog_is_repeatable(IsoStream *stream) /** * fs_id will be the id reserved for El-Torito * dev_id will be 0 for catalog, 1 for boot image (if needed) - * we leave ino_id for future use when we support multiple boot images + * we leave ino_id for future use when we support multiple boot images */ static void catalog_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, @@ -636,7 +636,7 @@ IsoStreamIface catalog_stream_class = { }; /** - * Create an IsoStream for writing El-Torito catalog for a given target. + * Create an IsoStream for writing El-Torito catalog for a given target. */ static int catalog_stream_new(Ecma119Image *target, IsoStream **stream) @@ -675,17 +675,17 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src) int ret; IsoFileSrc *file; IsoStream *stream; - + if (target == NULL || src == NULL || target->catalog == NULL) { return ISO_OUT_OF_MEM; } - + if (target->cat != NULL) { /* catalog file src already created */ *src = target->cat; return ISO_SUCCESS; } - + file = malloc(sizeof(IsoFileSrc)); if (file == NULL) { return ISO_OUT_OF_MEM; @@ -696,10 +696,11 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src) free(file); return ret; } - + /* fill fields */ file->prev_img = 0; /* TODO allow copy of old img catalog???? */ - file->block = 0; /* to be filled later */ + file->nsections = 0; /* to be filled later */ + file->sections = NULL; file->sort_weight = 1000; /* slightly high */ file->stream = stream; @@ -746,34 +747,34 @@ int eltorito_writer_write_vol_desc(IsoImageWriter *writer) memcpy(vol.std_identifier, "CD001", 5); vol.vol_desc_version[0] = 1; memcpy(vol.boot_sys_id, "EL TORITO SPECIFICATION", 23); - iso_lsb(vol.boot_catalog, t->cat->block, 4); - + iso_lsb(vol.boot_catalog, t->cat->sections[0].block, 4); + return iso_write(t, &vol, sizeof(struct ecma119_boot_rec_vol_desc)); } /** * Patch an isolinux boot image. - * + * * @return * 1 on success, 0 error (but continue), < 0 error */ -static +static int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize) { struct boot_info_table *info; uint32_t checksum; size_t offset; - + if (imgsize < 64) { return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0, "Isolinux image too small. We won't patch it."); } - + /* compute checksum, as the the sum of all 32 bit words in boot image * from offset 64 */ checksum = 0; offset = (size_t) 64; - + while (offset <= imgsize - 4) { checksum += iso_read_lsb(buf + offset, 4); offset += 4; @@ -783,12 +784,12 @@ int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize) return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0, "Unexpected isolinux image length. Patch might not work."); } - + /* patch boot info table */ info = (struct boot_info_table*)(buf + 8); /*memset(info, 0, sizeof(struct boot_info_table));*/ iso_lsb(info->bi_pvd, t->ms_block + 16, 4); - iso_lsb(info->bi_file, t->bootimg->block, 4); + iso_lsb(info->bi_file, t->bootimg->sections[0].block, 4); iso_lsb(info->bi_length, imgsize, 4); iso_lsb(info->bi_csum, checksum, 4); return ISO_SUCCESS; @@ -799,7 +800,7 @@ int eltorito_writer_write_data(IsoImageWriter *writer) { /* * We have nothing to write, but if we need to patch an isolinux image, - * this is a good place to do so. + * this is a good place to do so. */ Ecma119Image *t; int ret; @@ -809,7 +810,7 @@ int eltorito_writer_write_data(IsoImageWriter *writer) } t = writer->target; - + if (t->catalog->image->isolinux) { /* we need to patch the image */ size_t size; @@ -830,13 +831,13 @@ int eltorito_writer_write_data(IsoImageWriter *writer) if (ret != size) { return (ret < 0) ? ret : ISO_FILE_READ_ERROR; } - + /* ok, patch the read buffer */ ret = patch_boot_image(buf, t, size); if (ret < 0) { return ret; } - + /* replace the original stream with a memory stream that reads from * the patched buffer */ ret = iso_memory_stream_new(buf, size, &new); @@ -878,7 +879,7 @@ int eltorito_writer_create(Ecma119Image *target) /* add this writer to image */ target->writers[target->nwriters++] = writer; - /* + /* * get catalog and image file sources. * Note that the catalog may be already added, when creating the low * level ECMA-119 tree. @@ -895,7 +896,7 @@ int eltorito_writer_create(Ecma119Image *target) return ret; } target->bootimg = src; - + /* if we have selected to patch the image, it needs to be copied always */ if (target->catalog->image->isolinux) { src->prev_img = 0; diff --git a/libisofs/filesrc.c b/libisofs/filesrc.c index 32a1e25..c1f7af8 100644 --- a/libisofs/filesrc.c +++ b/libisofs/filesrc.c @@ -61,20 +61,28 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src) iso_stream_get_id(file->stream, &fs_id, &dev_id, &ino_id); - fsrc = malloc(sizeof(IsoFileSrc)); + fsrc = calloc(1, sizeof(IsoFileSrc)); if (fsrc == NULL) { return ISO_OUT_OF_MEM; } /* fill key and other atts */ - fsrc->prev_img = file->msblock ? 1 : 0; - fsrc->block = file->msblock; + fsrc->prev_img = file->from_old_session; + if (file->from_old_session) { + int ret = iso_file_get_old_image_sections(file, &(fsrc->nsections), + &(fsrc->sections), 0); + if (ret < 0) { + free(fsrc); + return ISO_OUT_OF_MEM; + } + } fsrc->sort_weight = file->sort_weight; fsrc->stream = file->stream; /* insert the filesrc in the tree */ ret = iso_rbtree_insert(img->files, fsrc, (void**)src); if (ret <= 0) { + free(fsrc->sections); free(fsrc); return ret; } @@ -117,6 +125,7 @@ int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src) void iso_file_src_free(void *node) { iso_stream_unref(((IsoFileSrc*)node)->stream); + free(((IsoFileSrc*)node)->sections); free(node); } @@ -174,8 +183,31 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer) /* fill block value */ for (i = 0; i < size; ++i) { + int extent = 0; IsoFileSrc *file = filelist[i]; - file->block = t->curblock; + + off_t section_size = iso_stream_get_size(file->stream); + if (section_size > (off_t) 0xffffffff) { + file->nsections = DIV_UP(iso_stream_get_size(file->stream) + - (off_t) 0xffffffff, (off_t)0xFFFFF800) + 1; + } else { + file->nsections = 1; + } + file->sections = realloc(file->sections, file->nsections * + sizeof(struct iso_file_section)); + for (extent = 0; extent < file->nsections - 1; ++extent) { + file->sections[extent].block = t->curblock + extent * 2097151; + file->sections[extent].size = 0xFFFFF800; + section_size -= (off_t) 0xFFFFF800; + } + + /* + * final section + */ + file->sections[extent].block = t->curblock + extent * 2097151; + file->sections[extent].size = section_size; + section_size -= (off_t) 0xFFFFF800; + t->curblock += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE); } diff --git a/libisofs/filesrc.h b/libisofs/filesrc.h index 5a3c03c..88e4760 100644 --- a/libisofs/filesrc.h +++ b/libisofs/filesrc.h @@ -1,8 +1,8 @@ /* * Copyright (c) 2007 Vreixo Formoso - * - * This file is part of the libisofs project; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 as + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See COPYING file for details. */ #ifndef LIBISO_FILESRC_H_ @@ -17,7 +17,11 @@ struct Iso_File_Src { unsigned int prev_img :1; /**< if the file comes from a previous image */ - uint32_t block; /**< Block where this file will be written on image */ + + /** File Sections of the file in the image */ + struct iso_file_section *sections; + int nsections; + int sort_weight; IsoStream *stream; }; @@ -26,12 +30,12 @@ int iso_file_src_cmp(const void *n1, const void *n2); /** * Create a new IsoFileSrc to get data from a specific IsoFile. - * - * The IsoFileSrc will be cached in a tree to prevent the same file for + * + * The IsoFileSrc will be cached in a tree to prevent the same file for * being written several times to image. If you call again this function * with a node that refers to the same source file, the previously * created one will be returned. No new IsoFileSrc is created in that case. - * + * * @param img * The image where this file is to be written * @param file @@ -45,12 +49,12 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src); /** * Add a given IsoFileSrc to the given image target. - * - * The IsoFileSrc will be cached in a tree to prevent the same file for + * + * The IsoFileSrc will be cached in a tree to prevent the same file for * being written several times to image. If you call again this function * with a node that refers to the same source file, the previously * created one will be returned. - * + * * @param img * The image where this file is to be written * @param new @@ -58,7 +62,7 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src); * @param src * Will be filled with a pointer to the IsoFileSrc really present in * the tree. It could be different than new if the same file already - * exists in the tree. + * exists in the tree. * @return * 1 on success, 0 if file already exists on tree, < 0 error */ @@ -76,7 +80,7 @@ off_t iso_file_src_get_size(IsoFileSrc *file); /** * Create a Writer for file contents. - * + * * It takes care of written the files in the correct order. */ int iso_file_src_writer_create(Ecma119Image *target); diff --git a/libisofs/iso1999.c b/libisofs/iso1999.c index 827d5ad..d8870ae 100644 --- a/libisofs/iso1999.c +++ b/libisofs/iso1999.c @@ -1,8 +1,8 @@ /* * Copyright (c) 2007 Vreixo Formoso - * - * This file is part of the libisofs project; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 as + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See COPYING file for details. */ @@ -32,7 +32,7 @@ int get_iso1999_name(Ecma119Image *t, const char *str, char **fname) *fname = NULL; return ISO_SUCCESS; } - + if (!strcmp(t->input_charset, t->output_charset)) { /* no conversion needed */ name = strdup(str); @@ -50,14 +50,14 @@ int get_iso1999_name(Ecma119Image *t, const char *str, char **fname) name = strdup(str); } } - + /* ISO 9660:1999 7.5.1 */ if (strlen(name) > 207) { name[207] = '\0'; } - + *fname = name; - + return ISO_SUCCESS; } @@ -117,7 +117,7 @@ int create_node(Ecma119Image *t, IsoNode *iso, Iso1999Node **node) IsoFile *file = (IsoFile*) iso; size = iso_stream_get_size(file->stream); - if (size > (off_t)0xffffffff) { + if (size > (off_t)0xffffffff && t->iso_level != 3) { free(n); return iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0, "File \"%s\" can't be added to image because is " @@ -159,7 +159,7 @@ int create_node(Ecma119Image *t, IsoNode *iso, Iso1999Node **node) /** * Create the low level ISO 9660:1999 tree from the high level ISO tree. - * + * * @return * 1 success, 0 file ignored, < 0 error */ @@ -230,7 +230,7 @@ int create_tree(Ecma119Image *t, IsoNode *iso, Iso1999Node **tree, int pathlen) } else { /* log and ignore */ ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0, - "El-Torito catalog found on a image without El-Torito.", + "El-Torito catalog found on a image without El-Torito.", iso->name); } break; @@ -238,7 +238,7 @@ int create_tree(Ecma119Image *t, IsoNode *iso, Iso1999Node **tree, int pathlen) case LIBISO_SPECIAL: ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0, "Can't add %s to ISO 9660:1999 tree. This kind of files " - "can only be added to a Rock Ridget tree. Skipping.", + "can only be added to a Rock Ridget tree. Skipping.", iso->name); break; default: @@ -269,15 +269,15 @@ cmp_node(const void *f1, const void *f2) } /** - * Sort the entries inside an ISO 9660:1999 directory, according to - * ISO 9660:1999, 9.3 + * Sort the entries inside an ISO 9660:1999 directory, according to + * ISO 9660:1999, 9.3 */ -static +static void sort_tree(Iso1999Node *root) { size_t i; - qsort(root->info.dir->children, root->info.dir->nchildren, + qsort(root->info.dir->children, root->info.dir->nchildren, sizeof(void*), cmp_node); for (i = 0; i < root->info.dir->nchildren; i++) { Iso1999Node *child = root->info.dir->children[i]; @@ -297,9 +297,9 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir) nchildren = dir->info.dir->nchildren; children = dir->info.dir->children; - + /* a hash table will temporary hold the names, for fast searching */ - ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash, + ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash, (compare_function_t)strcmp, &table); if (ret < 0) { return ret; @@ -320,7 +320,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir) int digits = 1; /* characters to change per name */ /* first, find all child with same name */ - while (j + 1 < nchildren && + while (j + 1 < nchildren && !cmp_node(children + i, children + j + 1)) { ++j; } @@ -330,7 +330,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir) } /* - * A max of 7 characters is good enought, it allows handling up to + * A max of 7 characters is good enought, it allows handling up to * 9,999,999 files with same name. */ while (digits < 8) { @@ -345,7 +345,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir) dot = strrchr(full_name, '.'); if (dot != NULL && children[i]->type != ISO1999_DIR) { - /* + /* * File (not dir) with extension. */ int extlen; @@ -358,17 +358,17 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir) if (max <= 0) { /* this can happen if extension is too long */ if (extlen + max > 3) { - /* + /* * reduce extension len, to give name an extra char - * note that max is negative or 0 + * note that max is negative or 0 */ extlen = extlen + max - 1; ext[extlen] = '\0'; max = 207 - extlen - 1 - digits; } else { - /* + /* * error, we don't support extensions < 3 - * This can't happen with current limit of digits. + * This can't happen with current limit of digits. */ ret = ISO_ERROR; goto mangle_cleanup; @@ -428,7 +428,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir) children[k]->name = new; iso_htable_add(table, new, new); - /* + /* * if we change a name we need to sort again children * at the end */ @@ -459,7 +459,7 @@ int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir) } ret = ISO_SUCCESS; - + mangle_cleanup : ; iso_htable_destroy(table, NULL); return ret; @@ -494,7 +494,7 @@ int iso1999_tree_create(Ecma119Image *t) { int ret; Iso1999Node *root; - + if (t == NULL) { return ISO_NULL_POINTER; } @@ -507,7 +507,7 @@ int iso1999_tree_create(Ecma119Image *t) } return ret; } - + /* the ISO 9660:1999 tree is stored in Ecma119Image target */ t->iso1999_root = root; @@ -559,10 +559,10 @@ size_t calc_dir_size(Ecma119Image *t, Iso1999Node *dir) len += dirent_len; } } - + /* - * The size of a dir is always a multiple of block size, as we must add - * the size of the unused space after the last directory record + * The size of a dir is always a multiple of block size, as we must add + * the size of the unused space after the last directory record * (ISO 9660:1999, 6.8.1.3) */ len = ROUND_UP(len, BLOCK_SIZE); @@ -626,7 +626,7 @@ int iso1999_writer_compute_data_blocks(IsoImageWriter *writer) t = writer->target; /* compute position of directories */ - iso_msg_debug(t->image->id, + iso_msg_debug(t->image->id, "Computing position of ISO 9660:1999 dir structure"); t->iso1999_ndirs = 0; calc_dir_pos(t, t->iso1999_root); @@ -647,7 +647,7 @@ int iso1999_writer_compute_data_blocks(IsoImageWriter *writer) /** * Write a single directory record (ISO 9660:1999, 9.1). - * + * * @param file_id * if >= 0, we use it instead of the filename (for "." and ".." entries). * @param len_fi @@ -655,11 +655,12 @@ int iso1999_writer_compute_data_blocks(IsoImageWriter *writer) */ static void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id, - uint8_t *buf, size_t len_fi) + uint8_t *buf, size_t len_fi, int extent) { uint32_t len; uint32_t block; uint8_t len_dr; /*< size of dir entry */ + int multi_extend = 0; uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id : (uint8_t*)node->name; @@ -674,12 +675,13 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id, len = node->info.dir->len; block = node->info.dir->block; } else if (node->type == ISO1999_FILE) { - len = iso_file_src_get_size(node->info.file); - block = node->info.file->block; + block = node->info.file->sections[extent].block; + len = node->info.file->sections[extent].size; + multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1; } else { - /* - * for nodes other than files and dirs, we set both - * len and block to 0 + /* + * for nodes other than files and dirs, we set both + * len and block to 0 */ len = 0; block = 0; @@ -695,20 +697,20 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id, iso_bb(rec->block, block, 4); iso_bb(rec->length, len, 4); iso_datetime_7(rec->recording_time, t->now, t->always_gmt); - rec->flags[0] = (node->type == ISO1999_DIR) ? 2 : 0; + rec->flags[0] = ((node->type == ISO1999_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0); iso_bb(rec->vol_seq_number, 1, 2); rec->len_fi[0] = len_fi; } /** - * Write the enhanced volume descriptor (ISO/IEC 9660:1999, 8.5) + * Write the enhanced volume descriptor (ISO/IEC 9660:1999, 8.5) */ static int iso1999_writer_write_vol_desc(IsoImageWriter *writer) { IsoImage *image; Ecma119Image *t; - + /* The enhanced volume descriptor is like the sup vol desc */ struct ecma119_sup_vol_desc vol; @@ -741,7 +743,7 @@ int iso1999_writer_write_vol_desc(IsoImageWriter *writer) vol.vol_desc_type[0] = 2; memcpy(vol.std_identifier, "CD001", 5); - + /* descriptor version is 2 (ISO/IEC 9660:1999, 8.5.2) */ vol.vol_desc_version[0] = 2; strncpy_pad((char*)vol.volume_id, vol_id, 32); @@ -754,12 +756,12 @@ int iso1999_writer_write_vol_desc(IsoImageWriter *writer) iso_lsb(vol.l_path_table_pos, t->iso1999_l_path_table_pos, 4); iso_msb(vol.m_path_table_pos, t->iso1999_m_path_table_pos, 4); - write_one_dir_record(t, t->iso1999_root, 0, vol.root_dir_record, 1); + write_one_dir_record(t, t->iso1999_root, 0, vol.root_dir_record, 1, 0); strncpy_pad((char*)vol.vol_set_id, volset_id, 128); strncpy_pad((char*)vol.publisher_id, pub_id, 128); strncpy_pad((char*)vol.data_prep_id, data_id, 128); - + strncpy_pad((char*)vol.system_id, system_id, 32); strncpy_pad((char*)vol.application_id, application_id, 128); @@ -801,30 +803,34 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir) memset(buffer, 0, BLOCK_SIZE); /* write the "." and ".." entries first */ - write_one_dir_record(t, dir, 0, buf, 1); + write_one_dir_record(t, dir, 0, buf, 1, 0); buf += 34; - write_one_dir_record(t, dir, 1, buf, 1); + write_one_dir_record(t, dir, 1, buf, 1, 0); buf += 34; for (i = 0; i < dir->info.dir->nchildren; i++) { + int section, nsections; Iso1999Node *child = dir->info.dir->children[i]; /* compute len of directory entry */ fi_len = strlen(child->name); len = fi_len + 33 + (fi_len % 2 ? 0 : 1); - if ( (buf + len - buffer) > BLOCK_SIZE) { - /* dir doesn't fit in current block */ - ret = iso_write(t, buffer, BLOCK_SIZE); - if (ret < 0) { - return ret; + nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1; + for (section = 0; section < nsections; ++section) { + if ( (buf + len - buffer) > BLOCK_SIZE) { + /* dir doesn't fit in current block */ + ret = iso_write(t, buffer, BLOCK_SIZE); + if (ret < 0) { + return ret; + } + memset(buffer, 0, BLOCK_SIZE); + buf = buffer; } - memset(buffer, 0, BLOCK_SIZE); - buf = buffer; + /* write the directory entry in any case */ + write_one_dir_record(t, child, -1, buf, fi_len, section); + buf += len; } - /* write the directory entry in any case */ - write_one_dir_record(t, child, -1, buf, fi_len); - buf += len; } /* write the last block */ @@ -1000,7 +1006,7 @@ int iso1999_writer_create(Ecma119Image *target) writer->data = NULL; writer->target = target; - iso_msg_debug(target->image->id, + iso_msg_debug(target->image->id, "Creating low level ISO 9660:1999 tree..."); ret = iso1999_tree_create(target); if (ret < 0) { diff --git a/libisofs/joliet.c b/libisofs/joliet.c index 0b86f03..87f1dc1 100644 --- a/libisofs/joliet.c +++ b/libisofs/joliet.c @@ -1,9 +1,9 @@ /* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Mario Danic - * - * This file is part of the libisofs project; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 as + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See COPYING file for details. */ @@ -47,7 +47,7 @@ int get_joliet_name(Ecma119Image *t, IsoNode *iso, uint16_t **name) *name = jname; return ISO_SUCCESS; } else { - /* + /* * only possible if mem error, as check for empty names is done * in public tree */ @@ -111,7 +111,7 @@ int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node) IsoFile *file = (IsoFile*) iso; size = iso_stream_get_size(file->stream); - if (size > (off_t)0xffffffff) { + if (size > (off_t)0xffffffff && t->iso_level != 3) { free(joliet); return iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0, "File \"%s\" can't be added to image because is " @@ -152,7 +152,7 @@ int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node) /** * Create the low level Joliet tree from the high level ISO tree. - * + * * @return * 1 success, 0 file ignored, < 0 error */ @@ -226,7 +226,7 @@ int create_tree(Ecma119Image *t, IsoNode *iso, JolietNode **tree, int pathlen) } else { /* log and ignore */ ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0, - "El-Torito catalog found on a image without El-Torito.", + "El-Torito catalog found on a image without El-Torito.", iso->name); } break; @@ -257,12 +257,12 @@ cmp_node(const void *f1, const void *f2) return ucscmp(f->name, g->name); } -static +static void sort_tree(JolietNode *root) { size_t i; - qsort(root->info.dir->children, root->info.dir->nchildren, + qsort(root->info.dir->children, root->info.dir->nchildren, sizeof(void*), cmp_node); for (i = 0; i < root->info.dir->nchildren; i++) { JolietNode *child = root->info.dir->children[i]; @@ -287,23 +287,23 @@ int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits, uint16_t *ucsnumber; char fmt[16]; char *nstr = alloca(digits + 1); - + sprintf(fmt, "%%0%dd", digits); sprintf(nstr, fmt, number); - + ret = str2ucs("ASCII", nstr, &ucsnumber); if (ret < 0) { return ret; } - + /* copy name */ pos = ucslen(src); ucsncpy(dest, src, pos); - + /* copy number */ ucsncpy(dest + pos, ucsnumber, digits); pos += digits; - + if (ext[0] != (uint16_t)0) { size_t extlen = ucslen(ext); dest[pos++] = (uint16_t)0x2E00; /* '.' in big endian UCS */ @@ -326,9 +326,9 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir) nchildren = dir->info.dir->nchildren; children = dir->info.dir->children; - + /* a hash table will temporary hold the names, for fast searching */ - ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash, + ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash, (compare_function_t)ucscmp, &table); if (ret < 0) { return ret; @@ -349,7 +349,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir) int digits = 1; /* characters to change per name */ /* first, find all child with same name */ - while (j + 1 < nchildren && + while (j + 1 < nchildren && !cmp_node_name(children + i, children + j + 1)) { ++j; } @@ -359,7 +359,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir) } /* - * A max of 7 characters is good enought, it allows handling up to + * A max of 7 characters is good enought, it allows handling up to * 9,999,999 files with same name. */ while (digits < 8) { @@ -374,7 +374,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir) dot = ucsrchr(full_name, '.'); if (dot != NULL && children[i]->type != JOLIET_DIR) { - /* + /* * File (not dir) with extension */ int extlen; @@ -387,17 +387,17 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir) if (max <= 0) { /* this can happen if extension is too long */ if (extlen + max > 3) { - /* + /* * reduce extension len, to give name an extra char - * note that max is negative or 0 + * note that max is negative or 0 */ extlen = extlen + max - 1; ext[extlen] = 0; max = 66 - extlen - 1 - digits; } else { - /* + /* * error, we don't support extensions < 3 - * This can't happen with current limit of digits. + * This can't happen with current limit of digits. */ ret = ISO_ERROR; goto mangle_cleanup; @@ -455,7 +455,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir) children[k]->name = new; iso_htable_add(table, new, new); - /* + /* * if we change a name we need to sort again children * at the end */ @@ -486,7 +486,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir) } ret = ISO_SUCCESS; - + mangle_cleanup : ; iso_htable_destroy(table, NULL); return ret; @@ -521,7 +521,7 @@ int joliet_tree_create(Ecma119Image *t) { int ret; JolietNode *root; - + if (t == NULL) { return ISO_NULL_POINTER; } @@ -534,7 +534,7 @@ int joliet_tree_create(Ecma119Image *t) } return ret; } - + /* the Joliet tree is stored in Ecma119Image target */ t->joliet_root = root; @@ -590,10 +590,10 @@ size_t calc_dir_size(Ecma119Image *t, JolietNode *dir) len += dirent_len; } } - + /* - * The size of a dir is always a multiple of block size, as we must add - * the size of the unused space after the last directory record + * The size of a dir is always a multiple of block size, as we must add + * the size of the unused space after the last directory record * (ECMA-119, 6.8.1.3) */ len = ROUND_UP(len, BLOCK_SIZE); @@ -677,7 +677,7 @@ int joliet_writer_compute_data_blocks(IsoImageWriter *writer) /** * Write a single directory record for Joliet. It is like (ECMA-119, 9.1), * but file identifier is stored in UCS. - * + * * @param file_id * if >= 0, we use it instead of the filename (for "." and ".." entries). * @param len_fi @@ -686,11 +686,12 @@ int joliet_writer_compute_data_blocks(IsoImageWriter *writer) */ static void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id, - uint8_t *buf, size_t len_fi) + uint8_t *buf, size_t len_fi, int extent) { uint32_t len; uint32_t block; uint8_t len_dr; /*< size of dir entry */ + int multi_extend = 0; uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id : (uint8_t*)node->name; @@ -713,12 +714,13 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id, len = node->info.dir->len; block = node->info.dir->block; } else if (node->type == JOLIET_FILE) { - len = iso_file_src_get_size(node->info.file); - block = node->info.file->block; + block = node->info.file->sections[extent].block; + len = node->info.file->sections[extent].size; + multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1; } else { - /* - * for nodes other than files and dirs, we set both - * len and block to 0 + /* + * for nodes other than files and dirs, we set both + * len and block to 0 */ len = 0; block = 0; @@ -734,7 +736,7 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id, iso_bb(rec->block, block, 4); iso_bb(rec->length, len, 4); iso_datetime_7(rec->recording_time, t->now, t->always_gmt); - rec->flags[0] = (node->type == JOLIET_DIR) ? 2 : 0; + rec->flags[0] = ((node->type == JOLIET_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0); iso_bb(rec->vol_seq_number, 1, 2); rec->len_fi[0] = len_fi; } @@ -748,19 +750,19 @@ void ucsncpy_pad(uint16_t *dest, const uint16_t *src, size_t max) { char *cdest, *csrc; size_t len, i; - + cdest = (char*)dest; csrc = (char*)src; - + if (src != NULL) { len = MIN(ucslen(src) * 2, max); } else { len = 0; } - + for (i = 0; i < len; ++i) cdest[i] = csrc[i]; - + for (i = len; i < max; i += 2) { cdest[i] = '\0'; cdest[i + 1] = ' '; @@ -805,7 +807,7 @@ int joliet_writer_write_vol_desc(IsoImageWriter *writer) memcpy(vol.std_identifier, "CD001", 5); vol.vol_desc_version[0] = 1; ucsncpy_pad((uint16_t*)vol.volume_id, vol_id, 32); - + /* make use of UCS-2 Level 3 */ memcpy(vol.esc_sequences, "%/E", 3); @@ -817,12 +819,12 @@ int joliet_writer_write_vol_desc(IsoImageWriter *writer) iso_lsb(vol.l_path_table_pos, t->joliet_l_path_table_pos, 4); iso_msb(vol.m_path_table_pos, t->joliet_m_path_table_pos, 4); - write_one_dir_record(t, t->joliet_root, 0, vol.root_dir_record, 1); + write_one_dir_record(t, t->joliet_root, 0, vol.root_dir_record, 1, 0); ucsncpy_pad((uint16_t*)vol.vol_set_id, volset_id, 128); ucsncpy_pad((uint16_t*)vol.publisher_id, pub_id, 128); ucsncpy_pad((uint16_t*)vol.data_prep_id, data_id, 128); - + ucsncpy_pad((uint16_t*)vol.system_id, system_id, 32); ucsncpy_pad((uint16_t*)vol.application_id, application_id, 128); @@ -864,12 +866,13 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir) memset(buffer, 0, BLOCK_SIZE); /* write the "." and ".." entries first */ - write_one_dir_record(t, dir, 0, buf, 1); + write_one_dir_record(t, dir, 0, buf, 1, 0); buf += 34; - write_one_dir_record(t, dir, 1, buf, 1); + write_one_dir_record(t, dir, 1, buf, 1, 0); buf += 34; for (i = 0; i < dir->info.dir->nchildren; i++) { + int section, nsections; JolietNode *child = dir->info.dir->children[i]; /* compute len of directory entry */ @@ -879,18 +882,23 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir) len += 4; } - if ( (buf + len - buffer) > BLOCK_SIZE) { - /* dir doesn't fit in current block */ - ret = iso_write(t, buffer, BLOCK_SIZE); - if (ret < 0) { - return ret; + nsections = (child->type == JOLIET_FILE) ? child->info.file->nsections : 1; + + for (section = 0; section < nsections; ++section) { + + if ( (buf + len - buffer) > BLOCK_SIZE) { + /* dir doesn't fit in current block */ + ret = iso_write(t, buffer, BLOCK_SIZE); + if (ret < 0) { + return ret; + } + memset(buffer, 0, BLOCK_SIZE); + buf = buffer; } - memset(buffer, 0, BLOCK_SIZE); - buf = buffer; + /* write the directory entry in any case */ + write_one_dir_record(t, child, -1, buf, fi_len, section); + buf += len; } - /* write the directory entry in any case */ - write_one_dir_record(t, child, -1, buf, fi_len); - buf += len; } /* write the last block */ diff --git a/libisofs/node.c b/libisofs/node.c index 9c8dee9..dd8ee27 100644 --- a/libisofs/node.c +++ b/libisofs/node.c @@ -1,8 +1,8 @@ /* * Copyright (c) 2007 Vreixo Formoso - * - * This file is part of the libisofs project; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 as + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See COPYING file for details. */ @@ -16,12 +16,12 @@ #include struct dir_iter_data -{ +{ /* points to the last visited child, to NULL before start */ IsoNode *pos; - + /* Some control flags. - * bit 0 -> 1 if next called, 0 reseted at start or on deletion + * bit 0 -> 1 if next called, 0 reseted at start or on deletion */ int flag; }; @@ -74,7 +74,7 @@ void iso_node_unref(IsoNode *node) IsoExtendedInfo *info = node->xinfo; while (info != NULL) { IsoExtendedInfo *tmp = info->next; - + /* free extended info */ info->process(info->data, 1); free(info); @@ -87,17 +87,17 @@ void iso_node_unref(IsoNode *node) } /** - * Add extended information to the given node. Extended info allows + * Add extended information to the given node. Extended info allows * applications (and libisofs itself) to add more information to an IsoNode. * You can use this facilities to associate new information with a given * node. - * + * * Each node keeps a list of added extended info, meaning you can add several * extended info data to each node. Each extended info you add is identified * by the proc parameter, a pointer to a function that knows how to manage * the external info data. Thus, in order to add several types of extended * info, you need to define a "proc" function for each type. - * + * * @param node * The node where to add the extended info * @param proc @@ -125,7 +125,7 @@ int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data) } pos = pos->next; } - + info = malloc(sizeof(IsoExtendedInfo)); if (info == NULL) { return ISO_OUT_OF_MEM; @@ -140,8 +140,8 @@ int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data) /** * Remove the given extended info (defined by the proc function) from the * given node. - * - * @return + * + * @return * 1 on success, 0 if node does not have extended info of the requested * type, < 0 on error */ @@ -152,14 +152,14 @@ int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc) if (node == NULL || proc == NULL) { return ISO_NULL_POINTER; } - + prev = NULL; pos = node->xinfo; while (pos != NULL) { if (pos->process == proc) { /* this is the extended info we want to remove */ pos->process(pos->data, 1); - + if (prev != NULL) { prev->next = pos->next; } else { @@ -172,17 +172,17 @@ int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc) pos = pos->next; } /* requested xinfo not found */ - return 0; + return 0; } /** * Get the given extended info (defined by the proc function) from the * given node. - * + * * @param data * Will be filled with the extended info corresponding to the given proc * function - * @return + * @return * 1 on success, 0 if node does not have extended info of the requested * type, < 0 on error */ @@ -193,7 +193,7 @@ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data) if (node == NULL || proc == NULL || data == NULL) { return ISO_NULL_POINTER; } - + pos = node->xinfo; while (pos != NULL) { if (pos->process == proc) { @@ -204,7 +204,7 @@ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data) pos = pos->next; } /* requested xinfo not found */ - return 0; + return 0; } /** @@ -217,7 +217,7 @@ enum IsoNodeType iso_node_get_type(IsoNode *node) /** * Set the name of a node. - * + * * @param name The name in UTF-8 encoding */ int iso_node_set_name(IsoNode *node, const char *name) @@ -228,7 +228,7 @@ int iso_node_set_name(IsoNode *node, const char *name) /* you can't change name of the root node */ return ISO_WRONG_ARG_VALUE; } - + /* check if the name is valid */ if (!iso_node_is_valid_name(name)) { return ISO_WRONG_ARG_VALUE; @@ -272,10 +272,10 @@ const char *iso_node_get_name(const IsoNode *node) } /** - * Set the permissions for the node. This attribute is only useful when + * Set the permissions for the node. This attribute is only useful when * Rock Ridge extensions are enabled. - * - * @param mode + * + * @param mode * bitmask with the permissions of the node, as specified in 'man 2 stat'. * The file type bitfields will be ignored, only file permissions will be * modified. @@ -285,15 +285,15 @@ void iso_node_set_permissions(IsoNode *node, mode_t mode) node->mode = (node->mode & S_IFMT) | (mode & ~S_IFMT); } -/** - * Get the permissions for the node +/** + * Get the permissions for the node */ mode_t iso_node_get_permissions(const IsoNode *node) { return node->mode & ~S_IFMT; } -/** +/** * Get the mode of the node, both permissions and file type, as specified in * 'man 2 stat'. */ @@ -303,7 +303,7 @@ mode_t iso_node_get_mode(const IsoNode *node) } /** - * Set the user id for the node. This attribute is only useful when + * Set the user id for the node. This attribute is only useful when * Rock Ridge extensions are enabled. */ void iso_node_set_uid(IsoNode *node, uid_t uid) @@ -320,7 +320,7 @@ uid_t iso_node_get_uid(const IsoNode *node) } /** - * Set the group id for the node. This attribute is only useful when + * Set the group id for the node. This attribute is only useful when * Rock Ridge extensions are enabled. */ void iso_node_set_gid(IsoNode *node, gid_t gid) @@ -336,7 +336,7 @@ gid_t iso_node_get_gid(const IsoNode *node) return node->gid; } -/** +/** * Set the time of last modification of the file */ void iso_node_set_mtime(IsoNode *node, time_t time) @@ -344,7 +344,7 @@ void iso_node_set_mtime(IsoNode *node, time_t time) node->mtime = time; } -/** +/** * Get the time of last modification of the file */ time_t iso_node_get_mtime(const IsoNode *node) @@ -352,7 +352,7 @@ time_t iso_node_get_mtime(const IsoNode *node) return node->mtime; } -/** +/** * Set the time of last access to the file */ void iso_node_set_atime(IsoNode *node, time_t time) @@ -360,24 +360,24 @@ void iso_node_set_atime(IsoNode *node, time_t time) node->atime = time; } -/** - * Get the time of last access to the file +/** + * Get the time of last access to the file */ time_t iso_node_get_atime(const IsoNode *node) { return node->atime; } -/** - * Set the time of last status change of the file +/** + * Set the time of last status change of the file */ void iso_node_set_ctime(IsoNode *node, time_t time) { node->ctime = time; } -/** - * Get the time of last status change of the file +/** + * Get the time of last status change of the file */ time_t iso_node_get_ctime(const IsoNode *node) { @@ -397,21 +397,21 @@ void iso_node_set_hidden(IsoNode *node, int hide_attrs) * the node, so you don't need to free it, it will be automatically freed * when the dir is deleted. Of course, if you want to keep using the node * after the dir life, you need to iso_node_ref() it. - * - * @param dir + * + * @param dir * the dir where to add the node - * @param child + * @param child * the node to add. You must ensure that the node hasn't previously added * to other dir, and that the node name is unique inside the child. * Otherwise this function will return a failure, and the child won't be * inserted. * @param replace * if the dir already contains a node with the same name, whether to - * replace or not the old node with this. + * replace or not the old node with this. * @return * number of nodes in dir if succes, < 0 otherwise */ -int iso_dir_add_node(IsoDir *dir, IsoNode *child, +int iso_dir_add_node(IsoDir *dir, IsoNode *child, enum iso_replace_mode replace) { IsoNode **pos; @@ -423,7 +423,7 @@ int iso_dir_add_node(IsoDir *dir, IsoNode *child, return ISO_WRONG_ARG_VALUE; } - /* + /* * check if child is already added to another dir, or if child * is the root node, where parent == itself */ @@ -437,17 +437,17 @@ int iso_dir_add_node(IsoDir *dir, IsoNode *child, /** * Locate a node inside a given dir. - * + * * @param name * The name of the node * @param node - * Location for a pointer to the node, it will filled with NULL if the dir + * Location for a pointer to the node, it will filled with NULL if the dir * doesn't have a child with the given name. * The node will be owned by the dir and shouldn't be unref(). Just call * iso_node_ref() to get your own reference to the node. * Note that you can pass NULL is the only thing you want to do is check * if a node with such name already exists on dir. - * @return + * @return * 1 node found, 0 child has no such node, < 0 error * Possible errors: * ISO_NULL_POINTER, if dir or name are NULL @@ -476,7 +476,7 @@ int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node) /** * Get the number of children of a directory. - * + * * @return * >= 0 number of items, < 0 error * Possible errors: @@ -497,12 +497,12 @@ int iter_next(IsoDirIter *iter, IsoNode **node) if (iter == NULL || node == NULL) { return ISO_NULL_POINTER; } - + data = iter->data; - + /* clear next flag */ data->flag &= ~0x01; - + if (data->pos == NULL) { /* we are at the beginning */ data->pos = iter->dir->children; @@ -529,12 +529,12 @@ int iter_next(IsoDirIter *iter, IsoNode **node) data->pos = data->pos->next; } } - + /* ok, take a ref to the current position, to prevent internal errors * if deleted somewhere */ iso_node_ref(data->pos); data->flag |= 0x01; /* set next flag */ - + /* return pointed node */ *node = data->pos; return ISO_SUCCESS; @@ -542,7 +542,7 @@ int iter_next(IsoDirIter *iter, IsoNode **node) /** * Check if there're more children. - * + * * @return * 1 dir has more elements, 0 no, < 0 error * Possible errors: @@ -589,8 +589,8 @@ static IsoNode** iso_dir_find_node(IsoDir *dir, IsoNode *node) * The child is not freed, so you will become the owner of the node. Later * you can add the node to another dir (calling iso_dir_add_node), or free * it if you don't need it (with iso_node_unref). - * - * @return + * + * @return * 1 on success, < 0 error */ int iso_node_take(IsoNode *node) @@ -610,10 +610,10 @@ int iso_node_take(IsoNode *node) /* should never occur */ return ISO_ASSERT_FAILURE; } - + /* notify iterators just before remove */ - iso_notify_dir_iters(node, 0); - + iso_notify_dir_iters(node, 0); + *pos = node->next; node->parent = NULL; node->next = NULL; @@ -626,8 +626,8 @@ int iso_node_take(IsoNode *node) * If you want to keep the child alive, you need to iso_node_ref() it * before this call, but in that case iso_node_take() is a better * alternative. - * - * @return + * + * @return * 1 on success, < 0 error */ int iso_node_remove(IsoNode *node) @@ -644,10 +644,10 @@ int iso_node_remove(IsoNode *node) * Get the parent of the given iso tree node. No extra ref is added to the * returned directory, you must take your ref. with iso_node_ref() if you * need it. - * + * * If node is the root node, the same node will be returned as its parent. - * - * This returns NULL if the node doesn't pertain to any tree + * + * This returns NULL if the node doesn't pertain to any tree * (it was removed/take). */ IsoDir *iso_node_get_parent(IsoNode *node) @@ -663,20 +663,20 @@ int iter_take(IsoDirIter *iter) if (iter == NULL) { return ISO_NULL_POINTER; } - + data = iter->data; - + if (!(data->flag & 0x01)) { return ISO_ERROR; /* next not called or end of dir */ } - + if (data->pos == NULL) { return ISO_ASSERT_FAILURE; } - + /* clear next flag */ data->flag &= ~0x01; - + return iso_node_take(data->pos); } @@ -686,13 +686,13 @@ int iter_remove(IsoDirIter *iter) int ret; IsoNode *pos; struct dir_iter_data *data; - + if (iter == NULL) { return ISO_NULL_POINTER; } data = iter->data; pos = data->pos; - + ret = iter_take(iter); if (ret == ISO_SUCCESS) { /* remove node */ @@ -706,8 +706,8 @@ void iter_notify_child_taken(IsoDirIter *iter, IsoNode *node) IsoNode *pos, *pre; struct dir_iter_data *data; data = iter->data; - - if (data->pos == node) { + + if (data->pos == node) { pos = iter->dir->children; pre = NULL; while (pos != NULL && pos != data->pos) { @@ -717,10 +717,10 @@ void iter_notify_child_taken(IsoDirIter *iter, IsoNode *node) if (pos == NULL || pos != data->pos) { return; } - + /* dispose iterator reference */ iso_node_unref(data->pos); - + if (pre == NULL) { /* node is a first position */ iter->dir->children = pos->next; @@ -766,7 +766,7 @@ int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter) data->pos = NULL; data->flag = 0x00; it->data = data; - + if (iso_dir_iter_register(it) < 0) { free(it); return ISO_OUT_OF_MEM; @@ -808,7 +808,7 @@ int iso_dir_iter_take(IsoDirIter *iter) if (iter == NULL) { return ISO_NULL_POINTER; } - return iter->class->take(iter); + return iter->class->take(iter); } int iso_dir_iter_remove(IsoDirIter *iter) @@ -816,7 +816,7 @@ int iso_dir_iter_remove(IsoDirIter *iter) if (iter == NULL) { return ISO_NULL_POINTER; } - return iter->class->remove(iter); + return iter->class->remove(iter); } /** @@ -851,13 +851,13 @@ int iso_symlink_set_dest(IsoSymlink *link, const char *dest) /** * Sets the order in which a node will be written on image. High weihted files * will be written first, so in a disc them will be written near the center. - * - * @param node - * The node which weight will be changed. If it's a dir, this function - * will change the weight of all its children. For nodes other that dirs + * + * @param node + * The node which weight will be changed. If it's a dir, this function + * will change the weight of all its children. For nodes other that dirs * or regular files, this function has no effect. - * @param w - * The weight as a integer number, the greater this value is, the + * @param w + * The weight as a integer number, the greater this value is, the * closer from the begining of image the file will be written. */ void iso_node_set_sort_weight(IsoNode *node, int w) @@ -881,8 +881,8 @@ int iso_file_get_sort_weight(IsoFile *file) return file->sort_weight; } -/** - * Get the size of the file, in bytes +/** + * Get the size of the file, in bytes */ off_t iso_file_get_size(IsoFile *file) { @@ -891,9 +891,9 @@ off_t iso_file_get_size(IsoFile *file) /** * Get the IsoStream that represents the contents of the given IsoFile. - * + * * If you open() the stream, it should be close() before image generation. - * + * * @return * The IsoStream. No extra ref is added, so the IsoStream belong to the * IsoFile, and it may be freed together with it. Add your own ref with @@ -908,7 +908,7 @@ IsoStream *iso_file_get_stream(IsoFile *file) /** * Get the block lba of a file node, if it was imported from an old image. - * + * * @param file * The file * @param lba @@ -917,31 +917,39 @@ IsoStream *iso_file_get_stream(IsoFile *file) * Reserved for future usage, submit 0 * @return * 1 if lba is valid (file comes from old image), 0 if file was newly - * added, i.e. it does not come from an old image, < 0 error + * added, i.e. it does not come from an old image, < 0 error * * @since 0.6.4 */ int iso_file_get_old_image_lba(IsoFile *file, uint32_t *lba, int flag) { + int ret; + int section_count; + struct iso_file_section *sections; if (file == NULL || lba == NULL) { return ISO_NULL_POINTER; } - if (flag != 0) { + ret = iso_file_get_old_image_sections(file, §ion_count, §ions, flag); + if (ret <= 0) { + return ret; + } + if (section_count != 1) { + free(sections); return ISO_WRONG_ARG_VALUE; } - if (file->msblock != 0) { - *lba = file->msblock; - return 1; - } + *lba = sections[0].block; + free(sections); return 0; } + + /* * Like iso_file_get_old_image_lba(), but take an IsoNode. - * + * * @return * 1 if lba is valid (file comes from old image), 0 if file was newly - * added, i.e. it does not come from an old image, 2 node type has no + * added, i.e. it does not come from an old image, 2 node type has no * LBA (no regular file), < 0 error * * @since 0.6.4 @@ -960,7 +968,7 @@ int iso_node_get_old_image_lba(IsoNode *node, uint32_t *lba, int flag) /** * Check if a given name is valid for an iso node. - * + * * @return * 1 if yes, 0 if not */ @@ -990,7 +998,7 @@ int iso_node_is_valid_name(const char *name) /** * Check if a given path is valid for the destination of a link. - * + * * @return * 1 if yes, 0 if not */ @@ -1008,18 +1016,18 @@ int iso_node_is_valid_link_dest(const char *dest) if (dest[0] == '\0' || strlen(dest) > PATH_MAX) { return 0; } - + /* check that all components are valid */ if (!strcmp(dest, "/")) { /* "/" is a valid component */ return 1; } - + ptr = strdup(dest); if (ptr == NULL) { return 0; } - + ret = 1; component = strtok_r(ptr, "/", &brk_info); while (component) { @@ -1041,13 +1049,13 @@ void iso_dir_find(IsoDir *dir, const char *name, IsoNode ***pos) *pos = &(dir->children); while (**pos != NULL && strcmp((**pos)->name, name) < 0) { *pos = &((**pos)->next); - } + } } int iso_dir_exists(IsoDir *dir, const char *name, IsoNode ***pos) { IsoNode **node; - + iso_dir_find(dir, name, &node); if (pos) { *pos = node; @@ -1055,7 +1063,7 @@ int iso_dir_exists(IsoDir *dir, const char *name, IsoNode ***pos) return (*node != NULL && !strcmp((*node)->name, name)) ? 1 : 0; } -int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos, +int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos, enum iso_replace_mode replace) { if (*pos != NULL && !strcmp((*pos)->name, node->name)) { @@ -1087,7 +1095,7 @@ int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos, /* CAN'T HAPPEN */ return ISO_ASSERT_FAILURE; } - + /* if we are reach here we have to replace */ node->next = (*pos)->next; (*pos)->parent = NULL; @@ -1117,7 +1125,7 @@ struct iter_reg_node *iter_reg = NULL; /** * Add a new iterator to the registry. The iterator register keeps track of - * all iterators being used, and are notified when directory structure + * all iterators being used, and are notified when directory structure * changes. */ int iso_dir_iter_register(IsoDirIter *iter) @@ -1150,7 +1158,7 @@ void iso_dir_iter_unregister(IsoDirIter *iter) } } -void iso_notify_dir_iters(IsoNode *node, int flag) +void iso_notify_dir_iters(IsoNode *node, int flag) { struct iter_reg_node *pos = iter_reg; while (pos != NULL) { @@ -1184,11 +1192,11 @@ int iso_node_new_root(IsoDir **root) int iso_node_new_dir(char *name, IsoDir **dir) { IsoDir *new; - + if (dir == NULL || name == NULL) { return ISO_NULL_POINTER; } - + /* check if the name is valid */ if (!iso_node_is_valid_name(name)) { return ISO_WRONG_ARG_VALUE; @@ -1209,11 +1217,11 @@ int iso_node_new_dir(char *name, IsoDir **dir) int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file) { IsoFile *new; - + if (file == NULL || name == NULL || stream == NULL) { return ISO_NULL_POINTER; } - + /* check if the name is valid */ if (!iso_node_is_valid_name(name)) { return ISO_WRONG_ARG_VALUE; @@ -1236,16 +1244,16 @@ int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file) int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link) { IsoSymlink *new; - + if (link == NULL || name == NULL || dest == NULL) { return ISO_NULL_POINTER; } - + /* check if the name is valid */ if (!iso_node_is_valid_name(name)) { return ISO_WRONG_ARG_VALUE; } - + /* check if destination is valid */ if (!iso_node_is_valid_link_dest(dest)) { /* guard against null or empty dest */ @@ -1265,18 +1273,18 @@ int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link) return ISO_SUCCESS; } -int iso_node_new_special(char *name, mode_t mode, dev_t dev, +int iso_node_new_special(char *name, mode_t mode, dev_t dev, IsoSpecial **special) { IsoSpecial *new; - + if (special == NULL || name == NULL) { return ISO_NULL_POINTER; } if (S_ISLNK(mode) || S_ISREG(mode) || S_ISDIR(mode)) { return ISO_WRONG_ARG_VALUE; } - + /* check if the name is valid */ if (!iso_node_is_valid_name(name)) { return ISO_WRONG_ARG_VALUE; diff --git a/libisofs/node.h b/libisofs/node.h index 993051c..7d5471b 100644 --- a/libisofs/node.h +++ b/libisofs/node.h @@ -1,8 +1,8 @@ /* * Copyright (c) 2007 Vreixo Formoso - * - * This file is part of the libisofs project; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 as + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See COPYING file for details. */ #ifndef LIBISO_NODE_H_ @@ -22,12 +22,12 @@ /** * The extended information is a way to attach additional information to each - * IsoNode. External applications may want to use this extension system to + * IsoNode. External applications may want to use this extension system to * store application speficic information related to each node. On the other * side, libisofs may make use of this struct to attach information to nodes in * some particular, uncommon, cases, without incrementing the size of the * IsoNode struct. - * + * * It is implemented like a chained list. */ typedef struct iso_extended_info IsoExtendedInfo; @@ -37,23 +37,23 @@ struct iso_extended_info { * Next struct in the chain. NULL if it is the last item */ IsoExtendedInfo *next; - + /** * Function to handle this particular extended information. The function * pointer acts as an identifier for the type of the information. Structs * with same information type must use the same function. - * + * * @param data * Attached data * @param flag - * What to do with the data. At this time the following values are + * What to do with the data. At this time the following values are * defined: * -> 1 the data must be freed * @return * 1 */ iso_node_xinfo_func process; - + /** * Pointer to information specific data. */ @@ -61,15 +61,15 @@ struct iso_extended_info { }; /** - * + * */ struct Iso_Node { /* * Initilized to 1, originally owned by user, until added to another node. - * Then it is owned by the parent node, so the user must take his own ref + * Then it is owned by the parent node, so the user must take his own ref * if needed. With the exception of the creation functions, none of the - * other libisofs functions that return an IsoNode increment its + * other libisofs functions that return an IsoNode increment its * refcount. This is responsablity of the client, if (s)he needs it. */ int refcount; @@ -115,14 +115,11 @@ struct Iso_File { IsoNode node; - /** - * Location of a file extent in a ms disc, 0 for newly added file - */ - uint32_t msblock; + unsigned int from_old_session : 1; - /** + /** * It sorts the order in which the file data is written to the CD image. - * Higher weighting files are written at the beginning of image + * Higher weighting files are written at the beginning of image */ int sort_weight; IsoStream *stream; @@ -143,18 +140,18 @@ struct Iso_Special struct iso_dir_iter_iface { - + int (*next)(IsoDirIter *iter, IsoNode **node); int (*has_next)(IsoDirIter *iter); void (*free)(IsoDirIter *iter); - + int (*take)(IsoDirIter *iter); int (*remove)(IsoDirIter *iter); - - /** + + /** * This is called just before remove a node from a directory. The iterator * may want to update its internal state according to this. */ @@ -167,37 +164,37 @@ struct iso_dir_iter_iface struct Iso_Dir_Iter { struct iso_dir_iter_iface *class; - + /* the directory this iterator iterates over */ IsoDir *dir; - + void *data; }; int iso_node_new_root(IsoDir **root); /** - * Create a new IsoDir. Attributes, uid/gid, timestamps, etc are set to + * Create a new IsoDir. Attributes, uid/gid, timestamps, etc are set to * default (0) values. You must set them. - * + * * @param name - * Name for the node. It is not strdup() so you shouldn't use this - * reference when this function returns successfully. NULL is not + * Name for the node. It is not strdup() so you shouldn't use this + * reference when this function returns successfully. NULL is not * allowed. * @param dir - * + * * @return * 1 on success, < 0 on error. */ int iso_node_new_dir(char *name, IsoDir **dir); /** - * Create a new file node. Attributes, uid/gid, timestamps, etc are set to + * Create a new file node. Attributes, uid/gid, timestamps, etc are set to * default (0) values. You must set them. - * + * * @param name - * Name for the node. It is not strdup() so you shouldn't use this - * reference when this function returns successfully. NULL is not + * Name for the node. It is not strdup() so you shouldn't use this + * reference when this function returns successfully. NULL is not * allowed. * @param stream * Source for file contents. The reference is taken by the node, @@ -210,14 +207,14 @@ int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file); /** * Creates a new IsoSymlink node. Attributes, uid/gid, timestamps, etc are set * to default (0) values. You must set them. - * + * * @param name - * name for the new symlink. It is not strdup() so you shouldn't use this - * reference when this function returns successfully. NULL is not + * name for the new symlink. It is not strdup() so you shouldn't use this + * reference when this function returns successfully. NULL is not * allowed. * @param dest - * destination of the link. It is not strdup() so you shouldn't use this - * reference when this function returns successfully. NULL is not + * destination of the link. It is not strdup() so you shouldn't use this + * reference when this function returns successfully. NULL is not * allowed. * @param link * place where to store a pointer to the newly created link. @@ -231,22 +228,22 @@ int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link); * an special file is a block device, a character device, a FIFO (named pipe) * or a socket. You can choose the specific kind of file you want to add * by setting mode propertly (see man 2 stat). - * - * Note that special files are only written to image when Rock Ridge + * + * Note that special files are only written to image when Rock Ridge * extensions are enabled. Moreover, a special file is just a directory entry * in the image tree, no data is written beyond that. - * - * Owner and hidden atts are taken from parent. You can modify any of them + * + * Owner and hidden atts are taken from parent. You can modify any of them * later. - * + * * @param name - * name for the new special file. It is not strdup() so you shouldn't use - * this reference when this function returns successfully. NULL is not + * name for the new special file. It is not strdup() so you shouldn't use + * this reference when this function returns successfully. NULL is not * allowed. * @param mode * file type and permissions for the new node. Note that you can't * specify any kind of file here, only special types are allowed. i.e, - * S_IFSOCK, S_IFBLK, S_IFCHR and S_IFIFO are valid types; S_IFLNK, + * S_IFSOCK, S_IFBLK, S_IFCHR and S_IFIFO are valid types; S_IFLNK, * S_IFREG and S_IFDIR aren't. * @param dev * device ID, equivalent to the st_rdev field in man 2 stat. @@ -255,12 +252,12 @@ int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link); * @return * 1 on success, < 0 otherwise */ -int iso_node_new_special(char *name, mode_t mode, dev_t dev, +int iso_node_new_special(char *name, mode_t mode, dev_t dev, IsoSpecial **special); /** * Check if a given name is valid for an iso node. - * + * * @return * 1 if yes, 0 if not */ @@ -268,7 +265,7 @@ int iso_node_is_valid_name(const char *name); /** * Check if a given path is valid for the destination of a link. - * + * * @return * 1 if yes, 0 if not */ @@ -276,7 +273,7 @@ int iso_node_is_valid_link_dest(const char *dest); /** * Find the position where to insert a node - * + * * @param dir * A valid dir. It can't be NULL * @param name @@ -288,7 +285,7 @@ void iso_dir_find(IsoDir *dir, const char *name, IsoNode ***pos); /** * Check if a node with the given name exists in a dir. - * + * * @param dir * A valid dir. It can't be NULL * @param name @@ -303,26 +300,26 @@ int iso_dir_exists(IsoDir *dir, const char *name, IsoNode ***pos); /** * Inserts a given node in a dir, at the specified position. - * + * * @param dir * Dir where to insert. It can't be NULL * @param node * The node to insert. It can't be NULL * @param pos * Position where the node will be inserted. It is a pointer previously - * obtained with a call to iso_dir_exists() or iso_dir_find(). + * obtained with a call to iso_dir_exists() or iso_dir_find(). * It can't be NULL. - * @param replace + * @param replace * Whether to replace an old node with the same name with the new node. * @return - * If success, number of children in dir. < 0 on error + * If success, number of children in dir. < 0 on error */ -int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos, +int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos, enum iso_replace_mode replace); /** * Add a new iterator to the registry. The iterator register keeps track of - * all iterators being used, and are notified when directory structure + * all iterators being used, and are notified when directory structure * changes. */ int iso_dir_iter_register(IsoDirIter *iter);