Add support for multisession on Level 3 images.

This commit is contained in:
Vreixo Formoso 2008-08-19 02:45:20 +02:00
parent 3a503a3e85
commit 2e99e1aac9
9 changed files with 497 additions and 461 deletions

View File

@ -241,7 +241,7 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
uint32_t len;
uint32_t block;
uint8_t len_dr; /*< size of dir entry without SUSP fields */
int multi_extend = 0;
int multi_extend = 0;
uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
: (uint8_t*)node->iso_name;
@ -262,17 +262,9 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
len = node->info.dir->len;
block = node->info.dir->block;
} else if (node->type == ECMA119_FILE) {
off_t size = iso_file_src_get_size(node->info.file)
- ((off_t)0xFFFFF800) * (off_t)extent; /* bytes in another extent */
if (size > (off_t) 0xffffffff) {
/* 2097151 is the number of blocks needed to store 4 GB - 2048 */
block = node->info.file->block + extent * 2097151;
len = 0xFFFFF800;
multi_extend = 1;
} else {
len = (uint32_t) size;
block = node->info.file->block;
}
block = node->info.file->sections[extent].block;
len = node->info.file->sections[extent].size;
multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1;
} else {
/*
* for nodes other than files and dirs, we set both
@ -457,26 +449,27 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
buf += len;
for (i = 0; i < dir->info.dir->nchildren; i++) {
int section, nsections;
Ecma119Node *child = dir->info.dir->children[i];
int extent = 0;
do {
/* compute len of directory entry */
fi_len = strlen(child->iso_name);
len = fi_len + 33 + (fi_len % 2 ? 0 : 1);
if (need_version_number(t, child)) {
len += 2;
}
/* compute len of directory entry */
fi_len = strlen(child->iso_name);
len = fi_len + 33 + (fi_len % 2 ? 0 : 1);
if (need_version_number(t, child)) {
len += 2;
/* get the SUSP fields if rockridge is enabled */
if (t->rockridge) {
ret = rrip_get_susp_fields(t, child, 0, 255 - len, &info);
if (ret < 0) {
return ret;
}
len += info.suf_len;
}
/* get the SUSP fields if rockridge is enabled */
if (t->rockridge) {
ret = rrip_get_susp_fields(t, child, 0, 255 - len, &info);
if (ret < 0) {
return ret;
}
len += info.suf_len;
}
nsections = (child->type == ECMA119_FILE) ? child->info.file->nsections : 1;
for (section = 0; section < nsections; ++section) {
if ( (buf + len - buffer) > BLOCK_SIZE) {
/* dir doesn't fit in current block */
@ -488,22 +481,9 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
buf = buffer;
}
/* write the directory entry in any case */
write_one_dir_record(t, child, -1, buf, fi_len, &info, extent);
write_one_dir_record(t, child, -1, buf, fi_len, &info, section);
buf += len;
if (child->type == ECMA119_FILE) {
/* check if file is too big and need more extents */
off_t size = iso_file_src_get_size(child->info.file)
- ((off_t)0xFFFFF800) * (off_t)extent;
if (size > (off_t) 0xffffffff) {
extent++;
} else {
break;
}
} else {
break; /* we only have a single extent */
}
} while(1); /* loop for each extend */
}
}
/* write the last block */

View File

