Changed tree, re-implemented and fixed a lot of problematic areas
This commit is contained in:
parent
0281fcb717
commit
3e29f914fd
@ -29,7 +29,9 @@ libisofs_libisofs_la_SOURCES = \
|
||||
libisofs/exclude.c \
|
||||
libisofs/exclude.h \
|
||||
libisofs/hash.h \
|
||||
libisofs/hash.c
|
||||
libisofs/hash.c \
|
||||
libisofs/file.h \
|
||||
libisofs/file.c
|
||||
|
||||
libinclude_HEADERS = \
|
||||
libisofs/libisofs.h
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "volume.h"
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "file.h"
|
||||
#include "libisofs.h"
|
||||
#include "libburn/libburn.h"
|
||||
|
||||
@ -101,30 +102,35 @@ add_susp_fields_rec(struct ecma119_write_target *t,
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!node->iso_self)
|
||||
return;
|
||||
|
||||
rrip_add_PX(t, node);
|
||||
rrip_add_NM(t, node);
|
||||
rrip_add_TF(t, node);
|
||||
if (node->iso_self->attrib.st_rdev)
|
||||
rrip_add_PN(t, node);
|
||||
if (S_ISLNK(node->iso_self->attrib.st_mode))
|
||||
rrip_add_SL(t, node);
|
||||
if (node->type == ECMA119_FILE && node->file.real_me)
|
||||
rrip_add_CL(t, node);
|
||||
if (node->type == ECMA119_DIR
|
||||
&& node->dir.real_parent != node->parent) {
|
||||
rrip_add_RE(t, node);
|
||||
rrip_add_PL(t, node);
|
||||
|
||||
switch (node->type) {
|
||||
case ECMA119_FILE:
|
||||
break;
|
||||
case ECMA119_SYMLINK:
|
||||
rrip_add_SL(t, node);
|
||||
break;
|
||||
case ECMA119_DIR:
|
||||
if (node->info.dir.real_parent != node->parent) {
|
||||
rrip_add_RE(t, node);
|
||||
rrip_add_PL(t, node);
|
||||
}
|
||||
for (i = 0; i < node->info.dir.nchildren; i++) {
|
||||
add_susp_fields_rec(t, node->info.dir.children[i]);
|
||||
}
|
||||
break;
|
||||
case ECMA119_PLACEHOLDER:
|
||||
rrip_add_CL(t, node);
|
||||
break;
|
||||
default:
|
||||
// FIXME support for device blocks by uncommenting this
|
||||
//if (node->iso_self->attrib.st_rdev)
|
||||
// rrip_add_PN(t, node);
|
||||
break;
|
||||
}
|
||||
susp_add_CE(t, node);
|
||||
|
||||
if (node->type == ECMA119_DIR) {
|
||||
for (i = 0; i < node->dir.nchildren; i++) {
|
||||
add_susp_fields_rec(t, node->dir.children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -151,35 +157,35 @@ calc_dir_size(struct ecma119_write_target *t,
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
t->dirlist_len++;
|
||||
dir->dir.len = 34 + dir->dir.self_susp.non_CE_len
|
||||
+ 34 + dir->dir.parent_susp.non_CE_len;
|
||||
dir->dir.CE_len = dir->dir.self_susp.CE_len
|
||||
+ dir->dir.parent_susp.CE_len;
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
dir->info.dir.len = 34 + dir->info.dir.self_susp.non_CE_len
|
||||
+ 34 + dir->info.dir.parent_susp.non_CE_len;
|
||||
dir->info.dir.CE_len = dir->info.dir.self_susp.CE_len
|
||||
+ dir->info.dir.parent_susp.CE_len;
|
||||
for (i = 0; i < dir->info.dir.nchildren; ++i) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||
|
||||
newlen = dir->dir.len + ch->dirent_len + ch->susp.non_CE_len;
|
||||
if ((newlen % 2048) < (dir->dir.len % 2048)) {
|
||||
dir->dir.len = newlen + (2048 - (dir->dir.len % 2048));
|
||||
newlen = dir->info.dir.len + ch->dirent_len + ch->susp.non_CE_len;
|
||||
if ((newlen % 2048) < (dir->info.dir.len % 2048)) {
|
||||
dir->info.dir.len = newlen + (2048 - (dir->info.dir.len % 2048));
|
||||
} else {
|
||||
dir->info.dir.len += ch->dirent_len + ch->susp.non_CE_len;
|
||||
}
|
||||
else {
|
||||
dir->dir.len += ch->dirent_len + ch->susp.non_CE_len;
|
||||
}
|
||||
dir->dir.CE_len += ch->susp.CE_len;
|
||||
dir->info.dir.CE_len += ch->susp.CE_len;
|
||||
}
|
||||
t->total_dir_size += round_up(dir->dir.len + dir->dir.CE_len,
|
||||
t->total_dir_size += round_up(dir->info.dir.len + dir->info.dir.CE_len,
|
||||
t->block_size);
|
||||
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
struct iso_tree_node *iso = ch->iso_self;
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||
//struct iso_tree_node *iso = ch->iso_self;
|
||||
if (ch->type == ECMA119_DIR) {
|
||||
calc_dir_size(t, ch);
|
||||
} else if (iso && iso->attrib.st_size
|
||||
&& iso->loc.type == LIBISO_FILESYS
|
||||
&& iso->loc.path) {
|
||||
t->filelist_len++;
|
||||
}
|
||||
}
|
||||
// else if (iso && iso->attrib.st_size
|
||||
// && iso->loc.type == LIBISO_FILESYS
|
||||
// && iso->loc.path) {
|
||||
// t->filelist_len++;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,26 +201,27 @@ calc_dir_pos(struct ecma119_write_target *t,
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
/* we don't need to set iso_self->block since each tree writes
|
||||
* its own directories */
|
||||
dir->block = t->curblock;
|
||||
t->curblock += div_up(dir->dir.len + dir->dir.CE_len, t->block_size);
|
||||
dir->info.dir.block = t->curblock;
|
||||
t->curblock += div_up(dir->info.dir.len + dir->info.dir.CE_len, t->block_size);
|
||||
t->dirlist[t->curfile++] = dir;
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||
if (ch->type == ECMA119_DIR)
|
||||
calc_dir_pos(t, ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
if (!dir->parent) {
|
||||
t->curfile = 0;
|
||||
}
|
||||
static int
|
||||
cmp_file(const void *f1, const void *f2)
|
||||
{
|
||||
struct iso_file *f = *((struct iso_file**)f1);
|
||||
struct iso_file *g = *((struct iso_file**)f2);
|
||||
/* higher weighted first */
|
||||
return g->sort_weight - f->sort_weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill out the block field for each ecma119_tree_node that is a file and fill
|
||||
* out t->filelist.
|
||||
* Fill out the block field for each file and fill out t->filelist.
|
||||
*/
|
||||
static void
|
||||
calc_file_pos(struct ecma119_write_target *t,
|
||||
@ -223,31 +230,40 @@ calc_file_pos(struct ecma119_write_target *t,
|
||||
size_t i;
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
t->filelist = calloc(1, sizeof(struct iso_file *) * t->file_table->count);
|
||||
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
if (ch->type == ECMA119_FILE && ch->iso_self) {
|
||||
struct iso_tree_node *iso = ch->iso_self;
|
||||
off_t size = iso->attrib.st_size;
|
||||
for (i = 0; i < FILE_HASH_NODES; ++i) {
|
||||
|
||||
struct iso_file_hash_node *node;
|
||||
|
||||
iso->block = ch->block = t->curblock;
|
||||
t->curblock += div_up(size, t->block_size);
|
||||
if (size && iso->loc.type == LIBISO_FILESYS
|
||||
&& iso->loc.path)
|
||||
t->filelist[t->curfile++] = ch;
|
||||
}
|
||||
node = t->file_table->table[i];
|
||||
if (!node)
|
||||
continue;
|
||||
|
||||
do {
|
||||
struct iso_file *file = node->file;
|
||||
if (file->size)
|
||||
t->filelist[t->curfile++] = file;
|
||||
node = node->next;
|
||||
} while (node);
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
if (ch->type == ECMA119_DIR)
|
||||
calc_file_pos(t, ch);
|
||||
|
||||
t->filelist_len = t->curfile;
|
||||
|
||||
/* sort */
|
||||
if ( t->sort_files )
|
||||
qsort(t->filelist, t->filelist_len, sizeof(void*), cmp_file);
|
||||
|
||||
/* fill block value */
|
||||
for ( i = 0; i < t->filelist_len; ++i) {
|
||||
struct iso_file *file = t->filelist[i];
|
||||
file->block = t->curblock;
|
||||
t->curblock += div_up(file->size, t->block_size);
|
||||
}
|
||||
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
if (!dir->parent) {
|
||||
t->curfile = 0;
|
||||
}
|
||||
t->curfile = 0;
|
||||
}
|
||||
|
||||
struct ecma119_write_target*
|
||||
@ -259,33 +275,48 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
struct ecma119_write_target *t =
|
||||
calloc(1, sizeof(struct ecma119_write_target));
|
||||
size_t i, j, cur;
|
||||
struct iso_tree_node *iso_root = volset->volume[volnum]->root;
|
||||
struct iso_tree_node *iso_root =
|
||||
(struct iso_tree_node*) volset->volume[volnum]->root;
|
||||
|
||||
//TODO default values here, need an API for this
|
||||
t->cache_inodes = 1;
|
||||
t->replace_mode = 1;
|
||||
t->dir_mode = 0555;
|
||||
t->file_mode = 0444;
|
||||
t->gid = 0;
|
||||
t->uid = 0;
|
||||
t->input_charset = "UTF-8";
|
||||
t->ouput_charset = "UTF-8";
|
||||
t->sort_files = 1;
|
||||
|
||||
t->file_table = iso_file_table_new(t->cache_inodes);
|
||||
volset->refcount++;
|
||||
t->root = ecma119_tree_create(t, iso_root);
|
||||
t->iso_level = level;
|
||||
t->block_size = 2048;
|
||||
|
||||
t->rockridge = (flags & ECMA119_ROCKRIDGE) ? 1 : 0;
|
||||
t->joliet = (flags & ECMA119_JOLIET) ? 1 : 0;
|
||||
|
||||
t->root = ecma119_tree_create(t, iso_root);
|
||||
if (t->joliet)
|
||||
t->joliet_root = joliet_tree_create(t, iso_root);
|
||||
t->volset = volset;
|
||||
t->volnum = volnum;
|
||||
t->now = time(NULL);
|
||||
|
||||
t->rockridge = (flags & ECMA119_ROCKRIDGE) ? 1 : 0;
|
||||
t->iso_level = level;
|
||||
t->block_size = 2048;
|
||||
|
||||
if (t->rockridge)
|
||||
add_susp_fields(t);
|
||||
|
||||
calc_dir_size(t, t->root);
|
||||
if (t->joliet) {
|
||||
joliet_calc_dir_size(t, t->joliet_root);
|
||||
t->pathlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len);
|
||||
t->dirlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len);
|
||||
t->pathlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len_joliet);
|
||||
t->dirlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len_joliet);
|
||||
}
|
||||
|
||||
t->dirlist = calloc(1, sizeof(void*) * t->dirlist_len);
|
||||
t->pathlist = calloc(1, sizeof(void*) * t->dirlist_len);
|
||||
t->filelist = calloc(1, sizeof(void*) * t->filelist_len);
|
||||
//t->filelist = calloc(1, sizeof(void*) * t->filelist_len);
|
||||
|
||||
/* fill out the pathlist */
|
||||
t->pathlist[0] = t->root;
|
||||
@ -293,10 +324,10 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
cur = 1;
|
||||
for (i = 0; i < t->dirlist_len; i++) {
|
||||
struct ecma119_tree_node *dir = t->pathlist[i];
|
||||
for (j = 0; j < dir->dir.nchildren; j++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[j];
|
||||
for (j = 0; j < dir->info.dir.nchildren; j++) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[j];
|
||||
if (ch->type == ECMA119_DIR) {
|
||||
size_t len = 8 + strlen(ch->name);
|
||||
size_t len = 8 + strlen(ch->iso_name);
|
||||
t->pathlist[cur++] = ch;
|
||||
t->path_table_size += len + len % 2;
|
||||
}
|
||||
@ -323,11 +354,19 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
}
|
||||
|
||||
calc_dir_pos(t, t->root);
|
||||
if (t->joliet)
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
t->curfile = 0;
|
||||
if (t->joliet) {
|
||||
|
||||
joliet_calc_dir_pos(t, t->joliet_root);
|
||||
|
||||
/* reset curfile when we're finished */
|
||||
t->curfile = 0;
|
||||
}
|
||||
calc_file_pos(t, t->root);
|
||||
if (t->joliet)
|
||||
joliet_update_file_pos (t, t->joliet_root);
|
||||
//if (t->joliet)
|
||||
// joliet_update_file_pos (t, t->joliet_root);
|
||||
|
||||
if (t->rockridge) {
|
||||
susp_finalize(t, t->root);
|
||||
@ -406,11 +445,13 @@ wr_files(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct state_files *f_st = &t->state_files;
|
||||
size_t nread;
|
||||
struct ecma119_tree_node *f = t->filelist[f_st->file];
|
||||
const char *path = f->iso_self->loc.path;
|
||||
struct iso_file *f = t->filelist[f_st->file];
|
||||
const char *path = f->path;
|
||||
|
||||
|
||||
if (!f_st->fd) {
|
||||
f_st->data_len = f->iso_self->attrib.st_size;
|
||||
printf("Writing file %s\n", path);
|
||||
f_st->data_len = f->size;
|
||||
f_st->fd = fopen(path, "r");
|
||||
if (!f_st->fd)
|
||||
err(1, "couldn't open %s for reading", path);
|
||||
@ -438,16 +479,16 @@ write_pri_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct ecma119_pri_vol_desc *vol = (struct ecma119_pri_vol_desc*)buf;
|
||||
struct iso_volume *volume = t->volset->volume[t->volnum];
|
||||
char *vol_id = str2d_char(volume->volume_id);
|
||||
char *pub_id = str2a_char(volume->publisher_id);
|
||||
char *data_id = str2a_char(volume->data_preparer_id);
|
||||
char *volset_id = str2d_char(t->volset->volset_id);
|
||||
char *vol_id = str2d_char(volume->volume_id, t->input_charset);
|
||||
char *pub_id = str2a_char(volume->publisher_id, t->input_charset);
|
||||
char *data_id = str2a_char(volume->data_preparer_id, t->input_charset);
|
||||
char *volset_id = str2d_char(t->volset->volset_id, t->input_charset);
|
||||
|
||||
char *system_id = str2a_char(volume->system_id);
|
||||
char *application_id = str2a_char(volume->application_id);
|
||||
char *copyright_file_id = str2d_char(volume->copyright_file_id);
|
||||
char *abstract_file_id = str2d_char(volume->abstract_file_id);
|
||||
char *biblio_file_id = str2d_char(volume->biblio_file_id);
|
||||
char *system_id = str2a_char(volume->system_id, t->input_charset);
|
||||
char *application_id = str2a_char(volume->application_id, t->input_charset);
|
||||
char *copyright_file_id = str2d_char(volume->copyright_file_id, t->input_charset);
|
||||
char *abstract_file_id = str2d_char(volume->abstract_file_id, t->input_charset);
|
||||
char *biblio_file_id = str2d_char(volume->biblio_file_id, t->input_charset);
|
||||
|
||||
vol->vol_desc_type[0] = 1;
|
||||
memcpy(vol->std_identifier, "CD001", 5);
|
||||
@ -522,17 +563,18 @@ write_path_table(struct ecma119_write_target *t, int l_type, uint8_t *buf)
|
||||
|
||||
for (i = 0; i < t->dirlist_len; i++) {
|
||||
dir = t->pathlist[i];
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
while ((i) && t->pathlist[parent] != dir->parent)
|
||||
parent++;
|
||||
assert(parent < i || i == 0);
|
||||
|
||||
rec = (struct ecma119_path_table_record*) buf;
|
||||
rec->len_di[0] = dir->parent ? (uint8_t) strlen(dir->name) : 1;
|
||||
rec->len_di[0] = dir->parent ? (uint8_t) strlen(dir->iso_name) : 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]);
|
||||
memcpy(rec->dir_id, dir->iso_name, rec->len_di[0]);
|
||||
buf += 8 + rec->len_di[0] + (rec->len_di[0] % 2);
|
||||
}
|
||||
}
|
||||
@ -558,22 +600,36 @@ 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 : strlen(node->name);
|
||||
uint8_t len_fi = (file_id >= 0) ? 1 : strlen(node->iso_name);
|
||||
uint8_t f_id = (uint8_t) ((file_id == 3) ? 0 : file_id);
|
||||
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->name;
|
||||
uint32_t len = (node->type == ECMA119_DIR) ? node->dir.len
|
||||
: node->file.real_me ? 0 : node->iso_self->attrib.st_size;
|
||||
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->iso_name;
|
||||
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
|
||||
|
||||
|
||||
if (node->type == ECMA119_DIR) {
|
||||
len = node->info.dir.len;
|
||||
block = node->info.dir.block;
|
||||
} else if (node->type == ECMA119_FILE) {
|
||||
len = node->info.file->size;
|
||||
block = node->info.file->block;
|
||||
} else {
|
||||
/* for nodes other than files and dirs, we set both len and block to 0 */
|
||||
len = 0;
|
||||
block = 0;
|
||||
}
|
||||
|
||||
/* we don't write out susp fields for the root node */
|
||||
if (t->rockridge) {
|
||||
if (file_id == 0) {
|
||||
susp_write(t, &node->dir.self_susp, &buf[len_dr]);
|
||||
len_dr += node->dir.self_susp.non_CE_len;
|
||||
assert(node->type == ECMA119_DIR);
|
||||
susp_write(t, &node->info.dir.self_susp, &buf[len_dr]);
|
||||
len_dr += node->info.dir.self_susp.non_CE_len;
|
||||
} else if (file_id == 1) {
|
||||
susp_write(t, &node->dir.parent_susp, &buf[len_dr]);
|
||||
len_dr += node->dir.parent_susp.non_CE_len;
|
||||
assert(node->type == ECMA119_DIR);
|
||||
susp_write(t, &node->info.dir.parent_susp, &buf[len_dr]);
|
||||
len_dr += node->info.dir.parent_susp.non_CE_len;
|
||||
} else if (file_id < 0) {
|
||||
susp_write(t, &node->susp, &buf[len_dr]);
|
||||
len_dr += node->susp.non_CE_len;
|
||||
@ -583,7 +639,7 @@ write_one_dir_record(struct ecma119_write_target *t,
|
||||
node = node->parent;
|
||||
|
||||
rec->len_dr[0] = len_dr;
|
||||
iso_bb(rec->block, node->block, 4);
|
||||
iso_bb(rec->block, block, 4);
|
||||
iso_bb(rec->length, len, 4);
|
||||
iso_datetime_7(rec->recording_time, t->now);
|
||||
rec->flags[0] = (node->type == ECMA119_DIR) ? 2 : 0;
|
||||
@ -611,8 +667,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->dir.nchildren; i++) {
|
||||
write_one_dir_record(t, dir->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--) {
|
||||
@ -629,16 +685,16 @@ write_one_dir(struct ecma119_write_target *t,
|
||||
|
||||
/* write the susp continuation areas */
|
||||
if (t->rockridge) {
|
||||
susp_write_CE(t, &dir->dir.self_susp, buf);
|
||||
buf += dir->dir.self_susp.CE_len;
|
||||
susp_write_CE(t, &dir->dir.parent_susp, buf);
|
||||
buf += dir->dir.parent_susp.CE_len;
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
susp_write_CE(t, &dir->dir.children[i]->susp, buf);
|
||||
buf += dir->dir.children[i]->susp.CE_len;
|
||||
susp_write_CE(t, &dir->info.dir.self_susp, buf);
|
||||
buf += dir->info.dir.self_susp.CE_len;
|
||||
susp_write_CE(t, &dir->info.dir.parent_susp, buf);
|
||||
buf += dir->info.dir.parent_susp.CE_len;
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
susp_write_CE(t, &dir->info.dir.children[i]->susp, buf);
|
||||
buf += dir->info.dir.children[i]->susp.CE_len;
|
||||
}
|
||||
}
|
||||
assert (buf - orig_buf == dir->dir.len + dir->dir.CE_len);
|
||||
assert (buf - orig_buf == dir->info.dir.len + dir->info.dir.CE_len);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -649,7 +705,7 @@ write_dirs(struct ecma119_write_target *t, uint8_t *buf)
|
||||
for (i = 0; i < t->dirlist_len; i++) {
|
||||
dir = t->dirlist[i];
|
||||
write_one_dir(t, dir, buf);
|
||||
buf += round_up(dir->dir.len + dir->dir.CE_len, t->block_size);
|
||||
buf += round_up(dir->info.dir.len + dir->info.dir.CE_len, t->block_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -714,6 +770,9 @@ bs_free_data(struct burn_source *bs)
|
||||
{
|
||||
struct ecma119_write_target *t = (struct ecma119_write_target*)bs->data;
|
||||
ecma119_tree_free(t->root);
|
||||
iso_file_table_clear(t->file_table);
|
||||
|
||||
//FIXME free joliet tree
|
||||
free(t->dirlist);
|
||||
free(t->pathlist);
|
||||
free(t->dirlist_joliet);
|
||||
|
@ -61,6 +61,35 @@ struct ecma119_write_target
|
||||
unsigned int rockridge:1;
|
||||
unsigned int joliet:1;
|
||||
unsigned int iso_level:2;
|
||||
|
||||
int replace_mode; /**< Replace ownership and modes of files
|
||||
*
|
||||
* 0. filesystem values
|
||||
* 1. useful values
|
||||
* bits 1-4 bitmask:
|
||||
* 2 - replace dir
|
||||
* 3 - replace file
|
||||
* 4 - replace gid
|
||||
* 5 - replace uid
|
||||
*/
|
||||
mode_t dir_mode;
|
||||
mode_t file_mode;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
|
||||
char *input_charset;
|
||||
char *ouput_charset;
|
||||
|
||||
int cache_inodes;
|
||||
|
||||
int sort_files; /**< if sort files or not. Sorting is based of
|
||||
* the weight of each file */
|
||||
|
||||
/**
|
||||
* In the CD, each file must have an unique inode number. So each
|
||||
* time we add a new file, this is incremented.
|
||||
*/
|
||||
ino_t ino;
|
||||
|
||||
int curblock;
|
||||
uint16_t block_size;
|
||||
@ -86,10 +115,13 @@ struct ecma119_write_target
|
||||
size_t dirlist_len; /**< The length of the previous 2 lists.
|
||||
*/
|
||||
|
||||
struct ecma119_tree_node **filelist;
|
||||
/**< A pre-order list of files with
|
||||
* non-NULL paths and non-zero sizes.
|
||||
|
||||
struct iso_file_table *file_table;
|
||||
/**<
|
||||
* A hash table with info about all files
|
||||
*/
|
||||
|
||||
struct iso_file **filelist; /**< A pre-order list of files.*/
|
||||
size_t filelist_len; /* Length of the previous list. */
|
||||
|
||||
int curfile; /**< Used as a helper field for writing
|
||||
@ -101,6 +133,8 @@ struct ecma119_write_target
|
||||
*/
|
||||
struct joliet_tree_node **dirlist_joliet;
|
||||
struct joliet_tree_node **pathlist_joliet;
|
||||
|
||||
size_t dirlist_len_joliet;
|
||||
|
||||
enum ecma119_write_state state; /* The current state of the writer. */
|
||||
|
||||
|
@ -12,54 +12,191 @@
|
||||
|
||||
static size_t calc_dirent_len(struct ecma119_tree_node *n)
|
||||
{
|
||||
int ret = n->name ? strlen(n->name) + 33 : 34;
|
||||
int ret = n->iso_name ? strlen(n->iso_name) + 33 : 34;
|
||||
if (ret % 2) ret++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
replace_node_mode(struct ecma119_write_target *t, struct stat *st)
|
||||
{
|
||||
if ( S_ISDIR(st->st_mode) ) {
|
||||
if ( t->replace_mode & 0x02 ) {
|
||||
/* replace dir mode with specific */
|
||||
st->st_mode &= S_IFMT;
|
||||
st->st_mode |= t->dir_mode;
|
||||
} else if (t->replace_mode & 0x01) {
|
||||
/* replace dir mode with default */
|
||||
/* read perm */
|
||||
mode_t new_mode = (st->st_mode & S_IFMT) | 0444;
|
||||
/* search bit if any */
|
||||
if ( st->st_mode & 0111)
|
||||
new_mode |= 0111;
|
||||
st->st_mode = new_mode;
|
||||
}
|
||||
} else {
|
||||
if ( t->replace_mode & 0x04 ) {
|
||||
/* replace file mode with specific */
|
||||
st->st_mode &= S_IFMT;
|
||||
st->st_mode |= t->file_mode;
|
||||
} else if (t->replace_mode & 0x01) {
|
||||
/* replace file mode with default */
|
||||
/* read perm */
|
||||
mode_t new_mode = (st->st_mode & S_IFMT) | 0444;
|
||||
/* execute bit if any */
|
||||
if ( st->st_mode & 0111)
|
||||
new_mode |= 0111;
|
||||
st->st_mode = new_mode;
|
||||
}
|
||||
|
||||
}
|
||||
if ( t->replace_mode & 0x08 ) {
|
||||
/* replace gid mode with specific */
|
||||
st->st_gid = t->gid;
|
||||
} else if (t->replace_mode & 0x01) {
|
||||
st->st_gid = 0;
|
||||
}
|
||||
if ( t->replace_mode & 0x10 ) {
|
||||
/* replace gid mode with specific */
|
||||
st->st_uid = t->uid;
|
||||
} else if (t->replace_mode & 0x01) {
|
||||
st->st_uid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ecma119_tree_node*
|
||||
create_ecma119_node(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
char *(*iso_name)(const char *, const char *) = ISO_ISDIR(iso) ?
|
||||
((t->iso_level == 1) ? iso_1_dirid : iso_2_dirid)
|
||||
: ((t->iso_level == 1) ? iso_1_fileid : iso_2_fileid);
|
||||
|
||||
assert(t && (!parent || parent->type == ECMA119_DIR) && iso );
|
||||
|
||||
ret = calloc(1, sizeof(struct ecma119_tree_node));
|
||||
|
||||
ret->iso_name = iso->name ? iso_name(iso->name, t->input_charset) : NULL;
|
||||
ret->dirent_len = calc_dirent_len(ret);
|
||||
ret->attrib = iso->attrib;
|
||||
if ( t->rockridge && t->replace_mode )
|
||||
replace_node_mode(t, &ret->attrib);
|
||||
|
||||
if (!iso->name)
|
||||
ret->full_name = NULL;
|
||||
else if ( strcmp(t->input_charset,t->ouput_charset) )
|
||||
ret->full_name = convert_str(iso->name, t->input_charset,
|
||||
t->ouput_charset);
|
||||
else
|
||||
ret->full_name = strdup(iso->name);
|
||||
ret->target = t;
|
||||
ret->parent = parent;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ecma119_tree_node*
|
||||
create_dir(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node *iso)
|
||||
struct iso_tree_node_dir *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
|
||||
assert(t && (!parent || parent->type == ECMA119_DIR)
|
||||
&& iso && S_ISDIR(iso->attrib.st_mode));
|
||||
&& iso && S_ISDIR(iso->node.attrib.st_mode));
|
||||
|
||||
ret = calloc(1, sizeof(struct ecma119_tree_node));
|
||||
ret->name = iso->name ? ((t->iso_level == 1) ? iso_1_dirid(iso->name)
|
||||
: iso_2_dirid(iso->name))
|
||||
: NULL;
|
||||
ret->dirent_len = calc_dirent_len(ret);
|
||||
ret->iso_self = iso;
|
||||
ret->target = t;
|
||||
ret = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||
ret->type = ECMA119_DIR;
|
||||
ret->parent = ret->dir.real_parent = parent;
|
||||
ret->dir.depth = parent ? parent->dir.depth + 1 : 1;
|
||||
ret->dir.nchildren = iso->nchildren;
|
||||
ret->dir.children = calloc(1, sizeof(void*) * iso->nchildren);
|
||||
ret->info.dir.real_parent = parent;
|
||||
ret->info.dir.depth = parent ? parent->info.dir.depth + 1 : 1;
|
||||
ret->info.dir.nchildren = 0;
|
||||
ret->info.dir.children = calloc(1, sizeof(void*) * iso->nchildren);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ecma119_tree_node*
|
||||
create_file(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node *iso)
|
||||
struct iso_tree_node_file *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
struct iso_file *file;
|
||||
|
||||
assert(t && iso && parent && parent->type == ECMA119_DIR);
|
||||
|
||||
ret = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||
ret->type = ECMA119_FILE;
|
||||
|
||||
/* get iso_file struct */
|
||||
file = iso_file_table_lookup(t->file_table, iso);
|
||||
if ( file == NULL ) {
|
||||
file = iso_file_new(iso);
|
||||
iso_file_table_add_file(t->file_table, file);
|
||||
file->ino = ++t->ino;
|
||||
} else {
|
||||
/* increment number of hard-links */
|
||||
file->nlink++;
|
||||
}
|
||||
|
||||
ret->attrib.st_nlink = file->nlink;
|
||||
ret->attrib.st_ino = file->ino;
|
||||
ret->info.file = file;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ecma119_tree_node*
|
||||
create_placeholder(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct ecma119_tree_node *real)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
|
||||
assert(t && real && real->type == ECMA119_DIR
|
||||
&& parent && parent->type == ECMA119_DIR);
|
||||
|
||||
ret = calloc(1, sizeof(struct ecma119_tree_node));
|
||||
ret->iso_name = real->iso_name; /* TODO strdup? */
|
||||
/* FIXME
|
||||
* if we strdup above, if name changes in mangle_all,
|
||||
* this probably keeps as original.
|
||||
* if not, both change, but we need to update dirent_len.
|
||||
* I think that attributes of a placeholder must be taken from
|
||||
* real_me, not keept here.
|
||||
* FIXME
|
||||
* Another question is that real is a dir, while placeholder is
|
||||
* a file, and ISO name restricctions are different, what to do?
|
||||
*/
|
||||
ret->dirent_len = real->dirent_len;
|
||||
ret->attrib = real->attrib;
|
||||
ret->full_name = strdup(real->full_name);
|
||||
ret->target = t;
|
||||
ret->parent = parent;
|
||||
ret->type = ECMA119_PLACEHOLDER;
|
||||
ret->info.real_me = real;
|
||||
ret->attrib.st_nlink = 1;
|
||||
ret->attrib.st_ino = ++t->ino;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ecma119_tree_node*
|
||||
create_symlink(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node_symlink *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
|
||||
assert(t && iso && parent && parent->type == ECMA119_DIR);
|
||||
|
||||
ret = calloc(1, sizeof(struct ecma119_tree_node));
|
||||
ret->name = iso->name ? ((t->iso_level == 1) ? iso_1_fileid(iso->name)
|
||||
: iso_2_fileid(iso->name))
|
||||
ret = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||
ret->iso_name = iso->node.name ? ((t->iso_level == 1) ?
|
||||
iso_1_fileid(iso->node.name, t->input_charset)
|
||||
: iso_2_fileid(iso->node.name, t->input_charset))
|
||||
: NULL;
|
||||
ret->dirent_len = calc_dirent_len(ret);
|
||||
ret->parent = parent;
|
||||
ret->iso_self = iso;
|
||||
ret->target = t;
|
||||
ret->type = ECMA119_FILE;
|
||||
ret->type = ECMA119_SYMLINK;
|
||||
ret->info.dest = iso->dest; /* TODO strdup? */
|
||||
ret->attrib.st_nlink = 1;
|
||||
ret->attrib.st_ino = ++t->ino;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -68,15 +205,41 @@ create_tree(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
size_t i;
|
||||
struct ecma119_tree_node *ret = NULL;
|
||||
|
||||
assert(t && iso);
|
||||
|
||||
ret = (S_ISDIR(iso->attrib.st_mode) ? create_dir : create_file)
|
||||
(t, parent, iso);
|
||||
for (i = 0; i < iso->nchildren; i++) {
|
||||
ret->dir.children[i] = create_tree(t, ret, iso->children[i]);
|
||||
|
||||
if ( iso->hide_flags & LIBISO_HIDE_ON_RR )
|
||||
return NULL;
|
||||
|
||||
switch (iso->attrib.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
ret = create_file(t, parent, (struct iso_tree_node_file*)iso);
|
||||
break;
|
||||
case S_IFLNK:
|
||||
if ( !t->rockridge )
|
||||
printf("Can't add symlinks to a non ISO tree. Skipping %s \n",
|
||||
iso->name);
|
||||
else
|
||||
ret = create_symlink(t, parent, (struct iso_tree_node_symlink*)iso);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
{
|
||||
size_t i;
|
||||
struct iso_tree_node_dir *dir = (struct iso_tree_node_dir*)iso;
|
||||
ret = create_dir(t, parent, dir);
|
||||
for (i = 0; i < dir->nchildren; i++) {
|
||||
struct ecma119_tree_node *child;
|
||||
child = create_tree(t, ret, dir->children[i]);
|
||||
if (child)
|
||||
ret->info.dir.children[ret->info.dir.nchildren++] = child;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* should never happen */
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -87,12 +250,13 @@ ecma119_tree_free(struct ecma119_tree_node *root)
|
||||
size_t i;
|
||||
|
||||
if (root->type == ECMA119_DIR) {
|
||||
for (i=0; i < root->dir.nchildren; i++) {
|
||||
ecma119_tree_free(root->dir.children[i]);
|
||||
for (i=0; i < root->info.dir.nchildren; i++) {
|
||||
ecma119_tree_free(root->info.dir.children[i]);
|
||||
}
|
||||
free(root->dir.children);
|
||||
free(root->info.dir.children);
|
||||
}
|
||||
free(root->name);
|
||||
free(root->iso_name);
|
||||
free(root->full_name);
|
||||
free(root);
|
||||
}
|
||||
|
||||
@ -102,8 +266,8 @@ max_child_name_len(struct ecma119_tree_node *root)
|
||||
size_t ret = 0, i;
|
||||
|
||||
assert(root->type == ECMA119_DIR);
|
||||
for (i=0; i < root->dir.nchildren; i++) {
|
||||
size_t len = strlen(root->dir.children[i]->name);
|
||||
for (i=0; i < root->info.dir.nchildren; i++) {
|
||||
size_t len = strlen(root->info.dir.children[i]->iso_name);
|
||||
ret = MAX(ret, len);
|
||||
}
|
||||
return ret;
|
||||
@ -120,13 +284,11 @@ reparent(struct ecma119_tree_node *child,
|
||||
assert(child && parent && parent->type == ECMA119_DIR && child->parent);
|
||||
|
||||
/* replace the child in the original parent with a placeholder */
|
||||
for (i=0; i < child->parent->dir.nchildren; i++) {
|
||||
if (child->parent->dir.children[i] == child) {
|
||||
placeholder = create_file(child->target,
|
||||
child->parent,
|
||||
child->iso_self);
|
||||
placeholder->file.real_me = child;
|
||||
child->parent->dir.children[i] = placeholder;
|
||||
for (i=0; i < child->parent->info.dir.nchildren; i++) {
|
||||
if (child->parent->info.dir.children[i] == child) {
|
||||
placeholder = create_placeholder(child->target,
|
||||
child->parent, child);
|
||||
child->parent->info.dir.children[i] = placeholder;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
@ -135,10 +297,10 @@ reparent(struct ecma119_tree_node *child,
|
||||
|
||||
/* add the child to its new parent */
|
||||
child->parent = parent;
|
||||
parent->dir.nchildren++;
|
||||
parent->dir.children = realloc( parent->dir.children,
|
||||
sizeof(void*) * parent->dir.nchildren );
|
||||
parent->dir.children[parent->dir.nchildren-1] = child;
|
||||
parent->info.dir.nchildren++;
|
||||
parent->info.dir.children = realloc( parent->info.dir.children,
|
||||
sizeof(void*) * parent->info.dir.nchildren );
|
||||
parent->info.dir.children[parent->info.dir.nchildren-1] = child;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,28 +309,50 @@ reparent(struct ecma119_tree_node *child,
|
||||
* - each path length is at most 255 characters
|
||||
*/
|
||||
static void
|
||||
reorder_tree(struct ecma119_tree_node *root,
|
||||
reorder_tree(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *root,
|
||||
struct ecma119_tree_node *cur)
|
||||
{
|
||||
size_t max_path;
|
||||
|
||||
assert(root && cur && cur->type == ECMA119_DIR);
|
||||
|
||||
cur->dir.depth = cur->parent ? cur->parent->dir.depth + 1 : 1;
|
||||
cur->dir.path_len = cur->parent ? cur->parent->dir.path_len
|
||||
+ strlen(cur->name) : 0;
|
||||
max_path = cur->dir.path_len + cur->dir.depth + max_child_name_len(cur);
|
||||
cur->info.dir.depth = cur->parent ? cur->parent->info.dir.depth + 1 : 1;
|
||||
cur->info.dir.path_len = cur->parent ? cur->parent->info.dir.path_len
|
||||
+ strlen(cur->iso_name) : 0;
|
||||
max_path = cur->info.dir.path_len + cur->info.dir.depth
|
||||
+ max_child_name_len(cur);
|
||||
|
||||
if (cur->dir.depth > 8 || max_path > 255) {
|
||||
reparent(cur, root);
|
||||
/* we are appended to the root's children now, so there is no
|
||||
* need to recurse (the root will hit us again) */
|
||||
if (cur->info.dir.depth > 8 || max_path > 255) {
|
||||
|
||||
if (t->rockridge) {
|
||||
reparent(cur, root);
|
||||
/* we are appended to the root's children now, so there is no
|
||||
* need to recurse (the root will hit us again) */
|
||||
} else {
|
||||
/* we need to delete cur */
|
||||
size_t i,j;
|
||||
struct ecma119_tree_node *parent = cur->parent;
|
||||
|
||||
printf("Can't dirs deeper than 8 without RR. Skipping %s\n",
|
||||
cur->full_name);
|
||||
for (i=0; i < parent->info.dir.nchildren; ++i) {
|
||||
if (parent->info.dir.children[i] == cur) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert ( i < parent->info.dir.nchildren);
|
||||
for ( j = i; j < parent->info.dir.nchildren - 1; ++j)
|
||||
parent->info.dir.children[j] = parent->info.dir.children[j+1];
|
||||
parent->info.dir.nchildren--;
|
||||
ecma119_tree_free(cur);
|
||||
}
|
||||
} else {
|
||||
size_t i;
|
||||
|
||||
for (i=0; i < cur->dir.nchildren; i++) {
|
||||
if (cur->dir.children[i]->type == ECMA119_DIR)
|
||||
reorder_tree(root, cur->dir.children[i]);
|
||||
for (i=0; i < cur->info.dir.nchildren; i++) {
|
||||
if (cur->info.dir.children[i]->type == ECMA119_DIR)
|
||||
reorder_tree(t, root, cur->info.dir.children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,7 +362,7 @@ cmp_node(const void *f1, const void *f2)
|
||||
{
|
||||
struct ecma119_tree_node *f = *((struct ecma119_tree_node**)f1);
|
||||
struct ecma119_tree_node *g = *((struct ecma119_tree_node**)f2);
|
||||
return strcmp(f->name, g->name);
|
||||
return strcmp(f->iso_name, g->iso_name);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -188,10 +372,11 @@ sort_tree(struct ecma119_tree_node *root)
|
||||
|
||||
assert(root && root->type == ECMA119_DIR);
|
||||
|
||||
qsort(root->dir.children, root->dir.nchildren, sizeof(void*), cmp_node);
|
||||
for (i=0; i < root->dir.nchildren; i++) {
|
||||
if (root->dir.children[i]->type == ECMA119_DIR)
|
||||
sort_tree(root->dir.children[i]);
|
||||
qsort(root->info.dir.children, root->info.dir.nchildren,
|
||||
sizeof(void*), cmp_node);
|
||||
for (i=0; i < root->info.dir.nchildren; i++) {
|
||||
if (root->info.dir.children[i]->type == ECMA119_DIR)
|
||||
sort_tree(root->info.dir.children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,7 +431,7 @@ static void
|
||||
mangle_all(struct ecma119_tree_node *dir)
|
||||
{
|
||||
size_t i, j, k;
|
||||
struct ecma119_dir_info d = dir->dir;
|
||||
struct ecma119_dir_info d = dir->info.dir;
|
||||
size_t n_change;
|
||||
int changed;
|
||||
|
||||
@ -257,8 +442,8 @@ mangle_all(struct ecma119_tree_node *dir)
|
||||
/* find the number of consecutive equal names */
|
||||
j = 1;
|
||||
while ( i+j < d.nchildren &&
|
||||
!strcmp(d.children[i]->name,
|
||||
d.children[i+j]->name) )
|
||||
!strcmp(d.children[i]->iso_name,
|
||||
d.children[i+j]->iso_name) )
|
||||
j++;
|
||||
if (j == 1) continue;
|
||||
|
||||
@ -266,7 +451,7 @@ mangle_all(struct ecma119_tree_node *dir)
|
||||
changed = 1;
|
||||
n_change = j / 10 + 1;
|
||||
for (k=0; k < j; k++) {
|
||||
mangle_name(&(d.children[i+k]->name),
|
||||
mangle_name(&(d.children[i+k]->iso_name),
|
||||
n_change,
|
||||
dir->target->iso_level,
|
||||
k);
|
||||
@ -290,7 +475,7 @@ ecma119_tree_create(struct ecma119_write_target *t,
|
||||
struct iso_tree_node *iso_root)
|
||||
{
|
||||
t->root = create_tree(t, NULL, iso_root);
|
||||
reorder_tree(t->root, t->root);
|
||||
reorder_tree(t, t->root, t->root);
|
||||
sort_tree(t->root);
|
||||
mangle_all(t->root);
|
||||
return t->root;
|
||||
@ -305,8 +490,8 @@ ecma119_tree_print(struct ecma119_tree_node *root, int spaces)
|
||||
memset(sp, ' ', spaces);
|
||||
sp[spaces] = '\0';
|
||||
|
||||
printf("%s%s\n", sp, root->name);
|
||||
printf("%s%s\n", sp, root->iso_name);
|
||||
if (root->type == ECMA119_DIR)
|
||||
for (i=0; i < root->dir.nchildren; i++)
|
||||
ecma119_tree_print(root->dir.children[i], spaces+2);
|
||||
for (i=0; i < root->info.dir.nchildren; i++)
|
||||
ecma119_tree_print(root->info.dir.children[i], spaces+2);
|
||||
}
|
||||
|
@ -10,11 +10,18 @@
|
||||
#ifndef LIBISO_ECMA119_TREE_H
|
||||
#define LIBISO_ECMA119_TREE_H
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "file.h"
|
||||
|
||||
struct ecma119_write_target;
|
||||
struct iso_tree_node;
|
||||
|
||||
enum {
|
||||
ECMA119_FILE,
|
||||
ECMA119_DIR
|
||||
ECMA119_SYMLINK,
|
||||
ECMA119_DIR,
|
||||
ECMA119_PLACEHOLDER /**< placeholder for a relocated dir. */
|
||||
};
|
||||
|
||||
struct ecma119_dir_info {
|
||||
@ -25,6 +32,7 @@ struct ecma119_dir_info {
|
||||
* Directory Records (including SU) */
|
||||
size_t CE_len; /**< sum of the lengths of children's
|
||||
* SUSP CE areas */
|
||||
size_t block;
|
||||
|
||||
int depth;
|
||||
size_t path_len; /**< The length of a path up to, and
|
||||
@ -37,39 +45,35 @@ struct ecma119_dir_info {
|
||||
/**< The parent before relocation */
|
||||
};
|
||||
|
||||
struct ecma119_file_info
|
||||
{
|
||||
struct ecma119_tree_node *real_me;
|
||||
/**< If this is non-NULL, the file is
|
||||
* a placeholder for a relocated
|
||||
* directory and this field points to
|
||||
* that relocated directory.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* A node for a tree containing all the information necessary for writing
|
||||
* an ISO9660 volume.
|
||||
*/
|
||||
struct ecma119_tree_node
|
||||
{
|
||||
char *name; /**< in ASCII, conforming to the
|
||||
* current ISO level. */
|
||||
char *iso_name; /**< in ASCII, conforming to the
|
||||
* current ISO level. */
|
||||
char *full_name; /**< full name, in current locale (TODO put this in UTF-8?) */
|
||||
size_t dirent_len; /**< Length of the directory record,
|
||||
* not including SU. */
|
||||
size_t block;
|
||||
* not including SU. */
|
||||
|
||||
struct ecma119_tree_node *parent;
|
||||
struct iso_tree_node *iso_self;
|
||||
/*struct iso_tree_node *iso_self;*/
|
||||
struct ecma119_write_target *target;
|
||||
|
||||
struct stat attrib;
|
||||
|
||||
struct susp_info susp;
|
||||
|
||||
int type; /**< file or directory */
|
||||
/* union {*/
|
||||
int type; /**< file, symlink, directory or placeholder */
|
||||
union {
|
||||
struct iso_file *file;
|
||||
char *dest;
|
||||
struct ecma119_dir_info dir;
|
||||
struct ecma119_file_info file;
|
||||
/* };*/
|
||||
struct ecma119_tree_node *real_me; /**< this field points to
|
||||
* the relocated directory.
|
||||
*/
|
||||
} info;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,42 +1,38 @@
|
||||
#include "hash.h"
|
||||
#include "exclude.h"
|
||||
|
||||
static struct iso_hash_node *table[HASH_NODES]={0,};
|
||||
static int num=0;
|
||||
|
||||
void
|
||||
iso_exclude_add_path(const char *path)
|
||||
iso_exclude_add_path(struct iso_hash_table *table, const char *path)
|
||||
{
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
num += iso_hash_insert(table, path);
|
||||
table->num += iso_hash_insert(table->table, path);
|
||||
}
|
||||
|
||||
void
|
||||
iso_exclude_remove_path(const char *path)
|
||||
/*void
|
||||
iso_exclude_remove_path(struct iso_hash_table *table, const char *path)
|
||||
{
|
||||
if (!num || !path)
|
||||
if (!table->num || !path)
|
||||
return;
|
||||
|
||||
num -= iso_hash_remove(table, path);
|
||||
}
|
||||
table->num -= iso_hash_remove(table->table, path);
|
||||
}*/
|
||||
|
||||
void
|
||||
iso_exclude_empty(void)
|
||||
iso_exclude_empty(struct iso_hash_table *table)
|
||||
{
|
||||
if (!num)
|
||||
if (!table->num)
|
||||
return;
|
||||
|
||||
iso_hash_empty(table);
|
||||
num=0;
|
||||
iso_hash_empty(table->table);
|
||||
table->num=0;
|
||||
}
|
||||
|
||||
int
|
||||
iso_exclude_lookup(const char *path)
|
||||
iso_exclude_lookup(struct iso_hash_table *table, const char *path)
|
||||
{
|
||||
if (!num || !path)
|
||||
if (!table->num || !path)
|
||||
return 0;
|
||||
|
||||
return iso_hash_lookup(table, path);
|
||||
return iso_hash_lookup(table->table, path);
|
||||
}
|
||||
|
@ -1,12 +1,37 @@
|
||||
#ifndef ISO_EXCLUDE_H
|
||||
#define ISO_EXCLUDE_H
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
struct iso_hash_table {
|
||||
struct iso_hash_node *table[HASH_NODES];
|
||||
int num;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a path to ignore when adding a directory recursively.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*/
|
||||
int
|
||||
iso_exclude_lookup(const char *path);
|
||||
int iso_exclude_lookup(struct iso_hash_table *table, const char *path);
|
||||
|
||||
/**
|
||||
* Add the path of a file or directory to ignore when adding a directory recursively.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*/
|
||||
void iso_exclude_add_path(struct iso_hash_table *table, const char *path);
|
||||
|
||||
/**
|
||||
* Remove a path that was set to be ignored when adding a directory recusively.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*/
|
||||
//void iso_exclude_remove_path(struct iso_hash_table *table, const char *path);
|
||||
|
||||
/**
|
||||
* Remove all paths that were set to be ignored when adding a directory recusively.
|
||||
*/
|
||||
void iso_exclude_empty(struct iso_hash_table *table);
|
||||
|
||||
#endif /* ISO_EXCLUDE */
|
||||
|
@ -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-> |