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
commit c1a7702f52
18 changed files with 1424 additions and 983 deletions

View File

@ -39,7 +39,7 @@ print_type(mode_t mode)
case S_IFREG: printf("[R] "); break;
case S_IFBLK: printf("[B] "); break;
case S_IFDIR: printf("[D] "); break;
case S_IFIFO: printf("[F] "); break;
case S_IFIFO: printf("[F] "); break;
}
}
@ -51,6 +51,7 @@ print_file_src(IsoFileSource *file)
iso_file_source_lstat(file, &info);
print_type(info.st_mode);
print_permissions(info.st_mode);
printf(" %10llu ", info.st_size);
//printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino);
name = iso_file_source_get_name(file);
printf(" %s", name);
@ -116,7 +117,7 @@ int main(int argc, char **argv)
iso_init();
iso_set_msgs_severities("NEVER", "ALL", "");
result = iso_data_source_new_from_file(argv[1], &src);
if (result < 0) {
printf ("Error creating data source\n");
@ -134,10 +135,10 @@ int main(int argc, char **argv)
printf ("Error creating filesystem\n");
return 1;
}
printf("\nVOLUME INFORMATION\n");
printf("==================\n\n");
printf("Vol. id: %s\n", iso_image_fs_get_volume_id(fs));
printf("Publisher: %s\n", iso_image_fs_get_publisher_id(fs));
printf("Data preparer: %s\n", iso_image_fs_get_data_preparer_id(fs));
@ -149,7 +150,7 @@ int main(int argc, char **argv)
printf("\nDIRECTORY TREE\n");
printf("==============\n");
result = fs->get_root(fs, &root);
if (result < 0) {
printf ("Can't get root %d\n", result);
@ -158,7 +159,7 @@ int main(int argc, char **argv)
//print_file_src(root);
print_dir(root, 0);
iso_file_source_unref(root);
fs->close(fs);
iso_filesystem_unref((IsoFilesystem*)fs);
iso_data_source_unref(src);

View File

@ -0,0 +1,58 @@
===============================================================================
ISO-9660 Level 3 Cookbook
===============================================================================
Creation date: 2008-Aug-17
Author: Vreixo Formoso
_______________________________________________________________________________
Contents:
---------
1. References
2. General
3. OS Support
4. Implementation
-------------------------------------------------------------------------------
1. References:
ECMA-119 "Volume and File Structure of CDROM for Information Interchange"
-------------------------------------------------------------------------------
2. General
In ECMA-119 standard, the size of a file section cannot be bigger than 4GB - 1,
because the Data Length field of the Directory Record is just 32 bits (9.1.4).
However, "each file shall consist of one or more File Sections" (6.5.1), and
that way we can store files greater than 4GB in a ECMA-119 image. Such image,
with multiple File Sections, is only supported at Level 3 (10.3), as Level 2
(10.2) states that "each file shall consist of only one File Section".
On disc, each file section is stored in a Extent (6.4.2), i.e. a set of
contiguous Logical Blocks.
-------------------------------------------------------------------------------
3. OS Support
Wikipedia states that "Microsoft Windows XP supports this, while Mac OS X
(as of 10.4.8) does not handle this case properly. In the case of Mac OS X,
the driver appears not to support file fragmentation at all (i.e. it only
supports ISO 9660 Level 2 but not Level 3). Linux supports multiple extents.
FreeBSD only shows and reads the last extent of a multi-extent file."
-------------------------------------------------------------------------------
4. Implementation
Each File Section will have its own Directory Record (6.5.1). So, for files
greater than 4 GB, we need to store several directory records, that will have
the same File Identifier, and stored in the order of the File Sections they
refer (9.3).
All but the last Directory Record must have the Multi-Extent flag set (9.1.6)

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
*/

View File

@ -1,6 +1,6 @@
/*
* Unit test for util.h
*
*
* This test utiliy functions
*/
#include "test.h"
@ -16,51 +16,51 @@ static void test_rrip_calc_len_file()
Ecma119Node *node;
Ecma119Image t;
size_t sua_len = 0, ce_len = 0;
memset(&t, 0, sizeof(Ecma119Image));
t.input_charset = "UTF-8";
t.output_charset = "UTF-8";
file = malloc(sizeof(IsoFile));
CU_ASSERT_PTR_NOT_NULL_FATAL(file);
file->msblock = 0;
file->from_old_session = 0;
file->sort_weight = 0;
file->stream = NULL; /* it is not needed here */
file->node.type = LIBISO_FILE;
node = malloc(sizeof(Ecma119Node));
CU_ASSERT_PTR_NOT_NULL_FATAL(node);
node->node = (IsoNode*)file;
node->parent = (Ecma119Node*)0x55555555; /* just to make it not NULL */
node->info.file = NULL; /* it is not needed here */
node->info.file = NULL; /* it is not needed here */
node->type = ECMA119_FILE;
/* Case 1. Name fit in System Use field */
file->node.name = "a small name.txt";
node->iso_name = "A_SMALL_.TXT";
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 0);
CU_ASSERT_EQUAL(sua_len, 44 + (5 + 16) + (5 + 3*7) + 1);
/* Case 2. Name fits exactly */
file->node.name = "a big name, with 133 characters, that it is the max "
"that fits in System Use field of the directory record "
"PADPADPADADPADPADPADPAD.txt";
node->iso_name = "A_BIG_NA.TXT";
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 0);
/* note that 254 is the max length of a directory record, as it needs to
* be an even number */
CU_ASSERT_EQUAL(sua_len, 254 - 46);
/* case 3. A name just 1 character too big to fit in SUA */
file->node.name = "a big name, with 133 characters, that it is the max "
"that fits in System Use field of the directory record "
"PADPADPADADPADPADPADPAD1.txt";
node->iso_name = "A_BIG_NA.TXT";
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
/* 28 (the chars moved to include the CE entry) + 5 (header of NM in CE) +
* 1 (the char that originally didn't fit) */
@ -68,21 +68,21 @@ static void test_rrip_calc_len_file()
/* note that 254 is the max length of a directory record, as it needs to
* be an even number */
CU_ASSERT_EQUAL(sua_len, 254 - 46);
/* case 4. A 255 characters name */
file->node.name = "a big name, with 255 characters, that it is the max "
"that a POSIX filename can have. PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP";
node->iso_name = "A_BIG_NA.TXT";
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
/* 150 + 5 (header + characters that don't fit in sua) */
CU_ASSERT_EQUAL(ce_len, 150 + 5);
/* note that 254 is the max length of a directory record, as it needs to
* be an even number */
CU_ASSERT_EQUAL(sua_len, 254 - 46);
free(node);
free(file);
}
@ -93,31 +93,31 @@ static void test_rrip_calc_len_symlink()
Ecma119Node *node;
Ecma119Image t;
size_t sua_len = 0, ce_len = 0;
memset(&t, 0, sizeof(Ecma119Image));
t.input_charset = "UTF-8";
t.output_charset = "UTF-8";
link = malloc(sizeof(IsoSymlink));
CU_ASSERT_PTR_NOT_NULL_FATAL(link);
link->node.type = LIBISO_SYMLINK;
node = malloc(sizeof(Ecma119Node));
CU_ASSERT_PTR_NOT_NULL_FATAL(node);
node->node = (IsoNode*)link;
node->parent = (Ecma119Node*)0x55555555; /* just to make it not NULL */
node->type = ECMA119_SYMLINK;
/* Case 1. Name and dest fit in System Use field */
link->node.name = "a small name.txt";
link->dest = "/three/components";
node->iso_name = "A_SMALL_.TXT";
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 0);
CU_ASSERT_EQUAL(sua_len, 44 + (5 + 16) + (5 + 3*7) + 1 +
CU_ASSERT_EQUAL(sua_len, 44 + (5 + 16) + (5 + 3*7) + 1 +
(5 + 2 + (2+5) + (2+10)) );
/* case 2. name + dest fits exactly */
link->node.name = "this name will have 74 characters as it is the max "
"that fits in the SU.txt";
@ -136,7 +136,7 @@ static void test_rrip_calc_len_symlink()
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 60);
CU_ASSERT_EQUAL(sua_len, 44 + (5 + 74) + (5 + 3*7) + 1 + 28);
/* 3.b extra byte in name */
link->node.name = "this name will have 75 characters as it is the max "
"that fits in the SUx.txt";
@ -145,10 +145,10 @@ static void test_rrip_calc_len_symlink()
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 59);
CU_ASSERT_EQUAL(sua_len, 44 + (5 + 75) + (5 + 3*7) + 28);
/* case 4. name seems to fit, but SL no, and when CE is added NM
/* case 4. name seems to fit, but SL no, and when CE is added NM
* doesn't fit too */
/* 4.a it just fits */
/* 4.a it just fits */
link->node.name = "this name will have 105 characters as it is just the "
"max that fits in the SU once we add the CE entry.txt";
link->dest = "./and/../a/./big/destination/with/10/components";
@ -156,8 +156,8 @@ static void test_rrip_calc_len_symlink()
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 59);
CU_ASSERT_EQUAL(sua_len, 254 - 46);
/* 4.b it just fits, the the component ends in '/' */
/* 4.b it just fits, the the component ends in '/' */
link->node.name = "this name will have 105 characters as it is just the "
"max that fits in the SU once we add the CE entry.txt";
link->dest = "./and/../a/./big/destination/with/10/components/";
@ -165,8 +165,8 @@ static void test_rrip_calc_len_symlink()
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 59);
CU_ASSERT_EQUAL(sua_len, 254 - 46);
/* 4.c extra char in name, that forces it to be divided */
/* 4.c extra char in name, that forces it to be divided */
link->node.name = "this name will have 105 characters as it is just the "
"max that fits in the SU once we add the CE entryc.txt";
link->dest = "./and/../a/./big/destination/with/10/components";
@ -174,7 +174,7 @@ static void test_rrip_calc_len_symlink()
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 59 + 6);
CU_ASSERT_EQUAL(sua_len, 254 - 46);
/* 5 max destination length to fit in a single SL entry (250) */
link->node.name = "this name will have 74 characters as it is the max "
"that fits in the SU.txt";
@ -186,7 +186,7 @@ static void test_rrip_calc_len_symlink()
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 255);
CU_ASSERT_EQUAL(sua_len, 44 + (5 + 74) + (5 + 3*7) + 1 + 28);
/* 6 min destination length to need two SL entries (251) */
link->node.name = "this name will have 74 characters as it is the max "
"that fits in the SU.txt";
@ -198,8 +198,8 @@ static void test_rrip_calc_len_symlink()
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 261);
CU_ASSERT_EQUAL(sua_len, 44 + (5 + 74) + (5 + 3*7) + 1 + 28);
/* 7 destination with big component that need to be splited
/* 7 destination with big component that need to be splited
* in two SL entries */
/* 7.a just fits in one */
link->node.name = "this name will have 74 characters as it is the max "
@ -213,7 +213,7 @@ static void test_rrip_calc_len_symlink()
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 255);
CU_ASSERT_EQUAL(sua_len, 44 + (5 + 74) + (5 + 3*7) + 1 + 28);
/* 7.b doesn't fits by one character */
link->node.name = "this name will have 74 characters as it is the max "
"that fits in the SU.txt";
@ -226,7 +226,7 @@ static void test_rrip_calc_len_symlink()
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 255 + (5+2+1));
CU_ASSERT_EQUAL(sua_len, 44 + (5 + 74) + (5 + 3*7) + 1 + 28);
/* 7.c several components before, such as it has just the right len
* to fit in the SL entry plus another one */
link->node.name = "this name will have 74 characters as it is the max "
@ -244,8 +244,8 @@ static void test_rrip_calc_len_symlink()
sua_len = rrip_calc_len(&t, node, 0, 255 - 46, &ce_len);
CU_ASSERT_EQUAL(ce_len, 255 + 255);
CU_ASSERT_EQUAL(sua_len, 44 + (5 + 74) + (5 + 3*7) + 1 + 28);
/*
/*
* 7.d several components before, and then a big component that doesn't
* fit in the 1st SL entry and another one. That case needs a 3rd SL entry,
* but instead of divide the component in 2 entries, we put it in 2,
@ -275,12 +275,12 @@ static
void susp_info_free(struct susp_info *susp)
{
size_t i;
for (i = 0; i < susp->n_susp_fields; ++i) {
free(susp->susp_fields[i]);
}
free(susp->susp_fields);
for (i = 0; i < susp->n_ce_susp_fields; ++i) {
free(susp->ce_susp_fields[i]);
}
@ -296,14 +296,14 @@ void test_rrip_get_susp_fields_file()
struct susp_info susp;
Ecma119Image t;
uint8_t *entry;
memset(&t, 0, sizeof(Ecma119Image));
t.input_charset = "UTF-8";
t.output_charset = "UTF-8";
file = malloc(sizeof(IsoFile));
CU_ASSERT_PTR_NOT_NULL_FATAL(file);
file->msblock = 0;
file->from_old_session = 0;
file->sort_weight = 0;
file->stream = NULL; /* it is not needed here */
file->node.type = LIBISO_FILE;
@ -313,20 +313,20 @@ void test_rrip_get_susp_fields_file()
file->node.mtime = 675757578;
file->node.atime = 546462546;
file->node.ctime = 323245342;
node = malloc(sizeof(Ecma119Node));
CU_ASSERT_PTR_NOT_NULL_FATAL(node);
node->node = (IsoNode*)file;
node->parent = (Ecma119Node*)0x55555555; /* just to make it not NULL */
node->info.file = NULL; /* it is not needed here */
node->info.file = NULL; /* it is not needed here */
node->type = ECMA119_FILE;
node->nlink = 1;
node->ino = 0x03447892;
/* Case 1. Name fit in System Use field */
file->node.name = "a small name.txt";
node->iso_name = "A_SMALL_.TXT";
memset(&susp, 0, sizeof(struct susp_info));
ret = rrip_get_susp_fields(&t, node, 0, 255 - 46, &susp);
CU_ASSERT_EQUAL(ret, 1);
@ -334,7 +334,7 @@ void test_rrip_get_susp_fields_file()
CU_ASSERT_EQUAL(susp.n_ce_susp_fields, 0);
CU_ASSERT_EQUAL(susp.n_susp_fields, 3); /* PX + TF + NM */
CU_ASSERT_EQUAL(susp.suf_len, 44 + (5 + 16) + (5 + 3*7) + 1);
/* PX is the first entry */
entry = susp.susp_fields[0];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -352,7 +352,7 @@ void test_rrip_get_susp_fields_file()
CU_ASSERT_EQUAL(iso_read_msb(entry + 32, 4), 654);
CU_ASSERT_EQUAL(iso_read_lsb(entry + 36, 4), 0x03447892);
CU_ASSERT_EQUAL(iso_read_msb(entry + 40, 4), 0x03447892);
/* TF is the second entry */
entry = susp.susp_fields[1];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -364,7 +364,7 @@ void test_rrip_get_susp_fields_file()
CU_ASSERT_EQUAL(iso_datetime_read_7(entry + 5), 675757578);
CU_ASSERT_EQUAL(iso_datetime_read_7(entry + 12), 546462546);
CU_ASSERT_EQUAL(iso_datetime_read_7(entry + 19), 323245342);
/* NM is the last entry */
entry = susp.susp_fields[2];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -374,24 +374,24 @@ void test_rrip_get_susp_fields_file()
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
CU_ASSERT_NSTRING_EQUAL(entry + 5, "a small name.txt", 16);
susp_info_free(&susp);
/* Case 2. Name fits exactly */
file->node.name = "a big name, with 133 characters, that it is the max "
"that fits in System Use field of the directory record "
"PADPADPADADPADPADPADPAD.txt";
node->iso_name = "A_BIG_NA.TXT";
memset(&susp, 0, sizeof(struct susp_info));
ret = rrip_get_susp_fields(&t, node, 0, 255 - 46, &susp);
CU_ASSERT_EQUAL(ret, 1);
CU_ASSERT_EQUAL(susp.ce_len, 0);
CU_ASSERT_EQUAL(susp.n_ce_susp_fields, 0);
CU_ASSERT_EQUAL(susp.suf_len, 254 - 46);
CU_ASSERT_EQUAL(susp.n_susp_fields, 3); /* PX + TF + NM */
/* NM is the last entry */
entry = susp.susp_fields[2];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -403,24 +403,24 @@ void test_rrip_get_susp_fields_file()
CU_ASSERT_NSTRING_EQUAL(entry + 5, "a big name, with 133 characters, that "
"it is the max that fits in System Use field of the "
"directory record PADPADPADADPADPADPADPAD.txt", 133);
susp_info_free(&susp);
/* case 3. A name just 1 character too big to fit in SUA */
file->node.name = "a big name, with 133 characters, that it is the max "
"that fits in System Use field of the directory record "
"PADPADPADADPADPADPADPAD1.txt";
node->iso_name = "A_BIG_NA.TXT";
memset(&susp, 0, sizeof(struct susp_info));
ret = rrip_get_susp_fields(&t, node, 0, 255 - 46, &susp);
CU_ASSERT_EQUAL(ret, 1);
CU_ASSERT_EQUAL(susp.ce_len, 28 + 5 + 1);
CU_ASSERT_EQUAL(susp.suf_len, 254 - 46);
CU_ASSERT_EQUAL(susp.n_susp_fields, 4); /* PX + TF + NM + CE */
CU_ASSERT_EQUAL(susp.n_ce_susp_fields, 1); /* NM */
/* test NM entry */
entry = susp.susp_fields[2];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -432,7 +432,7 @@ void test_rrip_get_susp_fields_file()
CU_ASSERT_NSTRING_EQUAL(entry + 5, "a big name, with 133 characters, that "
"it is the max that fits in System Use field of the "
"directory record", 105);
/* and CE entry */
entry = susp.susp_fields[3];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -446,7 +446,7 @@ void test_rrip_get_susp_fields_file()
CU_ASSERT_EQUAL(iso_read_msb(entry + 16, 4), 0);
CU_ASSERT_EQUAL(iso_read_lsb(entry + 20, 4), 34);
CU_ASSERT_EQUAL(iso_read_msb(entry + 24, 4), 34);
/* and check Continuation area */
entry = susp.ce_susp_fields[0];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -456,16 +456,16 @@ void test_rrip_get_susp_fields_file()
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
CU_ASSERT_NSTRING_EQUAL(entry + 5, " PADPADPADADPADPADPADPAD1.txt", 29);
susp_info_free(&susp);
/* case 4. A 255 characters name */
file->node.name = "a big name, with 255 characters, that it is the max "
"that a POSIX filename can have. PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP";
node->iso_name = "A_BIG_NA.TXT";
memset(&susp, 0, sizeof(struct susp_info));
susp.ce_block = 12;
susp.ce_len = 456;
@ -473,7 +473,7 @@ void test_rrip_get_susp_fields_file()
CU_ASSERT_EQUAL(ret, 1);
CU_ASSERT_EQUAL(susp.ce_len, 150 + 5 + 456);
CU_ASSERT_EQUAL(susp.suf_len, 254 - 46);
CU_ASSERT_EQUAL(susp.n_susp_fields, 4); /* PX + TF + NM + CE */
CU_ASSERT_EQUAL(susp.n_ce_susp_fields, 1); /* NM */
@ -488,7 +488,7 @@ void test_rrip_get_susp_fields_file()
CU_ASSERT_NSTRING_EQUAL(entry + 5, "a big name, with 255 characters, that "
"it is the max that a POSIX filename can have. PPP"
"PPPPPPPPPPPPPPPPPP", 105);
/* and CE entry */
entry = susp.susp_fields[3];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -517,9 +517,9 @@ void test_rrip_get_susp_fields_file()
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
"PPPPPPPPPPPPPP", 150);
susp_info_free(&susp);
free(node);
free(file);
}
@ -532,11 +532,11 @@ static void test_rrip_get_susp_fields_symlink()
int ret;
struct susp_info susp;
uint8_t *entry;
memset(&t, 0, sizeof(Ecma119Image));
t.input_charset = "UTF-8";
t.output_charset = "UTF-8";
link = malloc(sizeof(IsoSymlink));
CU_ASSERT_PTR_NOT_NULL_FATAL(link);
link->node.type = LIBISO_SYMLINK;
@ -546,7 +546,7 @@ static void test_rrip_get_susp_fields_symlink()
link->node.mtime = 675757578;
link->node.atime = 546462546;
link->node.ctime = 323245342;
node = malloc(sizeof(Ecma119Node));
CU_ASSERT_PTR_NOT_NULL_FATAL(node);
node->node = (IsoNode*)link;
@ -554,21 +554,21 @@ static void test_rrip_get_susp_fields_symlink()
node->type = ECMA119_SYMLINK;
node->nlink = 1;
node->ino = 0x03447892;
/* Case 1. Name and dest fit in System Use field */
link->node.name = "a small name.txt";
link->dest = "/three/components";
node->iso_name = "A_SMALL_.TXT";
memset(&susp, 0, sizeof(struct susp_info));
ret = rrip_get_susp_fields(&t, node, 0, 255 - 46, &susp);
CU_ASSERT_EQUAL(ret, 1);
CU_ASSERT_EQUAL(susp.ce_len, 0);
CU_ASSERT_EQUAL(susp.n_ce_susp_fields, 0);
CU_ASSERT_EQUAL(susp.n_susp_fields, 4); /* PX + TF + NM + SL */
CU_ASSERT_EQUAL(susp.suf_len, 44 + (5 + 16) + (5 + 3*7) + 1
CU_ASSERT_EQUAL(susp.suf_len, 44 + (5 + 16) + (5 + 3*7) + 1
+ (5 + 2 + (2 + 5) + (2 + 10)));
/* PX is the first entry */
entry = susp.susp_fields[0];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -586,7 +586,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(iso_read_msb(entry + 32, 4), 654);
CU_ASSERT_EQUAL(iso_read_lsb(entry + 36, 4), 0x03447892);
CU_ASSERT_EQUAL(iso_read_msb(entry + 40, 4), 0x03447892);
/* TF is the second entry */
entry = susp.susp_fields[1];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -598,7 +598,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(iso_datetime_read_7(entry + 5), 675757578);
CU_ASSERT_EQUAL(iso_datetime_read_7(entry + 12), 546462546);
CU_ASSERT_EQUAL(iso_datetime_read_7(entry + 19), 323245342);
/* NM is the 3rd entry */
entry = susp.susp_fields[2];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -617,7 +617,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[2], 5 + 2 + (2 + 5) + (2 + 10));
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
/* first component */
CU_ASSERT_EQUAL(entry[5], 0x8); /* root */
CU_ASSERT_EQUAL(entry[6], 0);
@ -626,14 +626,14 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[7], 0);
CU_ASSERT_EQUAL(entry[8], 5);
CU_ASSERT_NSTRING_EQUAL(entry + 9, "three", 5);
/* 3rd component */
CU_ASSERT_EQUAL(entry[14], 0);
CU_ASSERT_EQUAL(entry[15], 10);
CU_ASSERT_NSTRING_EQUAL(entry + 16, "components", 10);
susp_info_free(&susp);
/* case 2. name + dest fits exactly */
link->node.name = "this name will have 74 characters as it is the max "
"that fits in the SU.txt";
@ -647,7 +647,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(susp.n_ce_susp_fields, 0);
CU_ASSERT_EQUAL(susp.n_susp_fields, 4); /* PX + TF + NM + SL */
CU_ASSERT_EQUAL(susp.suf_len, 254 - 46);
/* NM is the 3rd entry */
entry = susp.susp_fields[2];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -667,7 +667,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[2], 5 + 2 + 5 + 2 + 3 + 2 + 5 + 13 + 6 + 4 + 12);
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
/* first component */
CU_ASSERT_EQUAL(entry[5], 0x2); /* current */
CU_ASSERT_EQUAL(entry[6], 0);
@ -676,7 +676,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[7], 0);
CU_ASSERT_EQUAL(entry[8], 3);
CU_ASSERT_NSTRING_EQUAL(entry + 9, "and", 3);
/* 3rd component */
CU_ASSERT_EQUAL(entry[12], 0x4); /* parent */
CU_ASSERT_EQUAL(entry[13], 0);
@ -685,7 +685,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[14], 0);
CU_ASSERT_EQUAL(entry[15], 1);
CU_ASSERT_EQUAL(entry[16], 'a');
/* 5th component */
CU_ASSERT_EQUAL(entry[17], 0x2); /* current */
CU_ASSERT_EQUAL(entry[18], 0);
@ -716,7 +716,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_NSTRING_EQUAL(entry + 49, "components", 10);
susp_info_free(&susp);
/* case 3. name fits, dest is one byte larger to fit */
/* 3.a extra byte in dest */
link->node.name = "this name will have 74 characters as it is the max "
@ -738,7 +738,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[0], 'P');
CU_ASSERT_EQUAL(entry[1], 'X');
CU_ASSERT_EQUAL(entry[2], 44);
/* TF is the second entry */
entry = susp.susp_fields[1];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -770,7 +770,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(iso_read_msb(entry + 16, 4), 0);
CU_ASSERT_EQUAL(iso_read_lsb(entry + 20, 4), 60);
CU_ASSERT_EQUAL(iso_read_msb(entry + 24, 4), 60);
/* finally, SL is the single entry in CE */
entry = susp.ce_susp_fields[0];
@ -780,7 +780,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[2], 60);
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
/* first component */
CU_ASSERT_EQUAL(entry[5], 0x2); /* current */
CU_ASSERT_EQUAL(entry[6], 0);
@ -789,7 +789,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[7], 0);
CU_ASSERT_EQUAL(entry[8], 3);
CU_ASSERT_NSTRING_EQUAL(entry + 9, "and", 3);
/* 3rd component */
CU_ASSERT_EQUAL(entry[12], 0x4); /* parent */
CU_ASSERT_EQUAL(entry[13], 0);
@ -798,7 +798,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[14], 0);
CU_ASSERT_EQUAL(entry[15], 1);
CU_ASSERT_EQUAL(entry[16], 'a');
/* 5th component */
CU_ASSERT_EQUAL(entry[17], 0x2); /* current */
CU_ASSERT_EQUAL(entry[18], 0);
@ -827,7 +827,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[47], 0);
CU_ASSERT_EQUAL(entry[48], 11);
CU_ASSERT_NSTRING_EQUAL(entry + 49, "componentsk", 11);
susp_info_free(&susp);
/* 3.b extra byte in name */
@ -868,7 +868,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(iso_read_msb(entry + 16, 4), 0);
CU_ASSERT_EQUAL(iso_read_lsb(entry + 20, 4), 59);
CU_ASSERT_EQUAL(iso_read_msb(entry + 24, 4), 59);
/* finally, SL is the single entry in CE */
entry = susp.ce_susp_fields[0];
@ -878,7 +878,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[2], 59);
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
/* first component */
CU_ASSERT_EQUAL(entry[5], 0x2); /* current */
CU_ASSERT_EQUAL(entry[6], 0);
@ -887,7 +887,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[7], 0);
CU_ASSERT_EQUAL(entry[8], 3);
CU_ASSERT_NSTRING_EQUAL(entry + 9, "and", 3);
/* 3rd component */
CU_ASSERT_EQUAL(entry[12], 0x4); /* parent */
CU_ASSERT_EQUAL(entry[13], 0);
@ -896,7 +896,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[14], 0);
CU_ASSERT_EQUAL(entry[15], 1);
CU_ASSERT_EQUAL(entry[16], 'a');
/* 5th component */
CU_ASSERT_EQUAL(entry[17], 0x2); /* current */
CU_ASSERT_EQUAL(entry[18], 0);
@ -925,12 +925,12 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[47], 0);
CU_ASSERT_EQUAL(entry[48], 10);
CU_ASSERT_NSTRING_EQUAL(entry + 49, "components", 10);
susp_info_free(&susp);
/* case 4. name seems to fit, but SL no, and when CE is added NM
/* case 4. name seems to fit, but SL no, and when CE is added NM
* doesn't fit too */
/* 4.a it just fits */
/* 4.a it just fits */
link->node.name = "this name will have 105 characters as it is just the "
"max that fits in the SU once we add the CE entry.txt";
link->dest = "./and/../a/./big/destination/with/10/components";
@ -978,7 +978,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[2], 59);
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
/* first component */
CU_ASSERT_EQUAL(entry[5], 0x2); /* current */
CU_ASSERT_EQUAL(entry[6], 0);
@ -987,7 +987,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[7], 0);
CU_ASSERT_EQUAL(entry[8], 3);
CU_ASSERT_NSTRING_EQUAL(entry + 9, "and", 3);
/* 3rd component */
CU_ASSERT_EQUAL(entry[12], 0x4); /* parent */
CU_ASSERT_EQUAL(entry[13], 0);
@ -996,7 +996,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[14], 0);
CU_ASSERT_EQUAL(entry[15], 1);
CU_ASSERT_EQUAL(entry[16], 'a');
/* 5th component */
CU_ASSERT_EQUAL(entry[17], 0x2); /* current */
CU_ASSERT_EQUAL(entry[18], 0);
@ -1025,10 +1025,10 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[47], 0);
CU_ASSERT_EQUAL(entry[48], 10);
CU_ASSERT_NSTRING_EQUAL(entry + 49, "components", 10);
susp_info_free(&susp);
/* 4.b it just fits, the the component ends in '/' */
/* 4.b it just fits, the the component ends in '/' */
link->node.name = "this name will have 105 characters as it is just the "
"max that fits in the SU once we add the CE entry.txt";
link->dest = "./and/../a/./big/destination/with/10/components/";
@ -1076,7 +1076,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[2], 59);
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
/* first component */
CU_ASSERT_EQUAL(entry[5], 0x2); /* current */
CU_ASSERT_EQUAL(entry[6], 0);
@ -1085,7 +1085,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[7], 0);
CU_ASSERT_EQUAL(entry[8], 3);
CU_ASSERT_NSTRING_EQUAL(entry + 9, "and", 3);
/* 3rd component */
CU_ASSERT_EQUAL(entry[12], 0x4); /* parent */
CU_ASSERT_EQUAL(entry[13], 0);
@ -1094,7 +1094,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[14], 0);
CU_ASSERT_EQUAL(entry[15], 1);
CU_ASSERT_EQUAL(entry[16], 'a');
/* 5th component */
CU_ASSERT_EQUAL(entry[17], 0x2); /* current */
CU_ASSERT_EQUAL(entry[18], 0);
@ -1123,10 +1123,10 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[47], 0);
CU_ASSERT_EQUAL(entry[48], 10);
CU_ASSERT_NSTRING_EQUAL(entry + 49, "components", 10);
susp_info_free(&susp);
/* 4.c extra char in name, that forces it to be divided */
/* 4.c extra char in name, that forces it to be divided */
link->node.name = "this name will have 106 characters as it is just the "
"max that fits in the SU once we add the CE entryc.txt";
link->dest = "./and/../a/./big/destination/with/10/components";
@ -1175,7 +1175,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
CU_ASSERT_EQUAL(entry[5], 't');
/* finally, SL is the single entry in CE */
entry = susp.ce_susp_fields[1];
CU_ASSERT_PTR_NOT_NULL(entry);
@ -1184,7 +1184,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[2], 59);
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
/* first component */
CU_ASSERT_EQUAL(entry[5], 0x2); /* current */
CU_ASSERT_EQUAL(entry[6], 0);
@ -1193,7 +1193,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[7], 0);
CU_ASSERT_EQUAL(entry[8], 3);
CU_ASSERT_NSTRING_EQUAL(entry + 9, "and", 3);
/* 3rd component */
CU_ASSERT_EQUAL(entry[12], 0x4); /* parent */
CU_ASSERT_EQUAL(entry[13], 0);
@ -1202,7 +1202,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[14], 0);
CU_ASSERT_EQUAL(entry[15], 1);
CU_ASSERT_EQUAL(entry[16], 'a');
/* 5th component */
CU_ASSERT_EQUAL(entry[17], 0x2); /* current */
CU_ASSERT_EQUAL(entry[18], 0);
@ -1231,9 +1231,9 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[47], 0);
CU_ASSERT_EQUAL(entry[48], 10);
CU_ASSERT_NSTRING_EQUAL(entry + 49, "components", 10);
susp_info_free(&susp);
/* 5 max destination length to fit in a single SL entry (250) */
link->node.name = "this name will have 74 characters as it is the max "
"that fits in the SU.txt";
@ -1259,7 +1259,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[2], 255);
CU_ASSERT_EQUAL(entry[3], 1);
CU_ASSERT_EQUAL(entry[4], 0);
/* first component */
CU_ASSERT_EQUAL(entry[5], 0x2); /* current */
CU_ASSERT_EQUAL(entry[6], 0);
@ -1268,7 +1268,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[7], 0);
CU_ASSERT_EQUAL(entry[8], 3);
CU_ASSERT_NSTRING_EQUAL(entry + 9, "and", 3);
/* 3rd component */
CU_ASSERT_EQUAL(entry[12], 0x4); /* parent */
CU_ASSERT_EQUAL(entry[13], 0);
@ -1277,7 +1277,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[14], 0);
CU_ASSERT_EQUAL(entry[15], 1);
CU_ASSERT_EQUAL(entry[16], 'a');
/* 5th component */
CU_ASSERT_EQUAL(entry[17], 0x2); /* current */
CU_ASSERT_EQUAL(entry[18], 0);
@ -1301,7 +1301,7 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[43], 0);
CU_ASSERT_EQUAL(entry[44], 4);
CU_ASSERT_NSTRING_EQUAL(entry + 45, "with", 4);
/* 10th component */
CU_ASSERT_EQUAL(entry[49], 0);
CU_ASSERT_EQUAL(entry[50], 2);
@ -1316,59 +1316,59 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_EQUAL(entry[65], 0);
CU_ASSERT_EQUAL(entry[66], 4);
CU_ASSERT_NSTRING_EQUAL(entry + 67, "that", 4);
/* 13th component */
CU_ASSERT_EQUAL(entry[71], 0);
CU_ASSERT_EQUAL(entry[72], 8);
CU_ASSERT_NSTRING_EQUAL(entry + 73, "conforms", 8);
/* 14th component */
CU_ASSERT_EQUAL(entry[81], 0);
CU_ASSERT_EQUAL(entry[82], 3);
CU_ASSERT_NSTRING_EQUAL(entry + 83, "the", 3);
/* 15th component */
CU_ASSERT_EQUAL(entry[86], 0);
CU_ASSERT_EQUAL(entry[87], 3);
CU_ASSERT_NSTRING_EQUAL(entry + 88, "max", 3);
/* 16th component */
CU_ASSERT_EQUAL(entry[91], 0);
CU_ASSERT_EQUAL(entry[92], 4);
CU_ASSERT_NSTRING_EQUAL(entry + 93, "that", 4);
/* 17th component */
CU_ASSERT_EQUAL(entry[97], 0);
CU_ASSERT_EQUAL(entry[98], 4);
CU_ASSERT_NSTRING_EQUAL(entry + 99, "fits", 4);
/* 18th component */
CU_ASSERT_EQUAL(entry[103], 0);
CU_ASSERT_EQUAL(entry[104], 2);
CU_ASSERT_NSTRING_EQUAL(entry + 105, "in", 2);
/* 19th component */
CU_ASSERT_EQUAL(entry[107], 0);
CU_ASSERT_EQUAL(entry[108], 11);
CU_ASSERT_NSTRING_EQUAL(entry + 109, "a single SL", 11);
/* 20th component */
CU_ASSERT_EQUAL(entry[120], 0);
CU_ASSERT_EQUAL(entry[121], 38);
CU_ASSERT_NSTRING_EQUAL(entry + 122, "entry as it takes "
"just two hundred and", 38);
/* 21th component */
CU_ASSERT_EQUAL(entry[160], 0);
CU_ASSERT_EQUAL(entry[161], 29);
CU_ASSERT_NSTRING_EQUAL(entry + 162, "fifty bytes bytes bytes bytes", 29);
/* 22th component */
CU_ASSERT_EQUAL(entry[191], 0);
CU_ASSERT_EQUAL(entry[192], 53);
CU_ASSERT_NSTRING_EQUAL(entry + 193, "bytes bytes bytes bytes bytes bytes"
" bytes bytes bytes", 53);
/* 23th component */
CU_ASSERT_EQUAL(entry[246], 0x4); /* parent */
CU_ASSERT_EQUAL(entry[247], 0);
@ -1379,15 +1379,15 @@ static void test_rrip_get_susp_fields_symlink()
CU_ASSERT_NSTRING_EQUAL(entry + 250, "bytes", 5);
susp_info_free(&susp);
free(node);
free(link);
}
void add_rockridge_suite()
void add_rockridge_suite()
{
CU_pSuite pSuite = CU_add_suite("RockRidge Suite", NULL, NULL);
CU_add_test(pSuite, "rrip_calc_len(file)", test_rrip_calc_len_file);
CU_add_test(pSuite, "rrip_calc_len(symlink)", test_rrip_calc_len_symlink);
CU_add_test(pSuite, "rrip_get_susp_fields(file)", test_rrip_get_susp_fields_file);