Merge level3 branch, adding support for ISO-9660 Level 3.

This commit is contained in:
Vreixo Formoso
2008-08-20 02:14:47 +02:00
18 changed files with 1424 additions and 983 deletions

View File

@@ -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;
}

View File

@@ -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.
*/
@@ -90,10 +90,10 @@ size_t calc_dirent_len(Ecma119Image *t, Ecma119Node *n)
/**
* Computes the total size of all directory entries of a single dir,
* acording to ECMA-119 6.8.1.1
*
*
* This also take into account the size needed for RR entries and
* SUSP continuation areas (SUSP, 5.1).
*
*
* @param ce
* Will be filled with the size needed for Continuation Areas
* @return
@@ -117,24 +117,29 @@ size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
for (i = 0; i < dir->info.dir->nchildren; ++i) {
size_t remaining;
int section, nsections;
Ecma119Node *child = dir->info.dir->children[i];
size_t dirent_len = calc_dirent_len(t, child);
if (t->rockridge) {
dirent_len += rrip_calc_len(t, child, 0, 255 - dirent_len, &ce_len);
*ce += ce_len;
}
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
if (dirent_len > remaining) {
/* child directory entry doesn't fit on block */
len += remaining + dirent_len;
} else {
len += dirent_len;
nsections = (child->type == ECMA119_FILE) ? child->info.file->nsections : 1;
for (section = 0; section < nsections; ++section) {
size_t dirent_len = calc_dirent_len(t, child);
if (t->rockridge) {
dirent_len += rrip_calc_len(t, child, 0, 255 - dirent_len, &ce_len);
*ce += ce_len;
}
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
if (dirent_len > remaining) {
/* child directory entry doesn't fit on block */
len += remaining + dirent_len;
} else {
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);
@@ -222,24 +227,26 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
/**
* Write a single directory record (ECMA-119, 9.1)
*
*
* @param file_id
* if >= 0, we use it instead of the filename (for "." and ".." entries).
* @param len_fi
* Computed length of the file identifier. Total size of the directory
* entry will be len + 33 + padding if needed (ECMA-119, 9.1.12)
* @param info
* SUSP entries for the given directory record. It will be NULL for the
* root directory record in the PVD (ECMA-119, 8.4.18) (in order to
* SUSP entries for the given directory record. It will be NULL for the
* root directory record in the PVD (ECMA-119, 8.4.18) (in order to
* distinguish it from the "." entry in the root directory)
*/
static
void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
uint8_t *buf, size_t len_fi, struct susp_info *info)
uint8_t *buf, size_t len_fi, struct susp_info *info,
int extent)
{
uint32_t len;
uint32_t block;
uint8_t len_dr; /*< size of dir entry without SUSP fields */
int multi_extend = 0;
uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
: (uint8_t*)node->iso_name;
@@ -260,12 +267,13 @@ 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) {
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;
@@ -281,11 +289,13 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *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 == ECMA119_DIR) ? 2 : 0;
rec->flags[0] = ((node->type == ECMA119_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
iso_bb(rec->vol_seq_number, 1, 2);
rec->len_fi[0] = len_fi;
/* and finally write the SUSP fields */
/*
* and finally write the SUSP fields.
*/
if (info != NULL) {
rrip_write_susp_fields(t, info, buf + len_dr);
}
@@ -365,7 +375,7 @@ int ecma119_writer_write_vol_desc(IsoImageWriter *writer)
iso_lsb(vol.l_path_table_pos, t->l_path_table_pos, 4);
iso_msb(vol.m_path_table_pos, t->m_path_table_pos, 4);
write_one_dir_record(t, t->root, 0, vol.root_dir_record, 1, NULL);
write_one_dir_record(t, t->root, 0, vol.root_dir_record, 1, NULL, 0);
strncpy_pad((char*)vol.vol_set_id, volset_id, 128);
strncpy_pad((char*)vol.publisher_id, pub_id, 128);
@@ -410,14 +420,14 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
/* initialize buffer with 0s */
memset(buffer, 0, BLOCK_SIZE);
/*
/*
* set susp_info to 0's, this way code for both plain ECMA-119 and
* RR is very similar
*/
memset(&info, 0, sizeof(struct susp_info));
if (t->rockridge) {
/* initialize the ce_block, it might be needed */
info.ce_block = dir->info.dir->block + DIV_UP(dir->info.dir->len,
info.ce_block = dir->info.dir->block + DIV_UP(dir->info.dir->len,
BLOCK_SIZE);
}
@@ -429,7 +439,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
}
}
len = 34 + info.suf_len;
write_one_dir_record(t, dir, 0, buf, 1, &info);
write_one_dir_record(t, dir, 0, buf, 1, &info, 0);
buf += len;
if (t->rockridge) {
@@ -439,40 +449,46 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
}
}
len = 34 + info.suf_len;
write_one_dir_record(t, dir, 1, buf, 1, &info);
write_one_dir_record(t, dir, 1, buf, 1, &info, 0);
buf += len;
for (i = 0; i < dir->info.dir->nchildren; i++) {
int section, nsections;
Ecma119Node *child = dir->info.dir->children[i];
/* 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;
}
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 */
ret = iso_write(t, buffer, BLOCK_SIZE);
if (ret < 0) {
return ret;
/* compute len of directory entry */
len = fi_len + 33 + (fi_len % 2 ? 0 : 1);
if (need_version_number(t, child)) {
len += 2;
}
memset(buffer, 0, BLOCK_SIZE);
buf = buffer;
/* 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;
}
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;
}
/* write the directory entry in any case */
write_one_dir_record(t, child, -1, buf, fi_len, &info, section);
buf += len;
}
/* write the directory entry in any case */
write_one_dir_record(t, child, -1, buf, fi_len, &info);
buf += len;
}
/* write the last block */
@@ -709,7 +725,7 @@ int pad_writer_write_data(IsoImageWriter *writer)
return ISO_ASSERT_FAILURE;
}
t = writer->target;
if (t->pad_blocks == 0) {
return ISO_SUCCESS;
}
@@ -820,7 +836,7 @@ void *write_function(void *arg)
iso_msg_submit(target->image->id, ISO_IMAGE_WRITE_CANCELED, 0, NULL);
} else {
/* image write error */
iso_msg_submit(target->image->id, ISO_WRITE_ERROR, res,
iso_msg_submit(target->image->id, ISO_WRITE_ERROR, res,
"Image write error");
}
iso_ring_buffer_writer_close(target->buffer, 1);
@@ -855,7 +871,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->iso1999 = opts->iso1999;
target->always_gmt = opts->always_gmt;
target->ino = 0;
target->omit_version_numbers = opts->omit_version_numbers
target->omit_version_numbers = opts->omit_version_numbers
| opts->max_37_char_filenames;
target->allow_deep_paths = opts->allow_deep_paths;
target->allow_longer_paths = opts->allow_longer_paths;
@@ -882,7 +898,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->appendable = opts->appendable;
target->replace_timestamps = opts->replace_timestamps ? 1 : 0;
target->timestamp = opts->replace_timestamps == 2 ?
target->timestamp = opts->replace_timestamps == 2 ?
opts->timestamp : target->now;
/* el-torito? */
@@ -909,10 +925,10 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
return ISO_OUT_OF_MEM;
}
/*
/*
* 2. Based on those options, create needed writers: iso, joliet...
* Each writer inits its structures and stores needed info into
* target.
* target.
* If the writer needs an volume descriptor, it increments image
* current block.
* Finally, create Writer for files.
@@ -944,7 +960,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
if (ret < 0) {
goto target_cleanup;
}
/* create writer for El-Torito */
if (target->eltorito) {
ret = eltorito_writer_create(target);
@@ -952,7 +968,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
goto target_cleanup;
}
}
/* create writer for Joliet structure */
if (target->joliet) {
ret = joliet_writer_create(target);
@@ -960,7 +976,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
goto target_cleanup;
}
}
/* create writer for ISO 9660:1999 structure */
if (target->iso1999) {
ret = iso1999_writer_create(target);
@@ -970,11 +986,11 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
}
voldesc_size = target->curblock - target->ms_block - 16;
/* Volume Descriptor Set Terminator */
target->curblock++;
/*
/*
* Create the writer for possible padding to ensure that in case of image
* growing we can safety overwrite the first 64 KiB of image.
*/
@@ -990,7 +1006,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
}
/*
* 3.
* 3.
* Call compute_data_blocks() in each Writer.
* That function computes the size needed by its structures and
* increments image current block propertly.
@@ -1130,14 +1146,14 @@ static void bs_free_data(struct burn_source *bs)
if (st < 4) {
/* forces writer to stop if it is still running */
iso_ring_buffer_reader_close(target->buffer, 0);
/* wait until writer thread finishes */
pthread_join(target->wthread, NULL);
iso_msg_debug(target->image->id, "Writer thread joined");
}
iso_msg_debug(target->image->id,
"Ring buffer was %d times full and %d times empty",
iso_msg_debug(target->image->id,
"Ring buffer was %d times full and %d times empty",
iso_ring_buffer_get_times_full(target->buffer),
iso_ring_buffer_get_times_empty(target->buffer));
@@ -1153,9 +1169,9 @@ int bs_cancel(struct burn_source *bs)
Ecma119Image *target = (Ecma119Image*)bs->data;
st = iso_ring_buffer_get_status(bs, &cap, &free);
if (free == cap && (st == 2 || st == 3)) {
/* image was already consumed */
/* image was already consumed */
iso_ring_buffer_reader_close(target->buffer, 0);
} else {
iso_msg_debug(target->image->id, "Reader thread being cancelled");
@@ -1176,7 +1192,7 @@ int bs_set_size(struct burn_source *bs, off_t size)
{
Ecma119Image *target = (Ecma119Image*)bs->data;
/*
/*
* just set the value to be returned by get_size. This is not used at
* all by libisofs, it is here just for helping libburn to correctly pad
* the image if needed.
@@ -1235,12 +1251,12 @@ int iso_write(Ecma119Image *target, void *buf, size_t count)
if (ret > 0 && (target->total_size != (off_t) 0)){
unsigned int kbw, kbt;
int percent;
target->bytes_written += (off_t) count;
kbw = (unsigned int) (target->bytes_written >> 10);
kbt = (unsigned int) (target->total_size >> 10);
percent = (kbw * 100) / kbt;
/* only report in 5% chunks */
if (percent >= target->percent_written + 5) {
iso_msg_debug(target->image->id, "Processed %u of %u KB (%d %%)",
@@ -1248,32 +1264,32 @@ int iso_write(Ecma119Image *target, void *buf, size_t count)
target->percent_written = percent;
}
}
return ret;
}
int iso_write_opts_new(IsoWriteOpts **opts, int profile)
{
IsoWriteOpts *wopts;
if (opts == NULL) {
return ISO_NULL_POINTER;
}
if (profile < 0 || profile > 2) {
return ISO_WRONG_ARG_VALUE;
}
wopts = calloc(1, sizeof(IsoWriteOpts));
if (wopts == NULL) {
return ISO_OUT_OF_MEM;
}
switch (profile) {
case 0:
wopts->level = 1;
break;
case 1:
wopts->level = 2;
wopts->level = 3;
wopts->rockridge = 1;
break;
case 2:
@@ -1305,7 +1321,7 @@ void iso_write_opts_free(IsoWriteOpts *opts)
if (opts == NULL) {
return;
}
free(opts->output_charset);
free(opts);
}
@@ -1315,7 +1331,7 @@ int iso_write_opts_set_iso_level(IsoWriteOpts *opts, int level)
if (opts == NULL) {
return ISO_NULL_POINTER;
}
if (level != 1 && level != 2) {
if (level != 1 && level != 2 && level != 3) {
return ISO_WRONG_ARG_VALUE;
}
opts->level = level;

View File

@@ -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.
*/
@@ -18,6 +18,18 @@
#define BLOCK_SIZE 2048
/*
* Maximum file section size. Set to 4GB - 1 = 0xffffffff
*/
#define MAX_ISO_FILE_SECTION_SIZE 0xffffffff
/*
* When a file need to be splitted in several sections, the maximum size
* of such sections, but the last one. Set to a multiple of BLOCK_SIZE.
* Default to 4GB - 2048 = 0xFFFFF800
*/
#define ISO_EXTENT_SIZE 0xFFFFF800
/**
* Holds the options for the image generation.
*/
@@ -33,11 +45,11 @@ struct iso_write_opts {
/* allways write timestamps in GMT */
unsigned int always_gmt :1;
/*
/*
* Relaxed constraints. Setting any of these to 1 break the specifications,
* but it is supposed to work on most moderns systems. Use with caution.
* but it is supposed to work on most moderns systems. Use with caution.
*/
/**
* Omit the version number (";1") at the end of the ISO-9660 identifiers.
* Version numbers are usually not used.
@@ -45,7 +57,7 @@ struct iso_write_opts {
unsigned int omit_version_numbers :1;
/**
* Allow ISO-9660 directory hierarchy to be deeper than 8 levels.
* Allow ISO-9660 directory hierarchy to be deeper than 8 levels.
*/
unsigned int allow_deep_paths :1;
@@ -64,30 +76,30 @@ struct iso_write_opts {
/**
* ISO-9660 forces filenames to have a ".", that separates file name from
* extension. libisofs adds it if original filename doesn't has one. Set
* extension. libisofs adds it if original filename doesn't has one. Set
* this to 1 to prevent this behavior
*/
unsigned int no_force_dots :1;
/**
* Allow lowercase characters in ISO-9660 filenames. By default, only
* uppercase characters, numbers and a few other characters are allowed.
* Allow lowercase characters in ISO-9660 filenames. By default, only
* uppercase characters, numbers and a few other characters are allowed.
*/
unsigned int allow_lowercase :1;
/**
* Allow all ASCII characters to be appear on an ISO-9660 filename. Note
* that "/" and "\0" characters are never allowed, even in RR names.
*/
unsigned int allow_full_ascii :1;
/**
* Allow all characters to be part of Volume and Volset identifiers on
* the Primary Volume Descriptor. This breaks ISO-9660 contraints, but
* should work on modern systems.
*/
unsigned int relaxed_vol_atts :1;
/**
* Allow paths in the Joliet tree to have more than 240 characters.
*/
@@ -102,7 +114,7 @@ struct iso_write_opts {
* If 0, the corresponding attribute will be kept as setted in the IsoNode.
* Unless you have changed it, it corresponds to the value on disc, so it
* is suitable for backup purposes. If set to 1, the corresponding attrib.
* will be changed by a default suitable value. Finally, if you set it to
* will be changed by a default suitable value. Finally, if you set it to
* 2, the attrib. will be changed with the value specified in the options
* below. Note that for mode attributes, only the permissions are set, the
* file type remains unchanged.
@@ -133,62 +145,62 @@ struct iso_write_opts {
/**
* This flags control the type of the image to create. Libisofs support
* two kind of images: stand-alone and appendable.
*
* two kind of images: stand-alone and appendable.
*
* A stand-alone image is an image that is valid alone, and that can be
* mounted by its own. This is the kind of image you will want to create
* in most cases. A stand-alone image can be burned in an empty CD or DVD,
* or write to an .iso file for future burning or distribution.
*
*
* On the other side, an appendable image is not self contained, it refers
* to serveral files that are stored outside the image. Its usage is for
* multisession discs, where you add data in a new session, while the
* previous session data can still be accessed. In those cases, the old
* multisession discs, where you add data in a new session, while the
* previous session data can still be accessed. In those cases, the old
* data is not written again. Instead, the new image refers to it, and thus
* it's only valid when appended to the original. Note that in those cases
* the image will be written after the original, and thus you will want
* to use a ms_block greater than 0.
*
* Note that if you haven't import a previous image (by means of
* to use a ms_block greater than 0.
*
* Note that if you haven't import a previous image (by means of
* iso_image_import()), the image will always be a stand-alone image, as
* there is no previous data to refer to.
*/
unsigned int appendable : 1;
/**
* Start block of the image. It is supposed to be the lba where the first
* block of the image will be written on disc. All references inside the
* ISO image will take this into account, thus providing a mountable image.
*
* For appendable images, that are written to a new session, you should
*
* For appendable images, that are written to a new session, you should
* pass here the lba of the next writable address on disc.
*
* In stand alone images this is usually 0. However, you may want to
*
* In stand alone images this is usually 0. However, you may want to
* provide a different ms_block if you don't plan to burn the image in the
* first session on disc, such as in some CD-Extra disc whether the data
* image is written in a new session after some audio tracks.
* image is written in a new session after some audio tracks.
*/
uint32_t ms_block;
/**
* When not NULL, it should point to a buffer of at least 64KiB, where
* When not NULL, it should point to a buffer of at least 64KiB, where
* libisofs will write the contents that should be written at the beginning
* of a overwriteable media, to grow the image. The growing of an image is
* a way, used by first time in growisofs by Andy Polyakov, to allow the
* appending of new data to non-multisession media, such as DVD+RW, in the
* same way you append a new session to a multisession disc, i.e., without
* need to write again the contents of the previous image.
*
* need to write again the contents of the previous image.
*
* Note that if you want this kind of image growing, you will also need to
* set appendable to "1" and provide a valid ms_block after the previous
* image.
*
* You should initialize the buffer either with 0s, or with the contents of
* the first blocks of the image you're growing. In most cases, 0 is good
*
* You should initialize the buffer either with 0s, or with the contents of
* the first blocks of the image you're growing. In most cases, 0 is good
* enought.
*/
uint8_t *overwrite;
/**
* Size, in number of blocks, of the FIFO buffer used between the writer
* thread and the burn_source. You have to provide at least a 32 blocks
@@ -228,13 +240,13 @@ struct ecma119_image
unsigned int no_force_dots :1;
unsigned int allow_lowercase :1;
unsigned int allow_full_ascii :1;
unsigned int relaxed_vol_atts : 1;
/** Allow paths on Joliet tree to be larger than 240 bytes */
unsigned int joliet_longer_paths :1;
/*
/*
* Mode replace. If one of these flags is set, the correspodent values are
* replaced with values below.
*/
@@ -251,7 +263,7 @@ struct ecma119_image
time_t timestamp;
/**
* if sort files or not. Sorting is based of the weight of each file
* if sort files or not. Sorting is based of the weight of each file
*/
int sort_files;
@@ -282,7 +294,7 @@ struct ecma119_image
*/
uint32_t curblock;
/*
/*
* number of dirs in ECMA-119 tree, computed together with dir position,
* and needed for path table computation in a efficient way
*/
@@ -290,7 +302,7 @@ struct ecma119_image
uint32_t path_table_size;
uint32_t l_path_table_pos;
uint32_t m_path_table_pos;
/*
* Joliet related information
*/
@@ -299,7 +311,7 @@ struct ecma119_image
uint32_t joliet_path_table_size;
uint32_t joliet_l_path_table_pos;
uint32_t joliet_m_path_table_pos;
/*
* ISO 9660:1999 related information
*/
@@ -308,7 +320,7 @@ struct ecma119_image
uint32_t iso1999_path_table_size;
uint32_t iso1999_l_path_table_pos;
uint32_t iso1999_m_path_table_pos;
/*
* El-Torito related information
*/
@@ -322,10 +334,10 @@ struct ecma119_image
* data. These padding blocks are added by libisofs to improve the handling
* of image growing. The idea is that the first blocks in the image are
* overwritten with the volume descriptors of the new image. These first
* blocks usually correspond to the volume descriptors and directory
* structure of the old image, and can be safety overwritten. However,
* with very small images they might correspond to valid data. To ensure
* this never happens, what we do is to add padding bytes, to ensure no
* blocks usually correspond to the volume descriptors and directory
* structure of the old image, and can be safety overwritten. However,
* with very small images they might correspond to valid data. To ensure
* this never happens, what we do is to add padding bytes, to ensure no
* file data is written in the first 64 KiB, that are the bytes we usually
* overwrite.
*/

View File

@@ -161,7 +161,7 @@ int create_file(Ecma119Image *img, IsoFile *iso, Ecma119Node **node)
off_t size;
size = iso_stream_get_size(iso->stream);
if (size > (off_t)0xffffffff) {
if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE && img->iso_level != 3) {
char *ipath = iso_tree_get_node_path(ISO_NODE(iso));
ret = iso_msg_submit(img->image->id, ISO_FILE_TOO_BIG, 0,
"File \"%s\" can't be added to image because "

View File

@@ -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;

View File

@@ -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.
*/
@@ -61,20 +61,45 @@ 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 && img->appendable) {
/*
* On multisession discs we keep file sections from old image.
*/
int ret = iso_file_get_old_image_sections(file, &(fsrc->nsections),
&(fsrc->sections), 0);
if (ret < 0) {
free(fsrc);
return ISO_OUT_OF_MEM;
}
} else {
/*
* For new files, or for image copy, we compute our own file sections.
* Block and size of each section will be filled later.
*/
off_t section_size = iso_stream_get_size(file->stream);
if (section_size > (off_t) MAX_ISO_FILE_SECTION_SIZE) {
fsrc->nsections = DIV_UP(section_size - (off_t) MAX_ISO_FILE_SECTION_SIZE,
(off_t)ISO_EXTENT_SIZE) + 1;
} else {
fsrc->nsections = 1;
}
fsrc->sections = calloc(fsrc->nsections, sizeof(struct iso_file_section));
}
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;
}
@@ -84,12 +109,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
@@ -97,7 +122,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
*/
@@ -108,7 +133,7 @@ int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src)
if (img == NULL || new == NULL || src == NULL) {
return ISO_NULL_POINTER;
}
/* insert the filesrc in the tree */
ret = iso_rbtree_insert(img->files, new, (void**)src);
return ret;
@@ -117,6 +142,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);
}
@@ -160,7 +186,7 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
} else {
inc_item = NULL;
}
/* store the filesrcs in a array */
filelist = (IsoFileSrc**)iso_rbtree_to_array(t->files, inc_item, &size);
if (filelist == NULL) {
@@ -174,8 +200,23 @@ 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);
for (extent = 0; extent < file->nsections - 1; ++extent) {
file->sections[extent].block = t->curblock + extent *
(ISO_EXTENT_SIZE / BLOCK_SIZE);
file->sections[extent].size = ISO_EXTENT_SIZE;
section_size -= (off_t) ISO_EXTENT_SIZE;
}
/*
* final section
*/
file->sections[extent].block = t->curblock + extent * (ISO_EXTENT_SIZE / BLOCK_SIZE);
file->sections[extent].size = (uint32_t)section_size;
t->curblock += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
}
@@ -259,22 +300,17 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
i = 0;
while ((file = filelist[i++]) != NULL) {
/*
* TODO WARNING
* when we allow files greater than 4GB, current DIV_UP implementation
* can overflow!!
*/
uint32_t nblocks = DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
res = filesrc_open(file);
iso_stream_get_file_name(file->stream, name);
if (res < 0) {
/*
/*
* UPS, very ugly error, the best we can do is just to write
* 0's to image
*/
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
"File \"%s\" can't be opened. Filling with 0s.", name);
if (res < 0) {
return res; /* aborted due to error severity */
@@ -290,7 +326,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
continue;
} else if (res > 1) {
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Size of file \"%s\" has changed. It will be %s", name,
(res == 2 ? "truncated" : "padded with 0's"));
if (res < 0) {
@@ -338,7 +374,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
if (res < 0) {
return res; /* aborted due error severity */
}
/* fill with 0s */
iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
"Filling with 0");

View File

@@ -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);

File diff suppressed because it is too large Load Diff

View File

@@ -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)MAX_ISO_FILE_SECTION_SIZE && t->iso_level != 3) {
char *ipath = iso_tree_get_node_path(iso);
ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
"File \"%s\" can't be added to image because is "
@@ -557,14 +557,19 @@ size_t calc_dir_size(Ecma119Image *t, Iso1999Node *dir)
for (i = 0; i < dir->info.dir->nchildren; ++i) {
size_t remaining;
int section, nsections;
Iso1999Node *child = dir->info.dir->children[i];
size_t dirent_len = calc_dirent_len(t, child);
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
if (dirent_len > remaining) {
/* child directory entry doesn't fit on block */
len += remaining + dirent_len;
} else {
len += dirent_len;
nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1;
for (section = 0; section < nsections; ++section) {
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
if (dirent_len > remaining) {
/* child directory entry doesn't fit on block */
len += remaining + dirent_len;
} else {
len += dirent_len;
}
}
}
@@ -663,11 +668,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;
@@ -682,8 +688,9 @@ 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
@@ -703,7 +710,7 @@ 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;
}
@@ -762,7 +769,7 @@ 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);
@@ -809,30 +816,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 */

View File

@@ -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)MAX_ISO_FILE_SECTION_SIZE && t->iso_level != 3) {
char *ipath = iso_tree_get_node_path(iso);
free(joliet);
ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
@@ -590,14 +590,19 @@ size_t calc_dir_size(Ecma119Image *t, JolietNode *dir)
for (i = 0; i < dir->info.dir->nchildren; ++i) {
size_t remaining;
int section, nsections;
JolietNode *child = dir->info.dir->children[i];
size_t dirent_len = calc_dirent_len(t, child);
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
if (dirent_len > remaining) {
/* child directory entry doesn't fit on block */
len += remaining + dirent_len;
} else {
len += dirent_len;
nsections = (child->type == JOLIET_FILE) ? child->info.file->nsections : 1;
for (section = 0; section < nsections; ++section) {
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
if (dirent_len > remaining) {
/* child directory entry doesn't fit on block */
len += remaining + dirent_len;
} else {
len += dirent_len;
}
}
}
@@ -696,11 +701,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;
@@ -723,8 +729,9 @@ 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
@@ -744,7 +751,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;
}
@@ -827,7 +834,7 @@ 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);
@@ -874,12 +881,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 */
@@ -889,18 +897,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 */

