Merge level3 branch, adding support for ISO-9660 Level 3.
This commit is contained in:
commit
c1a7702f52
@ -51,6 +51,7 @@ print_file_src(IsoFileSource *file)
|
|||||||
iso_file_source_lstat(file, &info);
|
iso_file_source_lstat(file, &info);
|
||||||
print_type(info.st_mode);
|
print_type(info.st_mode);
|
||||||
print_permissions(info.st_mode);
|
print_permissions(info.st_mode);
|
||||||
|
printf(" %10llu ", info.st_size);
|
||||||
//printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino);
|
//printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino);
|
||||||
name = iso_file_source_get_name(file);
|
name = iso_file_source_get_name(file);
|
||||||
printf(" %s", name);
|
printf(" %s", name);
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
@ -117,7 +117,11 @@ size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
|
|||||||
|
|
||||||
for (i = 0; i < dir->info.dir->nchildren; ++i) {
|
for (i = 0; i < dir->info.dir->nchildren; ++i) {
|
||||||
size_t remaining;
|
size_t remaining;
|
||||||
|
int section, nsections;
|
||||||
Ecma119Node *child = dir->info.dir->children[i];
|
Ecma119Node *child = dir->info.dir->children[i];
|
||||||
|
|
||||||
|
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);
|
size_t dirent_len = calc_dirent_len(t, child);
|
||||||
if (t->rockridge) {
|
if (t->rockridge) {
|
||||||
dirent_len += rrip_calc_len(t, child, 0, 255 - dirent_len, &ce_len);
|
dirent_len += rrip_calc_len(t, child, 0, 255 - dirent_len, &ce_len);
|
||||||
@ -131,6 +135,7 @@ size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
|
|||||||
len += dirent_len;
|
len += dirent_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The size of a dir is always a multiple of block size, as we must add
|
* The size of a dir is always a multiple of block size, as we must add
|
||||||
@ -235,11 +240,13 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
|
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 len;
|
||||||
uint32_t block;
|
uint32_t block;
|
||||||
uint8_t len_dr; /*< size of dir entry without SUSP fields */
|
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 *name = (file_id >= 0) ? (uint8_t*)&file_id
|
||||||
: (uint8_t*)node->iso_name;
|
: (uint8_t*)node->iso_name;
|
||||||
|
|
||||||
@ -260,8 +267,9 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
|
|||||||
len = node->info.dir->len;
|
len = node->info.dir->len;
|
||||||
block = node->info.dir->block;
|
block = node->info.dir->block;
|
||||||
} else if (node->type == ECMA119_FILE) {
|
} else if (node->type == ECMA119_FILE) {
|
||||||
len = iso_file_src_get_size(node->info.file);
|
block = node->info.file->sections[extent].block;
|
||||||
block = node->info.file->block;
|
len = node->info.file->sections[extent].size;
|
||||||
|
multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* for nodes other than files and dirs, we set both
|
* for nodes other than files and dirs, we set both
|
||||||
@ -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->block, block, 4);
|
||||||
iso_bb(rec->length, len, 4);
|
iso_bb(rec->length, len, 4);
|
||||||
iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
|
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);
|
iso_bb(rec->vol_seq_number, 1, 2);
|
||||||
rec->len_fi[0] = len_fi;
|
rec->len_fi[0] = len_fi;
|
||||||
|
|
||||||
/* and finally write the SUSP fields */
|
/*
|
||||||
|
* and finally write the SUSP fields.
|
||||||
|
*/
|
||||||
if (info != NULL) {
|
if (info != NULL) {
|
||||||
rrip_write_susp_fields(t, info, buf + len_dr);
|
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_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);
|
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.vol_set_id, volset_id, 128);
|
||||||
strncpy_pad((char*)vol.publisher_id, pub_id, 128);
|
strncpy_pad((char*)vol.publisher_id, pub_id, 128);
|
||||||
@ -429,7 +439,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
len = 34 + info.suf_len;
|
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;
|
buf += len;
|
||||||
|
|
||||||
if (t->rockridge) {
|
if (t->rockridge) {
|
||||||
@ -439,14 +449,19 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
len = 34 + info.suf_len;
|
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;
|
buf += len;
|
||||||
|
|
||||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
||||||
|
int section, nsections;
|
||||||
Ecma119Node *child = dir->info.dir->children[i];
|
Ecma119Node *child = dir->info.dir->children[i];
|
||||||
|
|
||||||
/* compute len of directory entry */
|
|
||||||
fi_len = strlen(child->iso_name);
|
fi_len = strlen(child->iso_name);
|
||||||
|
|
||||||
|
nsections = (child->type == ECMA119_FILE) ? child->info.file->nsections : 1;
|
||||||
|
for (section = 0; section < nsections; ++section) {
|
||||||
|
|
||||||
|
/* compute len of directory entry */
|
||||||
len = fi_len + 33 + (fi_len % 2 ? 0 : 1);
|
len = fi_len + 33 + (fi_len % 2 ? 0 : 1);
|
||||||
if (need_version_number(t, child)) {
|
if (need_version_number(t, child)) {
|
||||||
len += 2;
|
len += 2;
|
||||||
@ -471,9 +486,10 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
|
|||||||
buf = buffer;
|
buf = buffer;
|
||||||
}
|
}
|
||||||
/* write the directory entry in any case */
|
/* write the directory entry in any case */
|
||||||
write_one_dir_record(t, child, -1, buf, fi_len, &info);
|
write_one_dir_record(t, child, -1, buf, fi_len, &info, section);
|
||||||
buf += len;
|
buf += len;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* write the last block */
|
/* write the last block */
|
||||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||||
@ -1273,7 +1289,7 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
|
|||||||
wopts->level = 1;
|
wopts->level = 1;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
wopts->level = 2;
|
wopts->level = 3;
|
||||||
wopts->rockridge = 1;
|
wopts->rockridge = 1;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
@ -1315,7 +1331,7 @@ int iso_write_opts_set_iso_level(IsoWriteOpts *opts, int level)
|
|||||||
if (opts == NULL) {
|
if (opts == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
return ISO_NULL_POINTER;
|
||||||
}
|
}
|
||||||
if (level != 1 && level != 2) {
|
if (level != 1 && level != 2 && level != 3) {
|
||||||
return ISO_WRONG_ARG_VALUE;
|
return ISO_WRONG_ARG_VALUE;
|
||||||
}
|
}
|
||||||
opts->level = level;
|
opts->level = level;
|
||||||
|
@ -18,6 +18,18 @@
|
|||||||
|
|
||||||
#define BLOCK_SIZE 2048
|
#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.
|
* Holds the options for the image generation.
|
||||||
*/
|
*/
|
||||||
|
@ -161,7 +161,7 @@ int create_file(Ecma119Image *img, IsoFile *iso, Ecma119Node **node)
|
|||||||
off_t size;
|
off_t size;
|
||||||
|
|
||||||
size = iso_stream_get_size(iso->stream);
|
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));
|
char *ipath = iso_tree_get_node_path(ISO_NODE(iso));
|
||||||
ret = iso_msg_submit(img->image->id, ISO_FILE_TOO_BIG, 0,
|
ret = iso_msg_submit(img->image->id, ISO_FILE_TOO_BIG, 0,
|
||||||
"File \"%s\" can't be added to image because "
|
"File \"%s\" can't be added to image because "
|
||||||
|
@ -525,7 +525,7 @@ write_section_entry(uint8_t *buf, Ecma119Image *t)
|
|||||||
iso_lsb(se->load_seg, img->load_seg, 2);
|
iso_lsb(se->load_seg, img->load_seg, 2);
|
||||||
se->system_type[0] = img->partition_type;
|
se->system_type[0] = img->partition_type;
|
||||||
iso_lsb(se->sec_count, img->load_size, 2);
|
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
|
static
|
||||||
@ -699,7 +699,8 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
|
|||||||
|
|
||||||
/* fill fields */
|
/* fill fields */
|
||||||
file->prev_img = 0; /* TODO allow copy of old img catalog???? */
|
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->sort_weight = 1000; /* slightly high */
|
||||||
file->stream = stream;
|
file->stream = stream;
|
||||||
|
|
||||||
@ -746,7 +747,7 @@ int eltorito_writer_write_vol_desc(IsoImageWriter *writer)
|
|||||||
memcpy(vol.std_identifier, "CD001", 5);
|
memcpy(vol.std_identifier, "CD001", 5);
|
||||||
vol.vol_desc_version[0] = 1;
|
vol.vol_desc_version[0] = 1;
|
||||||
memcpy(vol.boot_sys_id, "EL TORITO SPECIFICATION", 23);
|
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));
|
return iso_write(t, &vol, sizeof(struct ecma119_boot_rec_vol_desc));
|
||||||
}
|
}
|
||||||
@ -788,7 +789,7 @@ int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize)
|
|||||||
info = (struct boot_info_table*)(buf + 8);
|
info = (struct boot_info_table*)(buf + 8);
|
||||||
/*memset(info, 0, sizeof(struct boot_info_table));*/
|
/*memset(info, 0, sizeof(struct boot_info_table));*/
|
||||||
iso_lsb(info->bi_pvd, t->ms_block + 16, 4);
|
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_length, imgsize, 4);
|
||||||
iso_lsb(info->bi_csum, checksum, 4);
|
iso_lsb(info->bi_csum, checksum, 4);
|
||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
|
@ -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);
|
iso_stream_get_id(file->stream, &fs_id, &dev_id, &ino_id);
|
||||||
|
|
||||||
fsrc = malloc(sizeof(IsoFileSrc));
|
fsrc = calloc(1, sizeof(IsoFileSrc));
|
||||||
if (fsrc == NULL) {
|
if (fsrc == NULL) {
|
||||||
return ISO_OUT_OF_MEM;
|
return ISO_OUT_OF_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill key and other atts */
|
/* fill key and other atts */
|
||||||
fsrc->prev_img = file->msblock ? 1 : 0;
|
fsrc->prev_img = file->from_old_session;
|
||||||
fsrc->block = file->msblock;
|
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->sort_weight = file->sort_weight;
|
||||||
fsrc->stream = file->stream;
|
fsrc->stream = file->stream;
|
||||||
|
|
||||||
/* insert the filesrc in the tree */
|
/* insert the filesrc in the tree */
|
||||||
ret = iso_rbtree_insert(img->files, fsrc, (void**)src);
|
ret = iso_rbtree_insert(img->files, fsrc, (void**)src);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
|
free(fsrc->sections);
|
||||||
free(fsrc);
|
free(fsrc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -117,6 +142,7 @@ int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src)
|
|||||||
void iso_file_src_free(void *node)
|
void iso_file_src_free(void *node)
|
||||||
{
|
{
|
||||||
iso_stream_unref(((IsoFileSrc*)node)->stream);
|
iso_stream_unref(((IsoFileSrc*)node)->stream);
|
||||||
|
free(((IsoFileSrc*)node)->sections);
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,8 +200,23 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||||||
|
|
||||||
/* fill block value */
|
/* fill block value */
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
|
int extent = 0;
|
||||||
IsoFileSrc *file = filelist[i];
|
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);
|
t->curblock += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,11 +300,6 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||||||
i = 0;
|
i = 0;
|
||||||
while ((file = filelist[i++]) != NULL) {
|
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);
|
uint32_t nblocks = DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
|
||||||
|
|
||||||
res = filesrc_open(file);
|
res = filesrc_open(file);
|
||||||
|
@ -17,7 +17,11 @@
|
|||||||
struct Iso_File_Src
|
struct Iso_File_Src
|
||||||
{
|
{
|
||||||
unsigned int prev_img :1; /**< if the file comes from a previous image */
|
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;
|
int sort_weight;
|
||||||
IsoStream *stream;
|
IsoStream *stream;
|
||||||
};
|
};
|
||||||
|
@ -240,7 +240,12 @@ struct image_fs_data
|
|||||||
struct stat info; /**< filled struct stat */
|
struct stat info; /**< filled struct stat */
|
||||||
char *name; /**< name of this file */
|
char *name; /**< name of this file */
|
||||||
|
|
||||||
uint32_t block; /**< block of the extend */
|
/**
|
||||||
|
* Location of file extents.
|
||||||
|
*/
|
||||||
|
struct iso_file_section *sections;
|
||||||
|
int nsections;
|
||||||
|
|
||||||
unsigned int opened : 2; /**< 0 not opened, 1 opened file, 2 opened dir */
|
unsigned int opened : 2; /**< 0 not opened, 1 opened file, 2 opened dir */
|
||||||
|
|
||||||
/* info for content reading */
|
/* info for content reading */
|
||||||
@ -372,7 +377,8 @@ int read_dir(ImageFileSourceData *data)
|
|||||||
fs = data->fs;
|
fs = data->fs;
|
||||||
fsdata = fs->data;
|
fsdata = fs->data;
|
||||||
|
|
||||||
block = data->block;
|
/* a dir has always a single extent */
|
||||||
|
block = data->sections[0].block;
|
||||||
ret = fsdata->src->read_block(fsdata->src, block, buffer);
|
ret = fsdata->src->read_block(fsdata->src, block, buffer);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
@ -434,11 +440,21 @@ int read_dir(ImageFileSourceData *data)
|
|||||||
*/
|
*/
|
||||||
ret = iso_file_source_new_ifs(fs, NULL, record, &child);
|
ret = iso_file_source_new_ifs(fs, NULL, record, &child);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
if (child) {
|
||||||
|
/*
|
||||||
|
* This can only happen with multi-extent files.
|
||||||
|
*/
|
||||||
|
ImageFileSourceData *ifsdata = child->data;
|
||||||
|
free(ifsdata->sections);
|
||||||
|
free(ifsdata->name);
|
||||||
|
free(ifsdata);
|
||||||
|
free(child);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add to the child list */
|
/* add to the child list */
|
||||||
if (ret != 0) {
|
if (ret == 1) {
|
||||||
struct child_list *node;
|
struct child_list *node;
|
||||||
node = malloc(sizeof(struct child_list));
|
node = malloc(sizeof(struct child_list));
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
@ -453,6 +469,7 @@ int read_dir(ImageFileSourceData *data)
|
|||||||
node->next = data->data.content;
|
node->next = data->data.content;
|
||||||
node->file = child;
|
node->file = child;
|
||||||
data->data.content = node;
|
data->data.content = node;
|
||||||
|
child = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tlen += record->len_dr[0];
|
tlen += record->len_dr[0];
|
||||||
@ -556,6 +573,76 @@ int ifs_close(IsoFileSource *src)
|
|||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the block where the given offset should start.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
uint32_t block_from_offset(int nsections, struct iso_file_section *sections,
|
||||||
|
off_t offset)
|
||||||
|
{
|
||||||
|
int section = 0;
|
||||||
|
off_t bytes = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ( (offset - bytes) < (off_t) sections[section].size ) {
|
||||||
|
return sections[section].block + (offset - bytes) / BLOCK_SIZE;
|
||||||
|
} else {
|
||||||
|
bytes += (off_t) sections[section].size;
|
||||||
|
section++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(section < nsections);
|
||||||
|
return 0; /* should never happen */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size available for reading on the corresponding block
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
uint32_t size_available(int nsections, struct iso_file_section *sections,
|
||||||
|
off_t offset)
|
||||||
|
{
|
||||||
|
int section = 0;
|
||||||
|
off_t bytes = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ( (offset - bytes) < (off_t) sections[section].size ) {
|
||||||
|
uint32_t curr_section_offset = (uint32_t)(offset - bytes);
|
||||||
|
uint32_t curr_section_left = sections[section].size - curr_section_offset;
|
||||||
|
uint32_t available = BLOCK_SIZE - curr_section_offset % BLOCK_SIZE;
|
||||||
|
return MIN(curr_section_left, available);
|
||||||
|
} else {
|
||||||
|
bytes += (off_t) sections[section].size;
|
||||||
|
section++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(section < nsections);
|
||||||
|
return 0; /* should never happen */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the block offset for reading the given file offset
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
uint32_t block_offset(int nsections, struct iso_file_section *sections,
|
||||||
|
off_t offset)
|
||||||
|
{
|
||||||
|
int section = 0;
|
||||||
|
off_t bytes = 0;
|
||||||
|
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ( (offset - bytes) < (off_t) sections[section].size ) {
|
||||||
|
return (uint32_t)(offset - bytes) % BLOCK_SIZE;
|
||||||
|
} else {
|
||||||
|
bytes += (off_t) sections[section].size;
|
||||||
|
section++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(section < nsections);
|
||||||
|
return 0; /* should never happen */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to read up to count bytes from the given source into
|
* Attempts to read up to count bytes from the given source into
|
||||||
* the buffer starting at buf.
|
* the buffer starting at buf.
|
||||||
@ -599,7 +686,7 @@ int ifs_read(IsoFileSource *src, void *buf, size_t count)
|
|||||||
size_t bytes;
|
size_t bytes;
|
||||||
uint8_t *orig;
|
uint8_t *orig;
|
||||||
|
|
||||||
if (data->data.offset % BLOCK_SIZE == 0) {
|
if (block_offset(data->nsections, data->sections, data->data.offset) == 0) {
|
||||||
/* we need to buffer next block */
|
/* we need to buffer next block */
|
||||||
uint32_t block;
|
uint32_t block;
|
||||||
_ImageFsData *fsdata;
|
_ImageFsData *fsdata;
|
||||||
@ -609,7 +696,8 @@ int ifs_read(IsoFileSource *src, void *buf, size_t count)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fsdata = data->fs->data;
|
fsdata = data->fs->data;
|
||||||
block = data->block + (data->data.offset / BLOCK_SIZE);
|
block = block_from_offset(data->nsections, data->sections,
|
||||||
|
data->data.offset);
|
||||||
ret = fsdata->src->read_block(fsdata->src, block,
|
ret = fsdata->src->read_block(fsdata->src, block,
|
||||||
data->data.content);
|
data->data.content);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -618,13 +706,13 @@ int ifs_read(IsoFileSource *src, void *buf, size_t count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* how much can I read */
|
/* how much can I read */
|
||||||
bytes = MIN(BLOCK_SIZE - (data->data.offset % BLOCK_SIZE),
|
bytes = MIN(size_available(data->nsections, data->sections, data->data.offset),
|
||||||
count - read);
|
count - read);
|
||||||
if (data->data.offset + (off_t)bytes > data->info.st_size) {
|
if (data->data.offset + (off_t)bytes > data->info.st_size) {
|
||||||
bytes = data->info.st_size - data->data.offset;
|
bytes = data->info.st_size - data->data.offset;
|
||||||
}
|
}
|
||||||
orig = data->data.content;
|
orig = data->data.content;
|
||||||
orig += data->data.offset % BLOCK_SIZE;
|
orig += block_offset(data->nsections, data->sections, data->data.offset);
|
||||||
memcpy((uint8_t*)buf + read, orig, bytes);
|
memcpy((uint8_t*)buf + read, orig, bytes);
|
||||||
read += bytes;
|
read += bytes;
|
||||||
data->data.offset += (off_t)bytes;
|
data->data.offset += (off_t)bytes;
|
||||||
@ -667,7 +755,11 @@ off_t ifs_lseek(IsoFileSource *src, off_t offset, int flag)
|
|||||||
return (off_t)ISO_WRONG_ARG_VALUE;
|
return (off_t)ISO_WRONG_ARG_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->data.offset % BLOCK_SIZE != 0) {
|
/*
|
||||||
|
* We check for block_offset != 0 because if it is already 0, the block
|
||||||
|
* will be read from image in the read function
|
||||||
|
*/
|
||||||
|
if (block_offset(data->nsections, data->sections, data->data.offset) != 0) {
|
||||||
/* we need to buffer the block */
|
/* we need to buffer the block */
|
||||||
uint32_t block;
|
uint32_t block;
|
||||||
_ImageFsData *fsdata;
|
_ImageFsData *fsdata;
|
||||||
@ -675,7 +767,8 @@ off_t ifs_lseek(IsoFileSource *src, off_t offset, int flag)
|
|||||||
if (data->data.offset < data->info.st_size) {
|
if (data->data.offset < data->info.st_size) {
|
||||||
int ret;
|
int ret;
|
||||||
fsdata = data->fs->data;
|
fsdata = data->fs->data;
|
||||||
block = data->block + (data->data.offset / BLOCK_SIZE);
|
block = block_from_offset(data->nsections, data->sections,
|
||||||
|
data->data.offset);
|
||||||
ret = fsdata->src->read_block(fsdata->src, block,
|
ret = fsdata->src->read_block(fsdata->src, block,
|
||||||
data->data.content);
|
data->data.content);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -811,6 +904,8 @@ void ifs_free(IsoFileSource *src)
|
|||||||
if (data->parent != NULL) {
|
if (data->parent != NULL) {
|
||||||
iso_file_source_unref(data->parent);
|
iso_file_source_unref(data->parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(data->sections);
|
||||||
free(data->name);
|
free(data->name);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
@ -871,7 +966,11 @@ char *get_name(_ImageFsData *fsdata, const char *str, size_t len)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
* @param src
|
||||||
|
* if not-NULL, it points to a multi-extent file returned by a previous
|
||||||
|
* call to this function.
|
||||||
* @return
|
* @return
|
||||||
|
* 2 node is still incomplete (multi-extent)
|
||||||
* 1 success, 0 record ignored (not an error, can be a relocated dir),
|
* 1 success, 0 record ignored (not an error, can be a relocated dir),
|
||||||
* < 0 error
|
* < 0 error
|
||||||
*/
|
*/
|
||||||
@ -909,15 +1008,6 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
|||||||
* First of all, check for unsupported ECMA-119 features
|
* First of all, check for unsupported ECMA-119 features
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* check for unsupported multiextend */
|
|
||||||
if (record->flags[0] & 0x80) {
|
|
||||||
iso_msg_submit(fsdata->msgid, ISO_UNSUPPORTED_ECMA119, 0,
|
|
||||||
"Unsupported image. This image makes use of Multi-Extend"
|
|
||||||
" features, that are not supported at this time. If you "
|
|
||||||
"need support for that, please request us this feature.");
|
|
||||||
return ISO_UNSUPPORTED_ECMA119;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for unsupported interleaved mode */
|
/* check for unsupported interleaved mode */
|
||||||
if (record->file_unit_size[0] || record->interleave_gap_size[0]) {
|
if (record->file_unit_size[0] || record->interleave_gap_size[0]) {
|
||||||
iso_msg_submit(fsdata->msgid, ISO_UNSUPPORTED_ECMA119, 0,
|
iso_msg_submit(fsdata->msgid, ISO_UNSUPPORTED_ECMA119, 0,
|
||||||
@ -941,6 +1031,81 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
|||||||
|
|
||||||
/* TODO #00013 : check for unsupported flags when reading a dir record */
|
/* TODO #00013 : check for unsupported flags when reading a dir record */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If src is not-NULL, it refers to more extents of this file. We ensure
|
||||||
|
* name matches, otherwise it means we are dealing with wrong image
|
||||||
|
*/
|
||||||
|
if (*src != NULL) {
|
||||||
|
ImageFileSourceData* data = (*src)->data;
|
||||||
|
char* new_name = get_name(fsdata, (char*)record->file_id, record->len_fi[0]);
|
||||||
|
if (new_name == NULL) {
|
||||||
|
iso_msg_submit(fsdata->msgid, ISO_WRONG_ECMA119, 0,
|
||||||
|
"Can't retrieve file name");
|
||||||
|
return ISO_WRONG_ECMA119;
|
||||||
|
}
|
||||||
|
if (strcmp(new_name, data->name)) {
|
||||||
|
iso_msg_submit(fsdata->msgid, ISO_WRONG_ECMA119, 0,
|
||||||
|
"Multi-extent file lacks last entry.");
|
||||||
|
free(new_name);
|
||||||
|
return ISO_WRONG_ECMA119;
|
||||||
|
}
|
||||||
|
free(new_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for multi-extent */
|
||||||
|
if (record->flags[0] & 0x80) {
|
||||||
|
iso_msg_debug(fsdata->msgid, "Found multi-extent file");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Directory entries can only have one section (ECMA-119, 6.8.1)
|
||||||
|
*/
|
||||||
|
if (record->flags[0] & 0x02) {
|
||||||
|
iso_msg_submit(fsdata->msgid, ISO_WRONG_ECMA119, 0,
|
||||||
|
"Directories with more than one section are not allowed.");
|
||||||
|
return ISO_WRONG_ECMA119;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*src == NULL) {
|
||||||
|
ifsdata = calloc(1, sizeof(ImageFileSourceData));
|
||||||
|
if (ifsdata == NULL) {
|
||||||
|
ret = ISO_OUT_OF_MEM;
|
||||||
|
goto ifs_cleanup;
|
||||||
|
}
|
||||||
|
ifsrc = calloc(1, sizeof(IsoFileSource));
|
||||||
|
if (ifsrc == NULL) {
|
||||||
|
ret = ISO_OUT_OF_MEM;
|
||||||
|
goto ifs_cleanup;
|
||||||
|
}
|
||||||
|
ifsrc->data = ifsdata;
|
||||||
|
ifsdata->name = get_name(fsdata, (char*)record->file_id, record->len_fi[0]);
|
||||||
|
if (ifsdata->name == NULL) {
|
||||||
|
iso_msg_submit(fsdata->msgid, ISO_WRONG_ECMA119, 0,
|
||||||
|
"Can't retrieve file name");
|
||||||
|
ret = ISO_WRONG_ECMA119;
|
||||||
|
goto ifs_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
*src = ifsrc;
|
||||||
|
} else {
|
||||||
|
ifsdata = (*src)->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store current extent */
|
||||||
|
ifsdata->sections = realloc(ifsdata->sections,
|
||||||
|
(1 + ifsdata->nsections) * sizeof(struct iso_file_section));
|
||||||
|
if (ifsdata->sections == NULL) {
|
||||||
|
free(ifsdata->name);
|
||||||
|
ret = ISO_OUT_OF_MEM;
|
||||||
|
goto ifs_cleanup;
|
||||||
|
}
|
||||||
|
ifsdata->sections[ifsdata->nsections].block = iso_read_bb(record->block, 4, NULL);
|
||||||
|
ifsdata->sections[ifsdata->nsections].size = iso_read_bb(record->length, 4, NULL);
|
||||||
|
|
||||||
|
ifsdata->info.st_size += (off_t) ifsdata->sections[ifsdata->nsections].size;
|
||||||
|
ifsdata->nsections++;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The idea is to read all the RR entries (if we want to do that and RR
|
* The idea is to read all the RR entries (if we want to do that and RR
|
||||||
* extensions exist on image), storing the info we want from that.
|
* extensions exist on image), storing the info we want from that.
|
||||||
@ -1264,6 +1429,7 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ok, we can now create the file source */
|
/* ok, we can now create the file source */
|
||||||
|
if (*src == NULL) {
|
||||||
ifsdata = calloc(1, sizeof(ImageFileSourceData));
|
ifsdata = calloc(1, sizeof(ImageFileSourceData));
|
||||||
if (ifsdata == NULL) {
|
if (ifsdata == NULL) {
|
||||||
ret = ISO_OUT_OF_MEM;
|
ret = ISO_OUT_OF_MEM;
|
||||||
@ -1274,6 +1440,12 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
|||||||
ret = ISO_OUT_OF_MEM;
|
ret = ISO_OUT_OF_MEM;
|
||||||
goto ifs_cleanup;
|
goto ifs_cleanup;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ifsdata = (*src)->data;
|
||||||
|
ifsrc = (*src);
|
||||||
|
free(ifsdata->name); /* we will assign a new one */
|
||||||
|
atts.st_size += (off_t)ifsdata->info.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
/* fill data */
|
/* fill data */
|
||||||
ifsdata->fs = fs;
|
ifsdata->fs = fs;
|
||||||
@ -1284,7 +1456,18 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
|||||||
}
|
}
|
||||||
ifsdata->info = atts;
|
ifsdata->info = atts;
|
||||||
ifsdata->name = name;
|
ifsdata->name = name;
|
||||||
ifsdata->block = iso_read_bb(record->block, 4, NULL);
|
|
||||||
|
/* save extents */
|
||||||
|
ifsdata->sections = realloc(ifsdata->sections,
|
||||||
|
(1 + ifsdata->nsections) * sizeof(struct iso_file_section));
|
||||||
|
if (ifsdata->sections == NULL) {
|
||||||
|
free(ifsdata->name);
|
||||||
|
ret = ISO_OUT_OF_MEM;
|
||||||
|
goto ifs_cleanup;
|
||||||
|
}
|
||||||
|
ifsdata->sections[ifsdata->nsections].block = iso_read_bb(record->block, 4, NULL);
|
||||||
|
ifsdata->sections[ifsdata->nsections].size = iso_read_bb(record->length, 4, NULL);
|
||||||
|
ifsdata->nsections++;
|
||||||
|
|
||||||
if (S_ISLNK(atts.st_mode)) {
|
if (S_ISLNK(atts.st_mode)) {
|
||||||
ifsdata->data.content = linkdest;
|
ifsdata->data.content = linkdest;
|
||||||
@ -1332,6 +1515,7 @@ int ifs_get_root(IsoFilesystem *fs, IsoFileSource **root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get root attributes from "." entry */
|
/* get root attributes from "." entry */
|
||||||
|
*root = NULL;
|
||||||
ret = iso_file_source_new_ifs((IsoImageFilesystem*)fs, NULL,
|
ret = iso_file_source_new_ifs((IsoImageFilesystem*)fs, NULL,
|
||||||
(struct ecma119_dir_record*) buffer, root);
|
(struct ecma119_dir_record*) buffer, root);
|
||||||
|
|
||||||
@ -2035,7 +2219,8 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||||||
/* source is a regular file */
|
/* source is a regular file */
|
||||||
_ImageFsData *fsdata = data->fs->data;
|
_ImageFsData *fsdata = data->fs->data;
|
||||||
|
|
||||||
if (fsdata->eltorito && data->block == fsdata->catblock) {
|
/* El-Torito images have only one section */
|
||||||
|
if (fsdata->eltorito && data->sections[0].block == fsdata->catblock) {
|
||||||
|
|
||||||
if (image->bootcat->node != NULL) {
|
if (image->bootcat->node != NULL) {
|
||||||
ret = iso_msg_submit(image->id, ISO_EL_TORITO_WARN, 0,
|
ret = iso_msg_submit(image->id, ISO_EL_TORITO_WARN, 0,
|
||||||
@ -2080,21 +2265,21 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||||||
return ISO_OUT_OF_MEM;
|
return ISO_OUT_OF_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the msblock is taken from the image */
|
/* mark file as from old session */
|
||||||
file->msblock = data->block;
|
file->from_old_session = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* and we set the sort weight based on the block on image, to
|
* and we set the sort weight based on the block on image, to
|
||||||
* improve performance on image modifying.
|
* improve performance on image modifying.
|
||||||
*/
|
*/
|
||||||
file->sort_weight = INT_MAX - data->block;
|
file->sort_weight = INT_MAX - data->sections[0].block;
|
||||||
|
|
||||||
file->stream = stream;
|
file->stream = stream;
|
||||||
file->node.type = LIBISO_FILE;
|
file->node.type = LIBISO_FILE;
|
||||||
new = (IsoNode*) file;
|
new = (IsoNode*) file;
|
||||||
new->refcount = 0;
|
new->refcount = 0;
|
||||||
|
|
||||||
if (fsdata->eltorito && data->block == fsdata->imgblock) {
|
if (fsdata->eltorito && data->sections[0].block == fsdata->imgblock) {
|
||||||
/* it is boot image node */
|
/* it is boot image node */
|
||||||
if (image->bootcat->image->image != NULL) {
|
if (image->bootcat->image->image != NULL) {
|
||||||
ret = iso_msg_submit(image->id, ISO_EL_TORITO_WARN, 0,
|
ret = iso_msg_submit(image->id, ISO_EL_TORITO_WARN, 0,
|
||||||
@ -2264,13 +2449,22 @@ int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoFileSource **src)
|
|||||||
goto boot_fs_cleanup;
|
goto boot_fs_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ifsdata->sections = malloc(sizeof(struct iso_file_section));
|
||||||
|
if (ifsdata->sections == NULL) {
|
||||||
|
ret = ISO_OUT_OF_MEM;
|
||||||
|
goto boot_fs_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* fill data */
|
/* fill data */
|
||||||
ifsdata->fs = fs;
|
ifsdata->fs = fs;
|
||||||
iso_filesystem_ref(fs);
|
iso_filesystem_ref(fs);
|
||||||
ifsdata->parent = NULL;
|
ifsdata->parent = NULL;
|
||||||
ifsdata->info = atts;
|
ifsdata->info = atts;
|
||||||
ifsdata->name = NULL;
|
ifsdata->name = NULL;
|
||||||
ifsdata->block = fsdata->imgblock;
|
|
||||||
|
ifsdata->sections[0].block = fsdata->imgblock;
|
||||||
|
ifsdata->sections[0].size = BLOCK_SIZE;
|
||||||
|
ifsdata->nsections = 1;
|
||||||
|
|
||||||
ifsrc->class = &ifs_class;
|
ifsrc->class = &ifs_class;
|
||||||
ifsrc->data = ifsdata;
|
ifsrc->data = ifsdata;
|
||||||
@ -2695,3 +2889,54 @@ int iso_read_image_features_has_eltorito(IsoReadImageFeatures *f)
|
|||||||
{
|
{
|
||||||
return f->hasElTorito;
|
return f->hasElTorito;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 arrays
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
int iso_file_get_old_image_sections(IsoFile *file, int *section_count,
|
||||||
|
struct iso_file_section **sections,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
if (file == NULL || section_count == NULL || sections == NULL) {
|
||||||
|
return ISO_NULL_POINTER;
|
||||||
|
}
|
||||||
|
if (flag != 0) {
|
||||||
|
return ISO_WRONG_ARG_VALUE;
|
||||||
|
}
|
||||||
|
if (file->from_old_session != 0) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When file is from old session, we retrieve the original IsoFileSource
|
||||||
|
* to get the sections. This break encapsultation, but safes memory as
|
||||||
|
* we don't need to store the sections in the IsoFile node.
|
||||||
|
*/
|
||||||
|
FSrcStreamData *data = file->stream->data;
|
||||||
|
ImageFileSourceData *ifsdata = data->src->data;
|
||||||
|
|
||||||
|
*section_count = ifsdata->nsections;
|
||||||
|
*sections = malloc(ifsdata->nsections *
|
||||||
|
sizeof(struct iso_file_section));
|
||||||
|
if (*sections == NULL) {
|
||||||
|
return ISO_OUT_OF_MEM;
|
||||||
|
}
|
||||||
|
memcpy(*sections, ifsdata->sections,
|
||||||
|
ifsdata->nsections * sizeof(struct iso_file_section));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -117,7 +117,7 @@ int create_node(Ecma119Image *t, IsoNode *iso, Iso1999Node **node)
|
|||||||
IsoFile *file = (IsoFile*) iso;
|
IsoFile *file = (IsoFile*) iso;
|
||||||
|
|
||||||
size = iso_stream_get_size(file->stream);
|
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);
|
char *ipath = iso_tree_get_node_path(iso);
|
||||||
ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
|
ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
|
||||||
"File \"%s\" can't be added to image because is "
|
"File \"%s\" can't be added to image because is "
|
||||||
@ -557,8 +557,12 @@ size_t calc_dir_size(Ecma119Image *t, Iso1999Node *dir)
|
|||||||
|
|
||||||
for (i = 0; i < dir->info.dir->nchildren; ++i) {
|
for (i = 0; i < dir->info.dir->nchildren; ++i) {
|
||||||
size_t remaining;
|
size_t remaining;
|
||||||
|
int section, nsections;
|
||||||
Iso1999Node *child = dir->info.dir->children[i];
|
Iso1999Node *child = dir->info.dir->children[i];
|
||||||
size_t dirent_len = calc_dirent_len(t, child);
|
size_t dirent_len = calc_dirent_len(t, child);
|
||||||
|
|
||||||
|
nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1;
|
||||||
|
for (section = 0; section < nsections; ++section) {
|
||||||
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
|
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
|
||||||
if (dirent_len > remaining) {
|
if (dirent_len > remaining) {
|
||||||
/* child directory entry doesn't fit on block */
|
/* child directory entry doesn't fit on block */
|
||||||
@ -567,6 +571,7 @@ size_t calc_dir_size(Ecma119Image *t, Iso1999Node *dir)
|
|||||||
len += dirent_len;
|
len += dirent_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The size of a dir is always a multiple of block size, as we must add
|
* The size of a dir is always a multiple of block size, as we must add
|
||||||
@ -663,11 +668,12 @@ int iso1999_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
|
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 len;
|
||||||
uint32_t block;
|
uint32_t block;
|
||||||
uint8_t len_dr; /*< size of dir entry */
|
uint8_t len_dr; /*< size of dir entry */
|
||||||
|
int multi_extend = 0;
|
||||||
uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
|
uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
|
||||||
: (uint8_t*)node->name;
|
: (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;
|
len = node->info.dir->len;
|
||||||
block = node->info.dir->block;
|
block = node->info.dir->block;
|
||||||
} else if (node->type == ISO1999_FILE) {
|
} else if (node->type == ISO1999_FILE) {
|
||||||
len = iso_file_src_get_size(node->info.file);
|
block = node->info.file->sections[extent].block;
|
||||||
block = node->info.file->block;
|
len = node->info.file->sections[extent].size;
|
||||||
|
multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* for nodes other than files and dirs, we set both
|
* 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->block, block, 4);
|
||||||
iso_bb(rec->length, len, 4);
|
iso_bb(rec->length, len, 4);
|
||||||
iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
|
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);
|
iso_bb(rec->vol_seq_number, 1, 2);
|
||||||
rec->len_fi[0] = len_fi;
|
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_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);
|
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.vol_set_id, volset_id, 128);
|
||||||
strncpy_pad((char*)vol.publisher_id, pub_id, 128);
|
strncpy_pad((char*)vol.publisher_id, pub_id, 128);
|
||||||
@ -809,18 +816,21 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
|||||||
memset(buffer, 0, BLOCK_SIZE);
|
memset(buffer, 0, BLOCK_SIZE);
|
||||||
|
|
||||||
/* write the "." and ".." entries first */
|
/* 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;
|
buf += 34;
|
||||||
write_one_dir_record(t, dir, 1, buf, 1);
|
write_one_dir_record(t, dir, 1, buf, 1, 0);
|
||||||
buf += 34;
|
buf += 34;
|
||||||
|
|
||||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
||||||
|
int section, nsections;
|
||||||
Iso1999Node *child = dir->info.dir->children[i];
|
Iso1999Node *child = dir->info.dir->children[i];
|
||||||
|
|
||||||
/* compute len of directory entry */
|
/* compute len of directory entry */
|
||||||
fi_len = strlen(child->name);
|
fi_len = strlen(child->name);
|
||||||
len = fi_len + 33 + (fi_len % 2 ? 0 : 1);
|
len = fi_len + 33 + (fi_len % 2 ? 0 : 1);
|
||||||
|
|
||||||
|
nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1;
|
||||||
|
for (section = 0; section < nsections; ++section) {
|
||||||
if ( (buf + len - buffer) > BLOCK_SIZE) {
|
if ( (buf + len - buffer) > BLOCK_SIZE) {
|
||||||
/* dir doesn't fit in current block */
|
/* dir doesn't fit in current block */
|
||||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||||
@ -831,9 +841,10 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
|
|||||||
buf = buffer;
|
buf = buffer;
|
||||||
}
|
}
|
||||||
/* write the directory entry in any case */
|
/* write the directory entry in any case */
|
||||||
write_one_dir_record(t, child, -1, buf, fi_len);
|
write_one_dir_record(t, child, -1, buf, fi_len, section);
|
||||||
buf += len;
|
buf += len;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* write the last block */
|
/* write the last block */
|
||||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||||
|
@ -111,7 +111,7 @@ int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node)
|
|||||||
IsoFile *file = (IsoFile*) iso;
|
IsoFile *file = (IsoFile*) iso;
|
||||||
|
|
||||||
size = iso_stream_get_size(file->stream);
|
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);
|
char *ipath = iso_tree_get_node_path(iso);
|
||||||
free(joliet);
|
free(joliet);
|
||||||
ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
|
ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
|
||||||
@ -590,8 +590,12 @@ size_t calc_dir_size(Ecma119Image *t, JolietNode *dir)
|
|||||||
|
|
||||||
for (i = 0; i < dir->info.dir->nchildren; ++i) {
|
for (i = 0; i < dir->info.dir->nchildren; ++i) {
|
||||||
size_t remaining;
|
size_t remaining;
|
||||||
|
int section, nsections;
|
||||||
JolietNode *child = dir->info.dir->children[i];
|
JolietNode *child = dir->info.dir->children[i];
|
||||||
size_t dirent_len = calc_dirent_len(t, child);
|
size_t dirent_len = calc_dirent_len(t, child);
|
||||||
|
|
||||||
|
nsections = (child->type == JOLIET_FILE) ? child->info.file->nsections : 1;
|
||||||
|
for (section = 0; section < nsections; ++section) {
|
||||||
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
|
remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
|
||||||
if (dirent_len > remaining) {
|
if (dirent_len > remaining) {
|
||||||
/* child directory entry doesn't fit on block */
|
/* child directory entry doesn't fit on block */
|
||||||
@ -600,6 +604,7 @@ size_t calc_dir_size(Ecma119Image *t, JolietNode *dir)
|
|||||||
len += dirent_len;
|
len += dirent_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The size of a dir is always a multiple of block size, as we must add
|
* The size of a dir is always a multiple of block size, as we must add
|
||||||
@ -696,11 +701,12 @@ int joliet_writer_compute_data_blocks(IsoImageWriter *writer)
|
|||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
|
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 len;
|
||||||
uint32_t block;
|
uint32_t block;
|
||||||
uint8_t len_dr; /*< size of dir entry */
|
uint8_t len_dr; /*< size of dir entry */
|
||||||
|
int multi_extend = 0;
|
||||||
uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
|
uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
|
||||||
: (uint8_t*)node->name;
|
: (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;
|
len = node->info.dir->len;
|
||||||
block = node->info.dir->block;
|
block = node->info.dir->block;
|
||||||
} else if (node->type == JOLIET_FILE) {
|
} else if (node->type == JOLIET_FILE) {
|
||||||
len = iso_file_src_get_size(node->info.file);
|
block = node->info.file->sections[extent].block;
|
||||||
block = node->info.file->block;
|
len = node->info.file->sections[extent].size;
|
||||||
|
multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* for nodes other than files and dirs, we set both
|
* 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->block, block, 4);
|
||||||
iso_bb(rec->length, len, 4);
|
iso_bb(rec->length, len, 4);
|
||||||
iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
|
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);
|
iso_bb(rec->vol_seq_number, 1, 2);
|
||||||
rec->len_fi[0] = len_fi;
|
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_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);
|
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.vol_set_id, volset_id, 128);
|
||||||
ucsncpy_pad((uint16_t*)vol.publisher_id, pub_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);
|
memset(buffer, 0, BLOCK_SIZE);
|
||||||
|
|
||||||
/* write the "." and ".." entries first */
|
/* 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;
|
buf += 34;
|
||||||
write_one_dir_record(t, dir, 1, buf, 1);
|
write_one_dir_record(t, dir, 1, buf, 1, 0);
|
||||||
buf += 34;
|
buf += 34;
|
||||||
|
|
||||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
||||||
|
int section, nsections;
|
||||||
JolietNode *child = dir->info.dir->children[i];
|
JolietNode *child = dir->info.dir->children[i];
|
||||||
|
|
||||||
/* compute len of directory entry */
|
/* compute len of directory entry */
|
||||||
@ -889,6 +897,10 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
len += 4;
|
len += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsections = (child->type == JOLIET_FILE) ? child->info.file->nsections : 1;
|
||||||
|
|
||||||
|
for (section = 0; section < nsections; ++section) {
|
||||||
|
|
||||||
if ( (buf + len - buffer) > BLOCK_SIZE) {
|
if ( (buf + len - buffer) > BLOCK_SIZE) {
|
||||||
/* dir doesn't fit in current block */
|
/* dir doesn't fit in current block */
|
||||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||||
@ -899,9 +911,10 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
|
|||||||
buf = buffer;
|
buf = buffer;
|
||||||
}
|
}
|
||||||
/* write the directory entry in any case */
|
/* write the directory entry in any case */
|
||||||
write_one_dir_record(t, child, -1, buf, fi_len);
|
write_one_dir_record(t, child, -1, buf, fi_len, section);
|
||||||
buf += len;
|
buf += len;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* write the last block */
|
/* write the last block */
|
||||||
ret = iso_write(t, buffer, BLOCK_SIZE);
|
ret = iso_write(t, buffer, BLOCK_SIZE);
|
||||||
|
@ -107,6 +107,17 @@ enum IsoNodeType {
|
|||||||
|
|
||||||
#define ISO_NODE(n) ((IsoNode*)n)
|
#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.
|
* Context for iterate on directory children.
|
||||||
* @see iso_dir_get_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.
|
* start point from which to set your custom options.
|
||||||
* ---> 1 [BACKUP]
|
* ---> 1 [BACKUP]
|
||||||
* POSIX compatibility for backup. Simple settings, ISO level is set to
|
* 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]
|
* ---> 2 [DISTRIBUTION]
|
||||||
* Setting for information distribution. Both RR and Joliet are enabled
|
* Setting for information distribution. Both RR and Joliet are enabled
|
||||||
* to maximize compatibility with most systems. Permissions are set to
|
* 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
|
* -> 1 for higher compatibility with old systems. With this level
|
||||||
* filenames are restricted to 8.3 characters.
|
* filenames are restricted to 8.3 characters.
|
||||||
* -> 2 to allow up to 31 filename characters.
|
* -> 2 to allow up to 31 filename characters.
|
||||||
|
* -> 3 to allow files greater than 4GB
|
||||||
* @return
|
* @return
|
||||||
* 1 success, < 0 error
|
* 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
|
* added, i.e. it does not come from an old image, < 0 error
|
||||||
*
|
*
|
||||||
* @since 0.6.4
|
* @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);
|
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.
|
* Like iso_file_get_old_image_lba(), but take an IsoNode.
|
||||||
*
|
*
|
||||||
|
@ -936,19 +936,27 @@ dev_t iso_special_get_dev(IsoSpecial *special)
|
|||||||
*/
|
*/
|
||||||
int iso_file_get_old_image_lba(IsoFile *file, uint32_t *lba, int flag)
|
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) {
|
if (file == NULL || lba == NULL) {
|
||||||
return ISO_NULL_POINTER;
|
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;
|
return ISO_WRONG_ARG_VALUE;
|
||||||
}
|
}
|
||||||
if (file->msblock != 0) {
|
*lba = sections[0].block;
|
||||||
*lba = file->msblock;
|
free(sections);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like iso_file_get_old_image_lba(), but take an IsoNode.
|
* Like iso_file_get_old_image_lba(), but take an IsoNode.
|
||||||
*
|
*
|
||||||
|
@ -115,10 +115,7 @@ struct Iso_File
|
|||||||
{
|
{
|
||||||
IsoNode node;
|
IsoNode node;
|
||||||
|
|
||||||
/**
|
unsigned int from_old_session : 1;
|
||||||
* Location of a file extent in a ms disc, 0 for newly added file
|
|
||||||
*/
|
|
||||||
uint32_t msblock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It sorts the order in which the file data is written to the CD image.
|
* It sorts the order in which the file data is written to the CD image.
|
||||||
|
@ -19,16 +19,6 @@ ino_t serial_id = (ino_t)1;
|
|||||||
ino_t mem_serial_id = (ino_t)1;
|
ino_t mem_serial_id = (ino_t)1;
|
||||||
ino_t cut_out_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
|
static
|
||||||
int fsrc_open(IsoStream *stream)
|
int fsrc_open(IsoStream *stream)
|
||||||
{
|
{
|
||||||
@ -612,6 +602,7 @@ void iso_stream_get_file_name(IsoStream *stream, char *name)
|
|||||||
FSrcStreamData *data = stream->data;
|
FSrcStreamData *data = stream->data;
|
||||||
char *path = iso_file_source_get_path(data->src);
|
char *path = iso_file_source_get_path(data->src);
|
||||||
strncpy(name, path, PATH_MAX);
|
strncpy(name, path, PATH_MAX);
|
||||||
|
free(path);
|
||||||
} else if (!strncmp(type, "boot", 4)) {
|
} else if (!strncmp(type, "boot", 4)) {
|
||||||
strcpy(name, "BOOT CATALOG");
|
strcpy(name, "BOOT CATALOG");
|
||||||
} else if (!strncmp(type, "mem ", 4)) {
|
} else if (!strncmp(type, "mem ", 4)) {
|
||||||
|
@ -13,6 +13,16 @@
|
|||||||
*/
|
*/
|
||||||
#include "fsource.h"
|
#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
|
* Get an identifier for the file of the source, for debug purposes
|
||||||
* @param name
|
* @param name
|
||||||
|
@ -23,7 +23,7 @@ static void test_rrip_calc_len_file()
|
|||||||
|
|
||||||
file = malloc(sizeof(IsoFile));
|
file = malloc(sizeof(IsoFile));
|
||||||
CU_ASSERT_PTR_NOT_NULL_FATAL(file);
|
CU_ASSERT_PTR_NOT_NULL_FATAL(file);
|
||||||
file->msblock = 0;
|
file->from_old_session = 0;
|
||||||
file->sort_weight = 0;
|
file->sort_weight = 0;
|
||||||
file->stream = NULL; /* it is not needed here */
|
file->stream = NULL; /* it is not needed here */
|
||||||
file->node.type = LIBISO_FILE;
|
file->node.type = LIBISO_FILE;
|
||||||
@ -303,7 +303,7 @@ void test_rrip_get_susp_fields_file()
|
|||||||
|
|
||||||
file = malloc(sizeof(IsoFile));
|
file = malloc(sizeof(IsoFile));
|
||||||
CU_ASSERT_PTR_NOT_NULL_FATAL(file);
|
CU_ASSERT_PTR_NOT_NULL_FATAL(file);
|
||||||
file->msblock = 0;
|
file->from_old_session = 0;
|
||||||
file->sort_weight = 0;
|
file->sort_weight = 0;
|
||||||
file->stream = NULL; /* it is not needed here */
|
file->stream = NULL; /* it is not needed here */
|
||||||
file->node.type = LIBISO_FILE;
|
file->node.type = LIBISO_FILE;
|
||||||
|
Loading…
Reference in New Issue
Block a user