@ -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
@ -699,7 +699,8 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
/* 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,7 +747,7 @@ 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));
}
@ -788,7 +789,7 @@ int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize)
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;

View File

@ -61,20 +61,28 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
iso_stream_get_id(file->stream, &fs_id, &dev_id, &ino_id);
fsrc = malloc(sizeof(IsoFileSrc));
fsrc = calloc(1, sizeof(IsoFileSrc));
if (fsrc == NULL) {
return ISO_OUT_OF_MEM;
}
/* fill key and other atts */
fsrc->prev_img = file->msblock ? 1 : 0;
fsrc->block = file->msblock;
fsrc->prev_img = file->from_old_session;
if (file->from_old_session) {
int ret = iso_file_get_old_image_sections(file, &(fsrc->nsections),
&(fsrc->sections), 0);
if (ret < 0) {
free(fsrc);
return ISO_OUT_OF_MEM;
}
}
fsrc->sort_weight = file->sort_weight;
fsrc->stream = file->stream;
/* insert the filesrc in the tree */
ret = iso_rbtree_insert(img->files, fsrc, (void**)src);
if (ret <= 0) {
free(fsrc->sections);
free(fsrc);
return ret;
}
@ -117,6 +125,7 @@ int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src)
void iso_file_src_free(void *node)
{
iso_stream_unref(((IsoFileSrc*)node)->stream);
free(((IsoFileSrc*)node)->sections);
free(node);
}
@ -174,8 +183,31 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
/* fill block value */
for (i = 0; i < size; ++i) {
int extent = 0;
IsoFileSrc *file = filelist[i];
file->block = t->curblock;
off_t section_size = iso_stream_get_size(file->stream);
if (section_size > (off_t) 0xffffffff) {
file->nsections = DIV_UP(iso_stream_get_size(file->stream)
- (off_t) 0xffffffff, (off_t)0xFFFFF800) + 1;
} else {
file->nsections = 1;
}
file->sections = realloc(file->sections, file->nsections *
sizeof(struct iso_file_section));
for (extent = 0; extent < file->nsections - 1; ++extent) {
file->sections[extent].block = t->curblock + extent * 2097151;
file->sections[extent].size = 0xFFFFF800;
section_size -= (off_t) 0xFFFFF800;
}
/*
* final section
*/
file->sections[extent].block = t->curblock + extent * 2097151;
file->sections[extent].size = section_size;
section_size -= (off_t) 0xFFFFF800;
t->curblock += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
}

View File

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

View File

