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 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; 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;
@ -262,17 +262,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) {
off_t size = iso_file_src_get_size(node->info.file) block = node->info.file->sections[extent].block;
- ((off_t)0xFFFFF800) * (off_t)extent; /* bytes in another extent */ len = node->info.file->sections[extent].size;
if (size > (off_t) 0xffffffff) { multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1;
/* 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;
}
} else { } else {
/* /*
* for nodes other than files and dirs, we set both * for nodes other than files and dirs, we set both
@ -457,26 +449,27 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
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];
int extent = 0; /* compute len of directory entry */
do { 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 */ /* get the SUSP fields if rockridge is enabled */
fi_len = strlen(child->iso_name); if (t->rockridge) {
len = fi_len + 33 + (fi_len % 2 ? 0 : 1); ret = rrip_get_susp_fields(t, child, 0, 255 - len, &info);
if (need_version_number(t, child)) { if (ret < 0) {
len += 2; return ret;
} }
len += info.suf_len;
}
/* get the SUSP fields if rockridge is enabled */ nsections = (child->type == ECMA119_FILE) ? child->info.file->nsections : 1;
if (t->rockridge) { for (section = 0; section < nsections; ++section) {
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) { if ( (buf + len - buffer) > BLOCK_SIZE) {
/* dir doesn't fit in current block */ /* dir doesn't fit in current block */
@ -488,22 +481,9 @@ 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, extent); write_one_dir_record(t, child, -1, buf, fi_len, &info, section);
buf += len; 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 */ /* 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); 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;

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); 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) {
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->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 +125,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 +183,31 @@ 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);
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); t->curblock += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
} }

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

View File

@ -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)0xffffffff && t->iso_level != 3) {
free(n); free(n);
return iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0, return 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 "
@ -655,11 +655,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;
@ -674,8 +675,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
@ -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->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;
} }
@ -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_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);
@ -801,30 +803,34 @@ 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);
if ( (buf + len - buffer) > BLOCK_SIZE) { nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1;
/* dir doesn't fit in current block */ for (section = 0; section < nsections; ++section) {
ret = iso_write(t, buffer, BLOCK_SIZE); if ( (buf + len - buffer) > BLOCK_SIZE) {
if (ret < 0) { /* dir doesn't fit in current block */
return ret; ret = iso_write(t, buffer, BLOCK_SIZE);
if (ret < 0) {
return ret;
}
memset(buffer, 0, BLOCK_SIZE);
buf = buffer;
} }
memset(buffer, 0, BLOCK_SIZE); /* write the directory entry in any case */
buf = buffer; 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 */ /* write the last block */

View File

@ -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)0xffffffff && t->iso_level != 3) {
free(joliet); free(joliet);
return iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0, return 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 "
@ -686,11 +686,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;
@ -713,8 +714,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
@ -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->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;
} }
@ -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_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);
@ -864,12 +866,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 */
@ -879,18 +882,23 @@ int write_one_dir(Ecma119Image *t, JolietNode *dir)
len += 4; len += 4;
} }
if ( (buf + len - buffer) > BLOCK_SIZE) { nsections = (child->type == JOLIET_FILE) ? child->info.file->nsections : 1;
/* dir doesn't fit in current block */
ret = iso_write(t, buffer, BLOCK_SIZE); for (section = 0; section < nsections; ++section) {
if (ret < 0) {
return ret; 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); /* write the directory entry in any case */
buf = buffer; 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 */ /* 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 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, &section_count, &sections, 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.
* *

View File

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