Changed tree, re-implemented and fixed a lot of problematic areas
This commit is contained in:
@@ -19,33 +19,66 @@ create_node(struct ecma119_write_target *t,
|
||||
struct joliet_tree_node *ret =
|
||||
calloc(1, sizeof(struct joliet_tree_node));
|
||||
|
||||
ret->name = iso_j_id(iso->name);
|
||||
ret->name = iso_j_id(iso->name, t->input_charset);
|
||||
ret->dirent_len = 34 + (ret->name ? ucslen(ret->name) * 2 : 0);
|
||||
ret->len = iso->attrib.st_size; /* for dirs, we'll change this */
|
||||
ret->block = iso->block; /* only actually for files, not dirs */
|
||||
ret->parent = parent;
|
||||
ret->iso_self = iso;
|
||||
ret->target = t;
|
||||
ret->nchildren = iso->nchildren;
|
||||
if (ret->nchildren)
|
||||
ret->children = calloc(sizeof(void*), ret->nchildren);
|
||||
|
||||
if ( ISO_ISDIR(iso) ) {
|
||||
struct iso_tree_node_dir *dir = (struct iso_tree_node_dir *) iso;
|
||||
ret->info.dir.children = calloc(sizeof(void*), dir->nchildren);
|
||||
ret->type = JOLIET_DIR;
|
||||
} else {
|
||||
/* it's a file */
|
||||
struct iso_tree_node_file *iso_f = (struct iso_tree_node_file *) iso;
|
||||
struct iso_file *file;
|
||||
file = iso_file_table_lookup(t->file_table, iso_f);
|
||||
if ( file == NULL ) {
|
||||
file = iso_file_new(iso_f);
|
||||
iso_file_table_add_file(t->file_table, file);
|
||||
}
|
||||
ret->info.file = file;
|
||||
ret->type = JOLIET_FILE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct joliet_tree_node*
|
||||
create_tree(struct ecma119_write_target *t,
|
||||
struct joliet_tree_node *parent,
|
||||
struct iso_tree_node *iso_root)
|
||||
{
|
||||
struct joliet_tree_node *root = create_node(t, parent, iso_root);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < root->nchildren; i++) {
|
||||
struct iso_tree_node *iso_ch = iso_root->children[i];
|
||||
if (ISO_ISDIR(iso_ch))
|
||||
root->children[i] = create_tree(t, root, iso_ch);
|
||||
else
|
||||
root->children[i] = create_node(t, root, iso_ch);
|
||||
struct iso_tree_node *iso)
|
||||
{
|
||||
struct joliet_tree_node *root;
|
||||
assert(t && iso);
|
||||
|
||||
if ( iso->hide_flags & LIBISO_HIDE_ON_JOLIET )
|
||||
return NULL;
|
||||
|
||||
switch (iso->attrib.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
root = create_node(t, parent, iso);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
{
|
||||
size_t i;
|
||||
struct joliet_tree_node *node;
|
||||
struct iso_tree_node_dir *dir;
|
||||
root = create_node(t, parent, iso);
|
||||
dir = (struct iso_tree_node_dir*)iso;
|
||||
for (i = 0; i < dir->nchildren; ++i) {
|
||||
node = create_tree(t, root, dir->children[i]);
|
||||
if ( node != NULL ) {
|
||||
root->info.dir.children[root->info.dir.nchildren++] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//TODO replace this printf
|
||||
printf("Can't add this kind of node to a Joliet tree");
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
@@ -63,12 +96,15 @@ sort_tree(struct joliet_tree_node *root)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(root && ISO_ISDIR(root->iso_self));
|
||||
assert(root && (root->type == JOLIET_DIR));
|
||||
|
||||
qsort(root->children, root->nchildren, sizeof(void*), cmp_node);
|
||||
for (i = 0; i < root->nchildren; i++)
|
||||
if (ISO_ISDIR(root->children[i]->iso_self))
|
||||
sort_tree(root->children[i]);
|
||||
qsort(root->info.dir.children, root->info.dir.nchildren,
|
||||
sizeof(void*), cmp_node);
|
||||
for (i = 0; i < root->info.dir.nchildren; i++) {
|
||||
struct joliet_tree_node *child = root->info.dir.children[i];
|
||||
if ( child->type == JOLIET_DIR )
|
||||
sort_tree(child);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -80,11 +116,11 @@ joliet_prepare_path_tables(struct ecma119_write_target *t)
|
||||
t->path_table_size_joliet = 10; /* root directory record */
|
||||
cur = 1;
|
||||
|
||||
for (i = 0; i < t->dirlist_len; i++) {
|
||||
for (i = 0; i < t->dirlist_len_joliet; i++) {
|
||||
struct joliet_tree_node *dir = t->pathlist_joliet[i];
|
||||
for (j = 0; j < dir->nchildren; j++) {
|
||||
struct joliet_tree_node *ch = dir->children[j];
|
||||
if (ISO_ISDIR(ch->iso_self)) {
|
||||
for (j = 0; j < dir->info.dir.nchildren; j++) {
|
||||
struct joliet_tree_node *ch = dir->info.dir.children[j];
|
||||
if (ch->type == JOLIET_DIR) {
|
||||
size_t len = 8 + ucslen(ch->name)*2;
|
||||
t->pathlist_joliet[cur++] = ch;
|
||||
t->path_table_size_joliet += len;
|
||||
@@ -104,22 +140,22 @@ joliet_calc_dir_size(struct ecma119_write_target *t,
|
||||
size_t newlen;
|
||||
struct joliet_tree_node *ch;
|
||||
|
||||
assert(root && ISO_ISDIR(root->iso_self));
|
||||
assert(root && (root->type == JOLIET_DIR) );
|
||||
|
||||
root->len = 68; /* for "." and ".." entries */
|
||||
for (i = 0; i < root->nchildren; i++) {
|
||||
ch = root->children[i];
|
||||
newlen = root->len + ch->dirent_len;
|
||||
if ((newlen % 2048) < (root->len % 2048)) {
|
||||
root->len = newlen + (2048 - (root->len % 2048));
|
||||
t->dirlist_len_joliet++;
|
||||
root->info.dir.len = 68; /* for "." and ".." entries */
|
||||
for (i = 0; i < root->info.dir.nchildren; ++i) {
|
||||
ch = root->info.dir.children[i];
|
||||
newlen = root->info.dir.len + ch->dirent_len;
|
||||
if ((newlen % 2048) < (root->info.dir.len % 2048)) {
|
||||
root->info.dir.len = newlen + (2048 - (root->info.dir.len % 2048));
|
||||
} else {
|
||||
root->info.dir.len += ch->dirent_len;
|
||||
}
|
||||
else {
|
||||
root->len += ch->dirent_len;
|
||||
}
|
||||
if (ISO_ISDIR(ch->iso_self))
|
||||
if (ch->type == JOLIET_DIR)
|
||||
joliet_calc_dir_size(t, ch);
|
||||
}
|
||||
t->total_dir_size_joliet += round_up (root->len, t->block_size);
|
||||
t->total_dir_size_joliet += round_up (root->info.dir.len, t->block_size);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,45 +168,17 @@ joliet_calc_dir_pos(struct ecma119_write_target *t,
|
||||
size_t i;
|
||||
struct joliet_tree_node *ch;
|
||||
|
||||
assert(root && ISO_ISDIR(root->iso_self));
|
||||
assert(root && (root->type == JOLIET_DIR));
|
||||
|
||||
root->block = t->curblock;
|
||||
t->curblock += div_up(root->len, t->block_size);
|
||||
root->info.dir.block = t->curblock;
|
||||
t->curblock += div_up(root->info.dir.len, t->block_size);
|
||||
|
||||
t->dirlist_joliet[t->curfile++] = root;
|
||||
for (i = 0; i < root->nchildren; i++) {
|
||||
ch = root->children[i];
|
||||
if (ISO_ISDIR(ch->iso_self))
|
||||
for (i = 0; i < root->info.dir.nchildren; i++) {
|
||||
ch = root->info.dir.children[i];
|
||||
if (ch->type == JOLIET_DIR)
|
||||
joliet_calc_dir_pos(t, ch);
|
||||
}
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
if (!root->parent)
|
||||
t->curfile = 0;
|
||||
}
|
||||
|
||||
void
|
||||
joliet_update_file_pos(struct ecma119_write_target *t,
|
||||
struct joliet_tree_node *dir)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(dir && ISO_ISDIR(dir->iso_self));
|
||||
for (i = 0; i < dir->nchildren; i++) {
|
||||
struct joliet_tree_node *ch;
|
||||
ch = dir->children[i];
|
||||
|
||||
if (!ISO_ISDIR (ch->iso_self)) {
|
||||
struct iso_tree_node *iso = ch->iso_self;
|
||||
ch->block = iso->block;
|
||||
}
|
||||
else
|
||||
joliet_update_file_pos(t, ch);
|
||||
}
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
if (!dir->parent)
|
||||
t->curfile = 0;
|
||||
}
|
||||
|
||||
struct joliet_tree_node*
|
||||
@@ -192,7 +200,7 @@ write_path_table(struct ecma119_write_target *t,
|
||||
void (*write_int)(uint8_t*, uint32_t, int) = l_type ?
|
||||
iso_lsb : iso_msb;
|
||||
|
||||
size_t i;
|
||||
size_t i;
|
||||
struct ecma119_path_table_record *rec;
|
||||
struct joliet_tree_node *dir;
|
||||
int parent = 0;
|
||||
@@ -209,7 +217,7 @@ write_path_table(struct ecma119_write_target *t,
|
||||
rec->len_di[0] = dir->parent ?
|
||||
(uint8_t) ucslen(dir->name) * 2 : 1;
|
||||
rec->len_xa[0] = 0;
|
||||
write_int(rec->block, dir->block, 4);
|
||||
write_int(rec->block, dir->info.dir.block, 4);
|
||||
write_int(rec->parent, parent + 1, 2);
|
||||
if (dir->parent)
|
||||
memcpy(rec->dir_id, dir->name, rec->len_di[0]);
|
||||
@@ -227,20 +235,31 @@ write_one_dir_record(struct ecma119_write_target *t,
|
||||
int file_id,
|
||||
uint8_t *buf)
|
||||
{
|
||||
uint32_t len;
|
||||
uint32_t block;
|
||||
uint8_t len_dr = (file_id >= 0) ? 34 : node->dirent_len;
|
||||
uint8_t len_fi = (file_id >= 0) ? 1 : ucslen(node->name) * 2;
|
||||
uint8_t f_id = (uint8_t) ((file_id == 3) ? 0 : file_id);
|
||||
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->name;
|
||||
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
|
||||
|
||||
if (node->type == JOLIET_DIR) {
|
||||
len = node->info.dir.len;
|
||||
block = node->info.dir.block;
|
||||
} else {
|
||||
/* file */
|
||||
len = node->info.file->size;
|
||||
block = node->info.file->block;
|
||||
}
|
||||
|
||||
if (file_id == 1 && node->parent)
|
||||
node = node->parent;
|
||||
|
||||
rec->len_dr[0] = len_dr;
|
||||
iso_bb(rec->block, node->block, 4);
|
||||
iso_bb(rec->length, node->len, 4);
|
||||
iso_bb(rec->block, block, 4);
|
||||
iso_bb(rec->length, len, 4);
|
||||
iso_datetime_7(rec->recording_time, t->now);
|
||||
rec->flags[0] = ISO_ISDIR(node->iso_self) ? 2 : 0;
|
||||
rec->flags[0] = (node->type == JOLIET_DIR) ? 2 : 0;
|
||||
iso_bb(rec->vol_seq_number, t->volnum + 1, 2);
|
||||
rec->len_fi[0] = len_fi;
|
||||
memcpy(rec->file_id, name, len_fi);
|
||||
@@ -263,14 +282,25 @@ write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct ecma119_sup_vol_desc *vol = (struct ecma119_sup_vol_desc*)buf;
|
||||
struct iso_volume *volume = t->volset->volume[t->volnum];
|
||||
uint16_t *vol_id = str2ucs(volume->volume_id);
|
||||
uint16_t *pub_id = str2ucs(volume->publisher_id);
|
||||
uint16_t *data_id = str2ucs(volume->data_preparer_id);
|
||||
uint16_t *volset_id = str2ucs(t->volset->volset_id);
|
||||
uint16_t *vol_id = str2ucs(volume->volume_id, t->input_charset);
|
||||
uint16_t *pub_id = str2ucs(volume->publisher_id, t->input_charset);
|
||||
uint16_t *data_id = str2ucs(volume->data_preparer_id, t->input_charset);
|
||||
uint16_t *volset_id = str2ucs(t->volset->volset_id, t->input_charset);
|
||||
int vol_id_len = MIN(32, ucslen(vol_id) * 2);
|
||||
int pub_id_len = MIN(128, ucslen(pub_id) * 2);
|
||||
int data_id_len = MIN(128, ucslen(data_id) * 2);
|
||||
int volset_id_len = MIN(128, ucslen(volset_id) * 2);
|
||||
|
||||
uint16_t *system_id = str2ucs(volume->system_id, t->input_charset);
|
||||
uint16_t *application_id = str2ucs(volume->application_id, t->input_charset);
|
||||
uint16_t *copyright_file_id = str2ucs(volume->copyright_file_id, t->input_charset);
|
||||
uint16_t *abstract_file_id = str2ucs(volume->abstract_file_id, t->input_charset);
|
||||
uint16_t *biblio_file_id = str2ucs(volume->biblio_file_id, t->input_charset);
|
||||
int system_id_len = MIN(32, ucslen(system_id) * 2);
|
||||
int application_id_len = MIN(128, ucslen(application_id) * 2);
|
||||
int copyright_file_id_len = MIN(37, ucslen(copyright_file_id) * 2);
|
||||
int abstract_file_id_len = MIN(37, ucslen(abstract_file_id) * 2);
|
||||
int biblio_file_id_len = MIN(37, ucslen(biblio_file_id) * 2);
|
||||
|
||||
vol->vol_desc_type[0] = 2;
|
||||
memcpy(vol->std_identifier, "CD001", 5);
|
||||
@@ -292,8 +322,13 @@ write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
memcpy(vol->vol_set_id, volset_id, volset_id_len);
|
||||
memcpy(vol->publisher_id, pub_id, pub_id_len);
|
||||
memcpy(vol->data_prep_id, data_id, data_id_len);
|
||||
/*memcpy(vol->application_id, "APPID", app_id_len);*/
|
||||
|
||||
|
||||
memcpy(vol->system_id, system_id, system_id_len);
|
||||
memcpy(vol->application_id, "APPID", application_id_len);
|
||||
memcpy(vol->copyright_file_id, copyright_file_id, copyright_file_id_len);
|
||||
memcpy(vol->abstract_file_id, abstract_file_id, abstract_file_id_len);
|
||||
memcpy(vol->bibliographic_file_id, biblio_file_id, biblio_file_id_len);
|
||||
|
||||
iso_datetime_17(vol->vol_creation_time, t->now);
|
||||
iso_datetime_17(vol->vol_modification_time, t->now);
|
||||
iso_datetime_17(vol->vol_effective_time, t->now);
|
||||
@@ -303,6 +338,11 @@ write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
free(volset_id);
|
||||
free(pub_id);
|
||||
free(data_id);
|
||||
free(system_id);
|
||||
free(application_id);
|
||||
free(copyright_file_id);
|
||||
free(abstract_file_id);
|
||||
free(biblio_file_id);
|
||||
|
||||
}
|
||||
|
||||
@@ -317,7 +357,7 @@ write_one_dir(struct ecma119_write_target *t,
|
||||
uint8_t *orig_buf = buf;
|
||||
uint8_t *prior_buf = buf;
|
||||
|
||||
assert(ISO_ISDIR (dir->iso_self));
|
||||
assert(dir->type == JOLIET_DIR);
|
||||
/* write the "." and ".." entries first */
|
||||
write_one_dir_record(t, dir, 0, buf);
|
||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
@@ -325,8 +365,8 @@ write_one_dir(struct ecma119_write_target *t,
|
||||
write_one_dir_record(t, dir, 1, buf);
|
||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
|
||||
for (i = 0; i < dir->nchildren; i++) {
|
||||
write_one_dir_record(t, dir->children[i], -1, buf);
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
write_one_dir_record(t, dir->info.dir.children[i], -1, buf);
|
||||
len = ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||
if ((buf + len - prior_buf) >= 2048) {
|
||||
for (j = len - 1; j >= 0; j--) {
|
||||
@@ -341,7 +381,7 @@ write_one_dir(struct ecma119_write_target *t,
|
||||
}
|
||||
}
|
||||
|
||||
assert (buf - orig_buf == dir->len);
|
||||
assert (buf - orig_buf == dir->info.dir.len);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -350,11 +390,11 @@ write_dirs(struct ecma119_write_target *t, uint8_t *buf)
|
||||
size_t i;
|
||||
struct joliet_tree_node *dir;
|
||||
|
||||
assert (t->curblock == t->dirlist_joliet[0]->block);
|
||||
for (i = 0; i < t->dirlist_len; i++) {
|
||||
assert (t->curblock == t->dirlist_joliet[0]->info.dir.block);
|
||||
for (i = 0; i < t->dirlist_len_joliet; i++) {
|
||||
dir = t->dirlist_joliet[i];
|
||||
write_one_dir(t, dir, buf);
|
||||
buf += round_up(dir->len, t->block_size);
|
||||
buf += round_up(dir->info.dir.len, t->block_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user