@ -117,7 +117,7 @@ int create_node(Ecma119Image *t, IsoNode *iso, Iso1999Node **node)
IsoFile *file = (IsoFile*) iso;
size = iso_stream_get_size(file->stream);
if (size > (off_t)0xffffffff) {
if (size > (off_t)0xffffffff && t->iso_level != 3) {
free(n);
return iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
"File \"%s\" can't be added to image because is "
@ -655,11 +655,12 @@ int iso1999_writer_compute_data_blocks(IsoImageWriter *writer)
*/
static
void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
uint8_t *buf, size_t len_fi)
uint8_t *buf, size_t len_fi, int extent)
{
uint32_t len;
uint32_t block;
uint8_t len_dr; /*< size of dir entry */
int multi_extend = 0;
uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
: (uint8_t*)node->name;
@ -674,8 +675,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
@ -695,7 +697,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;
}
@ -754,7 +756,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);
@ -801,30 +803,34 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
memset(buffer, 0, BLOCK_SIZE);
/* write the "." and ".." entries first */
write_one_dir_record(t, dir, 0, buf, 1);
write_one_dir_record(t, dir, 0, buf, 1, 0);
buf += 34;
write_one_dir_record(t, dir, 1, buf, 1);
write_one_dir_record(t, dir, 1, buf, 1, 0);
buf += 34;
for (i = 0; i < dir->info.dir->nchildren; i++) {
int section, nsections;
Iso1999Node *child = dir->info.dir->children[i];
/* compute len of directory entry */
fi_len = strlen(child->name);
len = fi_len + 33 + (fi_len % 2 ? 0 : 1);
if ( (buf + len - buffer) > BLOCK_SIZE) {
/* dir doesn't fit in current block */
ret = iso_write(t, buffer, BLOCK_SIZE);
if (ret < 0) {
return ret;
nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1;
for (section = 0; section < nsections; ++section) {
if ( (buf + len - buffer) > BLOCK_SIZE) {
/* dir doesn't fit in current block */
ret = iso_write(t, buffer, BLOCK_SIZE);
if (ret < 0) {
return ret;
}
memset(buffer, 0, BLOCK_SIZE);
buf = buffer;
}
memset(buffer, 0, BLOCK_SIZE);
buf = buffer;
/* write the directory entry in any case */
write_one_dir_record(t, child, -1, buf, fi_len, section);
buf += len;
}
/* write the directory entry in any case */
write_one_dir_record(t, child, -1, buf, fi_len);
buf += len;
}
/* write the last block */

View File

@ -111,7 +111,7 @@ int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node)
IsoFile *file = (IsoFile*) iso;
size = iso_stream_get_size(file->stream);
if (size > (off_t)0xffffffff) {
if (size > (off_t)0xffffffff && t->iso_level != 3) {
free(joliet);
return iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
"File \"%s\" can't be added to image because is "
@ -686,11 +686,12 @@ int joliet_writer_compute_data_blocks(IsoImageWriter *writer)
*/
static
void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
uint8_t *buf, size_t len_fi)
uint8_t *buf, size_t len_fi, int extent)
{
uint32_t len;
uint32_t block;
uint8_t len_dr; /*< size of dir entry */
int multi_extend = 0;
uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
: (uint8_t*)node->name;
@ -713,8 +714,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
@ -734,7 +736,7 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
iso_bb(rec->block, block, 4);
iso_bb(rec->length, len, 4);
iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
rec->flags[0] = (node->type == JOLIET_DIR) ? 2 : 0;
rec->flags[0] = ((node->type == JOLIET_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
iso_bb(rec->vol_seq_number, 1, 2);
rec->len_fi[0] = len_fi;
}
@ -817,7 +819,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);
@ -864,12 +866,13 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
memset(buffer, 0, BLOCK_SIZE);
/* write the "." and ".." entries first */
write_one_dir_record(t, dir, 0, buf, 1);
write_one_dir_record(t, dir, 0, buf, 1, 0);
buf += 34;
write_one_dir_record(t, dir, 1, buf, 1);
write_one_dir_record(t, dir, 1, buf, 1, 0);
buf += 34;
for (i = 0; i < dir->info.dir->nchildren; i++) {
int section, nsections;
JolietNode *child = dir->info.dir->children[i];
/* compute len of directory entry */
@ -879,18 +882,23 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
len += 4;
}
if ( (buf + len - buffer) > BLOCK_SIZE) {
/* dir doesn't fit in current block */
ret = iso_write(t, buffer, BLOCK_SIZE);
if (ret < 0) {
return ret;
nsections = (child->type == JOLIET_FILE) ? child->info.file->nsections : 1;
for (section = 0; section < nsections; ++section) {
if ( (buf + len - buffer) > BLOCK_SIZE) {
/* dir doesn't fit in current block */
ret = iso_write(t, buffer, BLOCK_SIZE);
if (ret < 0) {
return ret;
}
memset(buffer, 0, BLOCK_SIZE);
buf = buffer;
}
memset(buffer, 0, BLOCK_SIZE);
buf = buffer;
/* write the directory entry in any case */
write_one_dir_record(t, child, -1, buf, fi_len, section);
buf += len;
}
/* write the directory entry in any case */
write_one_dir_record(t, child, -1, buf, fi_len);
buf += len;
}
/* write the last block */

View File

@ -923,19 +923,27 @@ IsoStream *iso_file_get_stream(IsoFile *file)
*/
int iso_file_get_old_image_lba(IsoFile *file, uint32_t *lba, int flag)
{
int ret;
int section_count;
struct iso_file_section *sections;
if (file == NULL || lba == NULL) {
return ISO_NULL_POINTER;
}
if (flag != 0) {
ret = iso_file_get_old_image_sections(file, &section_count, &sections, flag);
if (ret <= 0) {
return ret;
}
if (section_count != 1) {
free(sections);
return ISO_WRONG_ARG_VALUE;
}
if (file->msblock != 0) {
*lba = file->msblock;
return 1;
}
*lba = sections[0].block;
free(sections);
return 0;
}
/*
* Like iso_file_get_old_image_lba(), but take an IsoNode.
*

View File

@ -115,10 +115,7 @@ 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.