Add support for multisession on Level 3 images.
This commit is contained in:
parent
3a503a3e85
commit
2e99e1aac9
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
|
246
libisofs/node.c
246
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 <limits.h>
|
||||
|
||||
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;
|
||||
|
111
libisofs/node.h
111
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);
|
||||
|
Loading…
Reference in New Issue
Block a user