View File

@@ -107,6 +107,17 @@ enum IsoNodeType {
#define ISO_NODE(n) ((IsoNode*)n)
/**
* File section in an old image.
*
* @since 0.6.8
*/
struct iso_file_section
{
uint32_t block;
uint32_t size;
};
/**
* Context for iterate on directory children.
* @see iso_dir_get_children()
@@ -917,7 +928,7 @@ int iso_lib_is_compatible(int major, int minor, int micro);
* start point from which to set your custom options.
* ---> 1 [BACKUP]
* POSIX compatibility for backup. Simple settings, ISO level is set to
* 2 and RR extensions are enabled. Useful for backup purposes.
* 3 and RR extensions are enabled. Useful for backup purposes.
* ---> 2 [DISTRIBUTION]
* Setting for information distribution. Both RR and Joliet are enabled
* to maximize compatibility with most systems. Permissions are set to
@@ -943,6 +954,7 @@ void iso_write_opts_free(IsoWriteOpts *opts);
* -> 1 for higher compatibility with old systems. With this level
* filenames are restricted to 8.3 characters.
* -> 2 to allow up to 31 filename characters.
* -> 3 to allow files greater than 4GB
* @return
* 1 success, < 0 error
*
@@ -2551,9 +2563,35 @@ IsoStream *iso_file_get_stream(IsoFile *file);
* added, i.e. it does not come from an old image, < 0 error
*
* @since 0.6.4
*
* @deprecated Use iso_file_get_old_image_sections(), as this function does
* not work with multi-extend files.
*/
int iso_file_get_old_image_lba(IsoFile *file, uint32_t *lba, int flag);
/**
* Get the start addresses and the sizes of the data extents of a file node
* if it was imported from an old image.
*
* @param file
* The file
* @param section_count
* Returns the number of extent entries in sections array.
* @param sections
* Returns the array of file sections. Apply free() to dispose it.
* @param flag
* Reserved for future usage, submit 0
* @return
* 1 if there are valid extents (file comes from old image),
* 0 if file was newly added, i.e. it does not come from an old image,
* < 0 error
*
* @since 0.6.8
*/
int iso_file_get_old_image_sections(IsoFile *file, int *section_count,
struct iso_file_section **sections,
int flag);
/*
* Like iso_file_get_old_image_lba(), but take an IsoNode.
*

View File

@@ -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
@@ -921,7 +921,7 @@ dev_t iso_special_get_dev(IsoSpecial *special)
/**
* Get the block lba of a file node, if it was imported from an old image.
*
*
* @param file
* The file
* @param lba
@@ -930,31 +930,39 @@ dev_t iso_special_get_dev(IsoSpecial *special)
* 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, &section_count, &sections, 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
@@ -973,7 +981,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
*/
@@ -1003,7 +1011,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
*/
@@ -1021,18 +1029,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) {
@@ -1054,13 +1062,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;
@@ -1068,7 +1076,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)) {
@@ -1100,7 +1108,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;
@@ -1130,7 +1138,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)
@@ -1163,7 +1171,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) {
@@ -1197,11 +1205,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;
@@ -1222,11 +1230,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;
@@ -1249,16 +1257,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 */
@@ -1278,18 +1286,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;

View File

@@ -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);

