Add support for multisession on Level 3 images.
This commit is contained in:
@ -1,9 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2007 Mario Danic
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
*
|
||||
* This file is part of the libisofs project; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. See COPYING file for details.
|
||||
*/
|
||||
|
||||
@ -47,7 +47,7 @@ int get_joliet_name(Ecma119Image *t, IsoNode *iso, uint16_t **name)
|
||||
*name = jname;
|
||||
return ISO_SUCCESS;
|
||||
} else {
|
||||
/*
|
||||
/*
|
||||
* only possible if mem error, as check for empty names is done
|
||||
* in public tree
|
||||
*/
|
||||
@ -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 "
|
||||
@ -152,7 +152,7 @@ int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node)
|
||||
|
||||
/**
|
||||
* Create the low level Joliet tree from the high level ISO tree.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* 1 success, 0 file ignored, < 0 error
|
||||
*/
|
||||
@ -226,7 +226,7 @@ int create_tree(Ecma119Image *t, IsoNode *iso, JolietNode **tree, int pathlen)
|
||||
} else {
|
||||
/* log and ignore */
|
||||
ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
|
||||
"El-Torito catalog found on a image without El-Torito.",
|
||||
"El-Torito catalog found on a image without El-Torito.",
|
||||
iso->name);
|
||||
}
|
||||
break;
|
||||
@ -257,12 +257,12 @@ cmp_node(const void *f1, const void *f2)
|
||||
return ucscmp(f->name, g->name);
|
||||
}
|
||||
|
||||
static
|
||||
static
|
||||
void sort_tree(JolietNode *root)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
qsort(root->info.dir->children, root->info.dir->nchildren,
|
||||
qsort(root->info.dir->children, root->info.dir->nchildren,
|
||||
sizeof(void*), cmp_node);
|
||||
for (i = 0; i < root->info.dir->nchildren; i++) {
|
||||
JolietNode *child = root->info.dir->children[i];
|
||||
@ -287,23 +287,23 @@ int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits,
|
||||
uint16_t *ucsnumber;
|
||||
char fmt[16];
|
||||
char *nstr = alloca(digits + 1);
|
||||
|
||||
|
||||
sprintf(fmt, "%%0%dd", digits);
|
||||
sprintf(nstr, fmt, number);
|
||||
|
||||
|
||||
ret = str2ucs("ASCII", nstr, &ucsnumber);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* copy name */
|
||||
pos = ucslen(src);
|
||||
ucsncpy(dest, src, pos);
|
||||
|
||||
|
||||
/* copy number */
|
||||
ucsncpy(dest + pos, ucsnumber, digits);
|
||||
pos += digits;
|
||||
|
||||
|
||||
if (ext[0] != (uint16_t)0) {
|
||||
size_t extlen = ucslen(ext);
|
||||
dest[pos++] = (uint16_t)0x2E00; /* '.' in big endian UCS */
|
||||
@ -326,9 +326,9 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
|
||||
nchildren = dir->info.dir->nchildren;
|
||||
children = dir->info.dir->children;
|
||||
|
||||
|
||||
/* a hash table will temporary hold the names, for fast searching */
|
||||
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
|
||||
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
|
||||
(compare_function_t)ucscmp, &table);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@ -349,7 +349,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
int digits = 1; /* characters to change per name */
|
||||
|
||||
/* first, find all child with same name */
|
||||
while (j + 1 < nchildren &&
|
||||
while (j + 1 < nchildren &&
|
||||
!cmp_node_name(children + i, children + j + 1)) {
|
||||
++j;
|
||||
}
|
||||
@ -359,7 +359,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
}
|
||||
|
||||
/*
|
||||
* A max of 7 characters is good enought, it allows handling up to
|
||||
* A max of 7 characters is good enought, it allows handling up to
|
||||
* 9,999,999 files with same name.
|
||||
*/
|
||||
while (digits < 8) {
|
||||
@ -374,7 +374,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
dot = ucsrchr(full_name, '.');
|
||||
if (dot != NULL && children[i]->type != JOLIET_DIR) {
|
||||
|
||||
/*
|
||||
/*
|
||||
* File (not dir) with extension
|
||||
*/
|
||||
int extlen;
|
||||
@ -387,17 +387,17 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
if (max <= 0) {
|
||||
/* this can happen if extension is too long */
|
||||
if (extlen + max > 3) {
|
||||
/*
|
||||
/*
|
||||
* reduce extension len, to give name an extra char
|
||||
* note that max is negative or 0
|
||||
* note that max is negative or 0
|
||||
*/
|
||||
extlen = extlen + max - 1;
|
||||
ext[extlen] = 0;
|
||||
max = 66 - extlen - 1 - digits;
|
||||
} else {
|
||||
/*
|
||||
/*
|
||||
* error, we don't support extensions < 3
|
||||
* This can't happen with current limit of digits.
|
||||
* This can't happen with current limit of digits.
|
||||
*/
|
||||
ret = ISO_ERROR;
|
||||
goto mangle_cleanup;
|
||||
@ -455,7 +455,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
children[k]->name = new;
|
||||
iso_htable_add(table, new, new);
|
||||
|
||||
/*
|
||||
/*
|
||||
* if we change a name we need to sort again children
|
||||
* at the end
|
||||
*/
|
||||
@ -486,7 +486,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
|
||||
}
|
||||
|
||||
ret = ISO_SUCCESS;
|
||||
|
||||
|
||||
mangle_cleanup : ;
|
||||
iso_htable_destroy(table, NULL);
|
||||
return ret;
|
||||
@ -521,7 +521,7 @@ int joliet_tree_create(Ecma119Image *t)
|
||||
{
|
||||
int ret;
|
||||
JolietNode *root;
|
||||
|
||||
|
||||
if (t == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
@ -534,7 +534,7 @@ int joliet_tree_create(Ecma119Image *t)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* the Joliet tree is stored in Ecma119Image target */
|
||||
t->joliet_root = root;
|
||||
|
||||
@ -590,10 +590,10 @@ size_t calc_dir_size(Ecma119Image *t, JolietNode *dir)
|
||||
len += dirent_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The size of a dir is always a multiple of block size, as we must add
|
||||
* the size of the unused space after the last directory record
|
||||
* The size of a dir is always a multiple of block size, as we must add
|
||||
* the size of the unused space after the last directory record
|
||||
* (ECMA-119, 6.8.1.3)
|
||||
*/
|
||||
len = ROUND_UP(len, BLOCK_SIZE);
|
||||
@ -677,7 +677,7 @@ int joliet_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
/**
|
||||
* Write a single directory record for Joliet. It is like (ECMA-119, 9.1),
|
||||
* but file identifier is stored in UCS.
|
||||
*
|
||||
*
|
||||
* @param file_id
|
||||
* if >= 0, we use it instead of the filename (for "." and ".." entries).
|
||||
* @param len_fi
|
||||
@ -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,12 +714,13 @@ 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
|
||||
* len and block to 0
|
||||
/*
|
||||
* for nodes other than files and dirs, we set both
|
||||
* len and block to 0
|
||||
*/
|
||||
len = 0;
|
||||
block = 0;
|
||||
@ -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;
|
||||
}
|
||||
@ -748,19 +750,19 @@ void ucsncpy_pad(uint16_t *dest, const uint16_t *src, size_t max)
|
||||
{
|
||||
char *cdest, *csrc;
|
||||
size_t len, i;
|
||||
|
||||
|
||||
cdest = (char*)dest;
|
||||
csrc = (char*)src;
|
||||
|
||||
|
||||
if (src != NULL) {
|
||||
len = MIN(ucslen(src) * 2, max);
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
cdest[i] = csrc[i];
|
||||
|
||||
|
||||
for (i = len; i < max; i += 2) {
|
||||
cdest[i] = '\0';
|
||||
cdest[i + 1] = ' ';
|
||||
@ -805,7 +807,7 @@ int joliet_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
memcpy(vol.std_identifier, "CD001", 5);
|
||||
vol.vol_desc_version[0] = 1;
|
||||
ucsncpy_pad((uint16_t*)vol.volume_id, vol_id, 32);
|
||||
|
||||
|
||||
/* make use of UCS-2 Level 3 */
|
||||
memcpy(vol.esc_sequences, "%/E", 3);
|
||||
|
||||
@ -817,12 +819,12 @@ 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);
|
||||
ucsncpy_pad((uint16_t*)vol.data_prep_id, data_id, 128);
|
||||
|
||||
|
||||
ucsncpy_pad((uint16_t*)vol.system_id, system_id, 32);
|
||||
|
||||
ucsncpy_pad((uint16_t*)vol.application_id, application_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 */
|
||||
|
Reference in New Issue
Block a user