Merge level3 branch, adding support for ISO-9660 Level 3.
This commit is contained in:
commit
c1a7702f52
@ -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);
|
||||
|
58
doc/devel/cookbook/Multi-Extent.txt
Normal file
58
doc/devel/cookbook/Multi-Extent.txt
Normal 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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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 "
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
*
|
||||
|
246
libisofs/node.c
246
libisofs/node.c
@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See COPYING file for details.
|
||||
*/
|
||||
|
||||
@ -16,12 +16,12 @@
|
||||
#include <limits.h>
|
||||
|
||||
struct dir_iter_data
|
||||
{
|
||||
{
|
||||
/* points to the last visited child, to NULL before start */
|
||||
IsoNode *pos;
|
||||
|
||||
|
||||
/* Some control flags.
|
||||
* bit 0 -> 1 if next called, 0 reseted at start or on deletion
|
||||
* bit 0 -> 1 if next called, 0 reseted at start or on deletion
|
||||
*/
|
||||
int flag;
|
||||
};
|
||||
@ -74,7 +74,7 @@ void iso_node_unref(IsoNode *node)
|
||||
IsoExtendedInfo *info = node->xinfo;
|
||||
while (info != NULL) {
|
||||
IsoExtendedInfo *tmp = info->next;
|
||||
|
||||
|
||||
/* free extended info */
|
||||
info->process(info->data, 1);
|
||||
free(info);
|
||||
@ -87,17 +87,17 @@ void iso_node_unref(IsoNode *node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extended information to the given node. Extended info allows
|
||||
* Add extended information to the given node. Extended info allows
|
||||
* applications (and libisofs itself) to add more information to an IsoNode.
|
||||
* You can use this facilities to associate new information with a given
|
||||
* node.
|
||||
*
|
||||
*
|
||||
* Each node keeps a list of added extended info, meaning you can add several
|
||||
* extended info data to each node. Each extended info you add is identified
|
||||
* by the proc parameter, a pointer to a function that knows how to manage
|
||||
* the external info data. Thus, in order to add several types of extended
|
||||
* info, you need to define a "proc" function for each type.
|
||||
*
|
||||
*
|
||||
* @param node
|
||||
* The node where to add the extended info
|
||||
* @param proc
|
||||
@ -125,7 +125,7 @@ int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data)
|
||||
}
|
||||
pos = pos->next;
|
||||
}
|
||||
|
||||
|
||||
info = malloc(sizeof(IsoExtendedInfo));
|
||||
if (info == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
@ -140,8 +140,8 @@ int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data)
|
||||
/**
|
||||
* Remove the given extended info (defined by the proc function) from the
|
||||
* given node.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @return
|
||||
* 1 on success, 0 if node does not have extended info of the requested
|
||||
* type, < 0 on error
|
||||
*/
|
||||
@ -152,14 +152,14 @@ int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc)
|
||||
if (node == NULL || proc == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
|
||||
prev = NULL;
|
||||
pos = node->xinfo;
|
||||
while (pos != NULL) {
|
||||
if (pos->process == proc) {
|
||||
/* this is the extended info we want to remove */
|
||||
pos->process(pos->data, 1);
|
||||
|
||||
|
||||
if (prev != NULL) {
|
||||
prev->next = pos->next;
|
||||
} else {
|
||||
@ -172,17 +172,17 @@ int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc)
|
||||
pos = pos->next;
|
||||
}
|
||||
/* requested xinfo not found */
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the given extended info (defined by the proc function) from the
|
||||
* given node.
|
||||
*
|
||||
*
|
||||
* @param data
|
||||
* Will be filled with the extended info corresponding to the given proc
|
||||
* function
|
||||
* @return
|
||||
* @return
|
||||
* 1 on success, 0 if node does not have extended info of the requested
|
||||
* type, < 0 on error
|
||||
*/
|
||||
@ -193,7 +193,7 @@ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
|
||||
if (node == NULL || proc == NULL || data == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
|
||||
pos = node->xinfo;
|
||||
while (pos != NULL) {
|
||||
if (pos->process == proc) {
|
||||
@ -204,7 +204,7 @@ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
|
||||
pos = pos->next;
|
||||
}
|
||||
/* requested xinfo not found */
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,7 +217,7 @@ enum IsoNodeType iso_node_get_type(IsoNode *node)
|
||||
|
||||
/**
|
||||
* Set the name of a node.
|
||||
*
|
||||
*
|
||||
* @param name The name in UTF-8 encoding
|
||||
*/
|
||||
int iso_node_set_name(IsoNode *node, const char *name)
|
||||
@ -228,7 +228,7 @@ int iso_node_set_name(IsoNode *node, const char *name)
|
||||
/* you can't change name of the root node */
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
|
||||
|
||||
/* check if the name is valid */
|
||||
if (!iso_node_is_valid_name(name)) {
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
@ -272,10 +272,10 @@ const char *iso_node_get_name(const IsoNode *node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the permissions for the node. This attribute is only useful when
|
||||
* Set the permissions for the node. This attribute is only useful when
|
||||
* Rock Ridge extensions are enabled.
|
||||
*
|
||||
* @param mode
|
||||
*
|
||||
* @param mode
|
||||
* bitmask with the permissions of the node, as specified in 'man 2 stat'.
|
||||
* The file type bitfields will be ignored, only file permissions will be
|
||||
* modified.
|
||||
@ -285,15 +285,15 @@ void iso_node_set_permissions(IsoNode *node, mode_t mode)
|
||||
node->mode = (node->mode & S_IFMT) | (mode & ~S_IFMT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the permissions for the node
|
||||
/**
|
||||
* Get the permissions for the node
|
||||
*/
|
||||
mode_t iso_node_get_permissions(const IsoNode *node)
|
||||
{
|
||||
return node->mode & ~S_IFMT;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Get the mode of the node, both permissions and file type, as specified in
|
||||
* 'man 2 stat'.
|
||||
*/
|
||||
@ -303,7 +303,7 @@ mode_t iso_node_get_mode(const IsoNode *node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user id for the node. This attribute is only useful when
|
||||
* Set the user id for the node. This attribute is only useful when
|
||||
* Rock Ridge extensions are enabled.
|
||||
*/
|
||||
void iso_node_set_uid(IsoNode *node, uid_t uid)
|
||||
@ -320,7 +320,7 @@ uid_t iso_node_get_uid(const IsoNode *node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the group id for the node. This attribute is only useful when
|
||||
* Set the group id for the node. This attribute is only useful when
|
||||
* Rock Ridge extensions are enabled.
|
||||
*/
|
||||
void iso_node_set_gid(IsoNode *node, gid_t gid)
|
||||
@ -336,7 +336,7 @@ gid_t iso_node_get_gid(const IsoNode *node)
|
||||
return node->gid;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Set the time of last modification of the file
|
||||
*/
|
||||
void iso_node_set_mtime(IsoNode *node, time_t time)
|
||||
@ -344,7 +344,7 @@ void iso_node_set_mtime(IsoNode *node, time_t time)
|
||||
node->mtime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Get the time of last modification of the file
|
||||
*/
|
||||
time_t iso_node_get_mtime(const IsoNode *node)
|
||||
@ -352,7 +352,7 @@ time_t iso_node_get_mtime(const IsoNode *node)
|
||||
return node->mtime;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Set the time of last access to the file
|
||||
*/
|
||||
void iso_node_set_atime(IsoNode *node, time_t time)
|
||||
@ -360,24 +360,24 @@ void iso_node_set_atime(IsoNode *node, time_t time)
|
||||
node->atime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time of last access to the file
|
||||
/**
|
||||
* Get the time of last access to the file
|
||||
*/
|
||||
time_t iso_node_get_atime(const IsoNode *node)
|
||||
{
|
||||
return node->atime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time of last status change of the file
|
||||
/**
|
||||
* Set the time of last status change of the file
|
||||
*/
|
||||
void iso_node_set_ctime(IsoNode *node, time_t time)
|
||||
{
|
||||
node->ctime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time of last status change of the file
|
||||
/**
|
||||
* Get the time of last status change of the file
|
||||
*/
|
||||
time_t iso_node_get_ctime(const IsoNode *node)
|
||||
{
|
||||
@ -397,21 +397,21 @@ void iso_node_set_hidden(IsoNode *node, int hide_attrs)
|
||||
* the node, so you don't need to free it, it will be automatically freed
|
||||
* when the dir is deleted. Of course, if you want to keep using the node
|
||||
* after the dir life, you need to iso_node_ref() it.
|
||||
*
|
||||
* @param dir
|
||||
*
|
||||
* @param dir
|
||||
* the dir where to add the node
|
||||
* @param child
|
||||
* @param child
|
||||
* the node to add. You must ensure that the node hasn't previously added
|
||||
* to other dir, and that the node name is unique inside the child.
|
||||
* Otherwise this function will return a failure, and the child won't be
|
||||
* inserted.
|
||||
* @param replace
|
||||
* if the dir already contains a node with the same name, whether to
|
||||
* replace or not the old node with this.
|
||||
* replace or not the old node with this.
|
||||
* @return
|
||||
* number of nodes in dir if succes, < 0 otherwise
|
||||
*/
|
||||
int iso_dir_add_node(IsoDir *dir, IsoNode *child,
|
||||
int iso_dir_add_node(IsoDir *dir, IsoNode *child,
|
||||
enum iso_replace_mode replace)
|
||||
{
|
||||
IsoNode **pos;
|
||||
@ -423,7 +423,7 @@ int iso_dir_add_node(IsoDir *dir, IsoNode *child,
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* check if child is already added to another dir, or if child
|
||||
* is the root node, where parent == itself
|
||||
*/
|
||||
@ -437,17 +437,17 @@ int iso_dir_add_node(IsoDir *dir, IsoNode *child,
|
||||
|
||||
/**
|
||||
* Locate a node inside a given dir.
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* The name of the node
|
||||
* @param node
|
||||
* Location for a pointer to the node, it will filled with NULL if the dir
|
||||
* Location for a pointer to the node, it will filled with NULL if the dir
|
||||
* doesn't have a child with the given name.
|
||||
* The node will be owned by the dir and shouldn't be unref(). Just call
|
||||
* iso_node_ref() to get your own reference to the node.
|
||||
* Note that you can pass NULL is the only thing you want to do is check
|
||||
* if a node with such name already exists on dir.
|
||||
* @return
|
||||
* @return
|
||||
* 1 node found, 0 child has no such node, < 0 error
|
||||
* Possible errors:
|
||||
* ISO_NULL_POINTER, if dir or name are NULL
|
||||
@ -476,7 +476,7 @@ int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node)
|
||||
|
||||
/**
|
||||
* Get the number of children of a directory.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* >= 0 number of items, < 0 error
|
||||
* Possible errors:
|
||||
@ -497,12 +497,12 @@ int iter_next(IsoDirIter *iter, IsoNode **node)
|
||||
if (iter == NULL || node == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
|
||||
data = iter->data;
|
||||
|
||||
|
||||
/* clear next flag */
|
||||
data->flag &= ~0x01;
|
||||
|
||||
|
||||
if (data->pos == NULL) {
|
||||
/* we are at the beginning */
|
||||
data->pos = iter->dir->children;
|
||||
@ -529,12 +529,12 @@ int iter_next(IsoDirIter *iter, IsoNode **node)
|
||||
data->pos = data->pos->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ok, take a ref to the current position, to prevent internal errors
|
||||
* if deleted somewhere */
|
||||
iso_node_ref(data->pos);
|
||||
data->flag |= 0x01; /* set next flag */
|
||||
|
||||
|
||||
/* return pointed node */
|
||||
*node = data->pos;
|
||||
return ISO_SUCCESS;
|
||||
@ -542,7 +542,7 @@ int iter_next(IsoDirIter *iter, IsoNode **node)
|
||||
|
||||
/**
|
||||
* Check if there're more children.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* 1 dir has more elements, 0 no, < 0 error
|
||||
* Possible errors:
|
||||
@ -589,8 +589,8 @@ static IsoNode** iso_dir_find_node(IsoDir *dir, IsoNode *node)
|
||||
* The child is not freed, so you will become the owner of the node. Later
|
||||
* you can add the node to another dir (calling iso_dir_add_node), or free
|
||||
* it if you don't need it (with iso_node_unref).
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @return
|
||||
* 1 on success, < 0 error
|
||||
*/
|
||||
int iso_node_take(IsoNode *node)
|
||||
@ -610,10 +610,10 @@ int iso_node_take(IsoNode *node)
|
||||
/* should never occur */
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/* notify iterators just before remove */
|
||||
iso_notify_dir_iters(node, 0);
|
||||
|
||||
iso_notify_dir_iters(node, 0);
|
||||
|
||||
*pos = node->next;
|
||||
node->parent = NULL;
|
||||
node->next = NULL;
|
||||
@ -626,8 +626,8 @@ int iso_node_take(IsoNode *node)
|
||||
* If you want to keep the child alive, you need to iso_node_ref() it
|
||||
* before this call, but in that case iso_node_take() is a better
|
||||
* alternative.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @return
|
||||
* 1 on success, < 0 error
|
||||
*/
|
||||
int iso_node_remove(IsoNode *node)
|
||||
@ -644,10 +644,10 @@ int iso_node_remove(IsoNode *node)
|
||||
* Get the parent of the given iso tree node. No extra ref is added to the
|
||||
* returned directory, you must take your ref. with iso_node_ref() if you
|
||||
* need it.
|
||||
*
|
||||
*
|
||||
* If node is the root node, the same node will be returned as its parent.
|
||||
*
|
||||
* This returns NULL if the node doesn't pertain to any tree
|
||||
*
|
||||
* This returns NULL if the node doesn't pertain to any tree
|
||||
* (it was removed/take).
|
||||
*/
|
||||
IsoDir *iso_node_get_parent(IsoNode *node)
|
||||
@ -663,20 +663,20 @@ int iter_take(IsoDirIter *iter)
|
||||
if (iter == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
|
||||
data = iter->data;
|
||||
|
||||
|
||||
if (!(data->flag & 0x01)) {
|
||||
return ISO_ERROR; /* next not called or end of dir */
|
||||
}
|
||||
|
||||
|
||||
if (data->pos == NULL) {
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/* clear next flag */
|
||||
data->flag &= ~0x01;
|
||||
|
||||
|
||||
return iso_node_take(data->pos);
|
||||
}
|
||||
|
||||
@ -686,13 +686,13 @@ int iter_remove(IsoDirIter *iter)
|
||||
int ret;
|
||||
IsoNode *pos;
|
||||
struct dir_iter_data *data;
|
||||
|
||||
|
||||
if (iter == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
data = iter->data;
|
||||
pos = data->pos;
|
||||
|
||||
|
||||
ret = iter_take(iter);
|
||||
if (ret == ISO_SUCCESS) {
|
||||
/* remove node */
|
||||
@ -706,8 +706,8 @@ void iter_notify_child_taken(IsoDirIter *iter, IsoNode *node)
|
||||
IsoNode *pos, *pre;
|
||||
struct dir_iter_data *data;
|
||||
data = iter->data;
|
||||
|
||||
if (data->pos == node) {
|
||||
|
||||
if (data->pos == node) {
|
||||
pos = iter->dir->children;
|
||||
pre = NULL;
|
||||
while (pos != NULL && pos != data->pos) {
|
||||
@ -717,10 +717,10 @@ void iter_notify_child_taken(IsoDirIter *iter, IsoNode *node)
|
||||
if (pos == NULL || pos != data->pos) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* dispose iterator reference */
|
||||
iso_node_unref(data->pos);
|
||||
|
||||
|
||||
if (pre == NULL) {
|
||||
/* node is a first position */
|
||||
iter->dir->children = pos->next;
|
||||
@ -766,7 +766,7 @@ int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter)
|
||||
data->pos = NULL;
|
||||
data->flag = 0x00;
|
||||
it->data = data;
|
||||
|
||||
|
||||
if (iso_dir_iter_register(it) < 0) {
|
||||
free(it);
|
||||
return ISO_OUT_OF_MEM;
|
||||
@ -808,7 +808,7 @@ int iso_dir_iter_take(IsoDirIter *iter)
|
||||
if (iter == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
return iter->class->take(iter);
|
||||
return iter->class->take(iter);
|
||||
}
|
||||
|
||||
int iso_dir_iter_remove(IsoDirIter *iter)
|
||||
@ -816,7 +816,7 @@ int iso_dir_iter_remove(IsoDirIter *iter)
|
||||
if (iter == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
return iter->class->remove(iter);
|
||||
return iter->class->remove(iter);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -851,13 +851,13 @@ int iso_symlink_set_dest(IsoSymlink *link, const char *dest)
|
||||
/**
|
||||
* Sets the order in which a node will be written on image. High weihted files
|
||||
* will be written first, so in a disc them will be written near the center.
|
||||
*
|
||||
* @param node
|
||||
* The node which weight will be changed. If it's a dir, this function
|
||||
* will change the weight of all its children. For nodes other that dirs
|
||||
*
|
||||
* @param node
|
||||
* The node which weight will be changed. If it's a dir, this function
|
||||
* will change the weight of all its children. For nodes other that dirs
|
||||
* or regular files, this function has no effect.
|
||||
* @param w
|
||||
* The weight as a integer number, the greater this value is, the
|
||||
* @param w
|
||||
* The weight as a integer number, the greater this value is, the
|
||||
* closer from the begining of image the file will be written.
|
||||
*/
|
||||
void iso_node_set_sort_weight(IsoNode *node, int w)
|
||||
@ -881,8 +881,8 @@ int iso_file_get_sort_weight(IsoFile *file)
|
||||
return file->sort_weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the file, in bytes
|
||||
/**
|
||||
* Get the size of the file, in bytes
|
||||
*/
|
||||
off_t iso_file_get_size(IsoFile *file)
|
||||
{
|
||||
@ -891,9 +891,9 @@ off_t iso_file_get_size(IsoFile *file)
|
||||
|
||||
/**
|
||||
* Get the IsoStream that represents the contents of the given IsoFile.
|
||||
*
|
||||
*
|
||||
* If you open() the stream, it should be close() before image generation.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* The IsoStream. No extra ref is added, so the IsoStream belong to the
|
||||
* IsoFile, and it may be freed together with it. Add your own ref with
|
||||
@ -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, §ion_count, §ions, flag);
|
||||
if (ret <= 0) {
|
||||
return ret;
|
||||
}
|
||||
if (section_count != 1) {
|
||||
free(sections);
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
if (file->msblock != 0) {
|
||||
*lba = file->msblock;
|
||||
return 1;
|
||||
}
|
||||
*lba = sections[0].block;
|
||||
free(sections);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Like iso_file_get_old_image_lba(), but take an IsoNode.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* 1 if lba is valid (file comes from old image), 0 if file was newly
|
||||
* added, i.e. it does not come from an old image, 2 node type has no
|
||||
* added, i.e. it does not come from an old image, 2 node type has no
|
||||
* LBA (no regular file), < 0 error
|
||||
*
|
||||
* @since 0.6.4
|
||||
@ -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;
|
||||
|
111
libisofs/node.h
111
libisofs/node.h
@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See COPYING file for details.
|
||||
*/
|
||||
#ifndef LIBISO_NODE_H_
|
||||
@ -22,12 +22,12 @@
|
||||
|
||||
/**
|
||||
* The extended information is a way to attach additional information to each
|
||||
* IsoNode. External applications may want to use this extension system to
|
||||
* IsoNode. External applications may want to use this extension system to
|
||||
* store application speficic information related to each node. On the other
|
||||
* side, libisofs may make use of this struct to attach information to nodes in
|
||||
* some particular, uncommon, cases, without incrementing the size of the
|
||||
* IsoNode struct.
|
||||
*
|
||||
*
|
||||
* It is implemented like a chained list.
|
||||
*/
|
||||
typedef struct iso_extended_info IsoExtendedInfo;
|
||||
@ -37,23 +37,23 @@ struct iso_extended_info {
|
||||
* Next struct in the chain. NULL if it is the last item
|
||||
*/
|
||||
IsoExtendedInfo *next;
|
||||
|
||||
|
||||
/**
|
||||
* Function to handle this particular extended information. The function
|
||||
* pointer acts as an identifier for the type of the information. Structs
|
||||
* with same information type must use the same function.
|
||||
*
|
||||
*
|
||||
* @param data
|
||||
* Attached data
|
||||
* @param flag
|
||||
* What to do with the data. At this time the following values are
|
||||
* What to do with the data. At this time the following values are
|
||||
* defined:
|
||||
* -> 1 the data must be freed
|
||||
* @return
|
||||
* 1
|
||||
*/
|
||||
iso_node_xinfo_func process;
|
||||
|
||||
|
||||
/**
|
||||
* Pointer to information specific data.
|
||||
*/
|
||||
@ -61,15 +61,15 @@ struct iso_extended_info {
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct Iso_Node
|
||||
{
|
||||
/*
|
||||
* Initilized to 1, originally owned by user, until added to another node.
|
||||
* Then it is owned by the parent node, so the user must take his own ref
|
||||
* Then it is owned by the parent node, so the user must take his own ref
|
||||
* if needed. With the exception of the creation functions, none of the
|
||||
* other libisofs functions that return an IsoNode increment its
|
||||
* other libisofs functions that return an IsoNode increment its
|
||||
* refcount. This is responsablity of the client, if (s)he needs it.
|
||||
*/
|
||||
int refcount;
|
||||
@ -115,14 +115,11 @@ struct Iso_File
|
||||
{
|
||||
IsoNode node;
|
||||
|
||||
/**
|
||||
* Location of a file extent in a ms disc, 0 for newly added file
|
||||
*/
|
||||
uint32_t msblock;
|
||||
unsigned int from_old_session : 1;
|
||||
|
||||
/**
|
||||
/**
|
||||
* It sorts the order in which the file data is written to the CD image.
|
||||
* Higher weighting files are written at the beginning of image
|
||||
* Higher weighting files are written at the beginning of image
|
||||
*/
|
||||
int sort_weight;
|
||||
IsoStream *stream;
|
||||
@ -143,18 +140,18 @@ struct Iso_Special
|
||||
|
||||
struct iso_dir_iter_iface
|
||||
{
|
||||
|
||||
|
||||
int (*next)(IsoDirIter *iter, IsoNode **node);
|
||||
|
||||
int (*has_next)(IsoDirIter *iter);
|
||||
|
||||
void (*free)(IsoDirIter *iter);
|
||||
|
||||
|
||||
int (*take)(IsoDirIter *iter);
|
||||
|
||||
int (*remove)(IsoDirIter *iter);
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* This is called just before remove a node from a directory. The iterator
|
||||
* may want to update its internal state according to this.
|
||||
*/
|
||||
@ -167,37 +164,37 @@ struct iso_dir_iter_iface
|
||||
struct Iso_Dir_Iter
|
||||
{
|
||||
struct iso_dir_iter_iface *class;
|
||||
|
||||
|
||||
/* the directory this iterator iterates over */
|
||||
IsoDir *dir;
|
||||
|
||||
|
||||
void *data;
|
||||
};
|
||||
|
||||
int iso_node_new_root(IsoDir **root);
|
||||
|
||||
/**
|
||||
* Create a new IsoDir. Attributes, uid/gid, timestamps, etc are set to
|
||||
* Create a new IsoDir. Attributes, uid/gid, timestamps, etc are set to
|
||||
* default (0) values. You must set them.
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* Name for the node. It is not strdup() so you shouldn't use this
|
||||
* reference when this function returns successfully. NULL is not
|
||||
* Name for the node. It is not strdup() so you shouldn't use this
|
||||
* reference when this function returns successfully. NULL is not
|
||||
* allowed.
|
||||
* @param dir
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* 1 on success, < 0 on error.
|
||||
*/
|
||||
int iso_node_new_dir(char *name, IsoDir **dir);
|
||||
|
||||
/**
|
||||
* Create a new file node. Attributes, uid/gid, timestamps, etc are set to
|
||||
* Create a new file node. Attributes, uid/gid, timestamps, etc are set to
|
||||
* default (0) values. You must set them.
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* Name for the node. It is not strdup() so you shouldn't use this
|
||||
* reference when this function returns successfully. NULL is not
|
||||
* Name for the node. It is not strdup() so you shouldn't use this
|
||||
* reference when this function returns successfully. NULL is not
|
||||
* allowed.
|
||||
* @param stream
|
||||
* Source for file contents. The reference is taken by the node,
|
||||
@ -210,14 +207,14 @@ int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file);
|
||||
/**
|
||||
* Creates a new IsoSymlink node. Attributes, uid/gid, timestamps, etc are set
|
||||
* to default (0) values. You must set them.
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* name for the new symlink. It is not strdup() so you shouldn't use this
|
||||
* reference when this function returns successfully. NULL is not
|
||||
* name for the new symlink. It is not strdup() so you shouldn't use this
|
||||
* reference when this function returns successfully. NULL is not
|
||||
* allowed.
|
||||
* @param dest
|
||||
* destination of the link. It is not strdup() so you shouldn't use this
|
||||
* reference when this function returns successfully. NULL is not
|
||||
* destination of the link. It is not strdup() so you shouldn't use this
|
||||
* reference when this function returns successfully. NULL is not
|
||||
* allowed.
|
||||
* @param link
|
||||
* place where to store a pointer to the newly created link.
|
||||
@ -231,22 +228,22 @@ int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link);
|
||||
* an special file is a block device, a character device, a FIFO (named pipe)
|
||||
* or a socket. You can choose the specific kind of file you want to add
|
||||
* by setting mode propertly (see man 2 stat).
|
||||
*
|
||||
* Note that special files are only written to image when Rock Ridge
|
||||
*
|
||||
* Note that special files are only written to image when Rock Ridge
|
||||
* extensions are enabled. Moreover, a special file is just a directory entry
|
||||
* in the image tree, no data is written beyond that.
|
||||
*
|
||||
* Owner and hidden atts are taken from parent. You can modify any of them
|
||||
*
|
||||
* Owner and hidden atts are taken from parent. You can modify any of them
|
||||
* later.
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* name for the new special file. It is not strdup() so you shouldn't use
|
||||
* this reference when this function returns successfully. NULL is not
|
||||
* name for the new special file. It is not strdup() so you shouldn't use
|
||||
* this reference when this function returns successfully. NULL is not
|
||||
* allowed.
|
||||
* @param mode
|
||||
* file type and permissions for the new node. Note that you can't
|
||||
* specify any kind of file here, only special types are allowed. i.e,
|
||||
* S_IFSOCK, S_IFBLK, S_IFCHR and S_IFIFO are valid types; S_IFLNK,
|
||||
* S_IFSOCK, S_IFBLK, S_IFCHR and S_IFIFO are valid types; S_IFLNK,
|
||||
* S_IFREG and S_IFDIR aren't.
|
||||
* @param dev
|
||||
* device ID, equivalent to the st_rdev field in man 2 stat.
|
||||
@ -255,12 +252,12 @@ int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link);
|
||||
* @return
|
||||
* 1 on success, < 0 otherwise
|
||||
*/
|
||||
int iso_node_new_special(char *name, mode_t mode, dev_t dev,
|
||||
int iso_node_new_special(char *name, mode_t mode, dev_t dev,
|
||||
IsoSpecial **special);
|
||||
|
||||
/**
|
||||
* Check if a given name is valid for an iso node.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* 1 if yes, 0 if not
|
||||
*/
|
||||
@ -268,7 +265,7 @@ int iso_node_is_valid_name(const char *name);
|
||||
|
||||
/**
|
||||
* Check if a given path is valid for the destination of a link.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* 1 if yes, 0 if not
|
||||
*/
|
||||
@ -276,7 +273,7 @@ int iso_node_is_valid_link_dest(const char *dest);
|
||||
|
||||
/**
|
||||
* Find the position where to insert a node
|
||||
*
|
||||
*
|
||||
* @param dir
|
||||
* A valid dir. It can't be NULL
|
||||
* @param name
|
||||
@ -288,7 +285,7 @@ void iso_dir_find(IsoDir *dir, const char *name, IsoNode ***pos);
|
||||
|
||||
/**
|
||||
* Check if a node with the given name exists in a dir.
|
||||
*
|
||||
*
|
||||
* @param dir
|
||||
* A valid dir. It can't be NULL
|
||||
* @param name
|
||||
@ -303,26 +300,26 @@ int iso_dir_exists(IsoDir *dir, const char *name, IsoNode ***pos);
|
||||
|
||||
/**
|
||||
* Inserts a given node in a dir, at the specified position.
|
||||
*
|
||||
*
|
||||
* @param dir
|
||||
* Dir where to insert. It can't be NULL
|
||||
* @param node
|
||||
* The node to insert. It can't be NULL
|
||||
* @param pos
|
||||
* Position where the node will be inserted. It is a pointer previously
|
||||
* obtained with a call to iso_dir_exists() or iso_dir_find().
|
||||
* obtained with a call to iso_dir_exists() or iso_dir_find().
|
||||
* It can't be NULL.
|
||||
* @param replace
|
||||
* @param replace
|
||||
* Whether to replace an old node with the same name with the new node.
|
||||
* @return
|
||||
* If success, number of children in dir. < 0 on error
|
||||
* If success, number of children in dir. < 0 on error
|
||||
*/
|
||||
int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos,
|
||||
int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos,
|
||||
enum iso_replace_mode replace);
|
||||
|
||||
/**
|
||||
* Add a new iterator to the registry. The iterator register keeps track of
|
||||
* all iterators being used, and are notified when directory structure
|
||||
* all iterators being used, and are notified when directory structure
|
||||
* changes.
|
||||
*/
|
||||
int iso_dir_iter_register(IsoDirIter *iter);
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user