View File

@@ -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.
*/
@@ -19,16 +19,6 @@ ino_t serial_id = (ino_t)1;
ino_t mem_serial_id = (ino_t)1;
ino_t cut_out_serial_id = (ino_t)1;
typedef struct
{
IsoFileSource *src;
/* key for file identification inside filesystem */
dev_t dev_id;
ino_t ino_id;
off_t size; /**< size of this file */
} FSrcStreamData;
static
int fsrc_open(IsoStream *stream)
{
@@ -116,7 +106,7 @@ void fsrc_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
{
FSrcStreamData *data;
IsoFilesystem *fs;
data = (FSrcStreamData*)stream->data;
fs = iso_file_source_get_filesystem(data->src);
@@ -164,7 +154,7 @@ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream)
if (S_ISDIR(info.st_mode)) {
return ISO_FILE_IS_DIR;
}
/* check for read access to contents */
r = iso_file_source_access(src);
if (r < 0) {
@@ -184,7 +174,7 @@ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream)
/* take the ref to IsoFileSource */
data->src = src;
data->size = info.st_size;
/* get the id numbers */
{
IsoFilesystem *fs;
@@ -193,7 +183,7 @@ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream)
fs_id = fs->get_id(fs);
if (fs_id == 0) {
/*
/*
* the filesystem implementation is unable to provide valid
* st_dev and st_ino fields. Use serial_id.
*/
@@ -232,11 +222,11 @@ int cut_out_open(IsoStream *stream)
struct stat info;
IsoFileSource *src;
struct cut_out_stream *data;
if (stream == NULL) {
return ISO_NULL_POINTER;
}
data = stream->data;
src = data->src;
ret = iso_file_source_stat(data->src, &info);
@@ -247,7 +237,7 @@ int cut_out_open(IsoStream *stream)
if (ret < 0) {
return ret;
}
{
off_t ret;
if (data->offset > info.st_size) {
@@ -310,7 +300,7 @@ void cut_out_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
{
FSrcStreamData *data;
IsoFilesystem *fs;
data = (FSrcStreamData*)stream->data;
fs = iso_file_source_get_filesystem(data->src);
@@ -339,7 +329,7 @@ IsoStreamIface cut_out_stream_class = {
cut_out_free
};
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
IsoStream **stream)
{
int r;
@@ -364,7 +354,7 @@ int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
if (offset > info.st_size) {
return ISO_FILE_OFFSET_TOO_BIG;
}
/* check for read access to contents */
r = iso_file_source_access(src);
if (r < 0) {
@@ -384,10 +374,10 @@ int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
/* take a new ref to IsoFileSource */
data->src = src;
iso_file_source_ref(src);
data->offset = offset;
data->size = MIN(info.st_size - offset, size);
/* get the id numbers */
data->dev_id = (dev_t) 0;
data->ino_id = cut_out_serial_id++;
@@ -461,15 +451,15 @@ int mem_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;
}
if (data->offset >= data->size) {
return 0; /* EOF */
}
len = MIN(count, data->size - data->offset);
memcpy(buf, data->buf + data->offset, len);
data->offset += len;
@@ -517,7 +507,7 @@ IsoStreamIface mem_stream_class = {
/**
* Create a stream for reading from a arbitrary memory buffer.
* When the Stream refcount reach 0, the buffer is free(3).
*
*
* @return
* 1 sucess, < 0 error
*/
@@ -607,11 +597,12 @@ void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
void iso_stream_get_file_name(IsoStream *stream, char *name)
{
char *type = stream->class->type;
if (!strncmp(type, "fsrc", 4)) {
FSrcStreamData *data = stream->data;
char *path = iso_file_source_get_path(data->src);
strncpy(name, path, PATH_MAX);
free(path);
} else if (!strncmp(type, "boot", 4)) {
strcpy(name, "BOOT CATALOG");
} else if (!strncmp(type, "mem ", 4)) {

View File

@@ -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_STREAM_H_
@@ -13,9 +13,19 @@
*/
#include "fsource.h"
typedef struct
{
IsoFileSource *src;
/* key for file identification inside filesystem */
dev_t dev_id;
ino_t ino_id;
off_t size; /**< size of this file */
} FSrcStreamData;
/**
* Get an identifier for the file of the source, for debug purposes
* @param name
* @param name
* Should provide at least PATH_MAX bytes
*/
void iso_stream_get_file_name(IsoStream *stream, char *name);
@@ -25,28 +35,28 @@ void iso_stream_get_file_name(IsoStream *stream, char *name);
* The stream will take the ref. to the IsoFileSource, so after a successfully
* exectution of this function, you musn't unref() the source, unless you
* take an extra ref.
*
*
* @return
* 1 sucess, < 0 error
* Possible errors:
*
*
*/
int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream);
/**
* Create a new stream to read a chunk of an IsoFileSource..
* The stream will add a ref. to the IsoFileSource.
*
*
* @return
* 1 sucess, < 0 error
*/
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size,
IsoStream **stream);
/**
* Create a stream for reading from a arbitrary memory buffer.
* When the Stream refcount reach 0, the buffer is free(3).
*
*
* @return
* 1 sucess, < 0 error
*/