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.c \
|
||||||
libisofs/exclude.h \
|
libisofs/exclude.h \
|
||||||
libisofs/hash.h \
|
libisofs/hash.h \
|
||||||
libisofs/hash.c
|
libisofs/hash.c \
|
||||||
|
libisofs/file.h \
|
||||||
|
libisofs/file.c
|
||||||
|
|
||||||
libinclude_HEADERS = \
|
libinclude_HEADERS = \
|
||||||
libisofs/libisofs.h
|
libisofs/libisofs.h
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "volume.h"
|
#include "volume.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "file.h"
|
||||||
#include "libisofs.h"
|
#include "libisofs.h"
|
||||||
#include "libburn/libburn.h"
|
#include "libburn/libburn.h"
|
||||||
|
|
||||||
@ -101,30 +102,35 @@ add_susp_fields_rec(struct ecma119_write_target *t,
|
|||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (!node->iso_self)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rrip_add_PX(t, node);
|
rrip_add_PX(t, node);
|
||||||
rrip_add_NM(t, node);
|
rrip_add_NM(t, node);
|
||||||
rrip_add_TF(t, node);
|
rrip_add_TF(t, node);
|
||||||
if (node->iso_self->attrib.st_rdev)
|
|
||||||
rrip_add_PN(t, node);
|
switch (node->type) {
|
||||||
if (S_ISLNK(node->iso_self->attrib.st_mode))
|
case ECMA119_FILE:
|
||||||
|
break;
|
||||||
|
case ECMA119_SYMLINK:
|
||||||
rrip_add_SL(t, node);
|
rrip_add_SL(t, node);
|
||||||
if (node->type == ECMA119_FILE && node->file.real_me)
|
break;
|
||||||
rrip_add_CL(t, node);
|
case ECMA119_DIR:
|
||||||
if (node->type == ECMA119_DIR
|
if (node->info.dir.real_parent != node->parent) {
|
||||||
&& node->dir.real_parent != node->parent) {
|
|
||||||
rrip_add_RE(t, node);
|
rrip_add_RE(t, node);
|
||||||
rrip_add_PL(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);
|
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
|
static void
|
||||||
@ -151,35 +157,35 @@ calc_dir_size(struct ecma119_write_target *t,
|
|||||||
assert(dir->type == ECMA119_DIR);
|
assert(dir->type == ECMA119_DIR);
|
||||||
|
|
||||||
t->dirlist_len++;
|
t->dirlist_len++;
|
||||||
dir->dir.len = 34 + dir->dir.self_susp.non_CE_len
|
dir->info.dir.len = 34 + dir->info.dir.self_susp.non_CE_len
|
||||||
+ 34 + dir->dir.parent_susp.non_CE_len;
|
+ 34 + dir->info.dir.parent_susp.non_CE_len;
|
||||||
dir->dir.CE_len = dir->dir.self_susp.CE_len
|
dir->info.dir.CE_len = dir->info.dir.self_susp.CE_len
|
||||||
+ dir->dir.parent_susp.CE_len;
|
+ dir->info.dir.parent_susp.CE_len;
|
||||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
for (i = 0; i < dir->info.dir.nchildren; ++i) {
|
||||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||||
|
|
||||||
newlen = dir->dir.len + ch->dirent_len + ch->susp.non_CE_len;
|
newlen = dir->info.dir.len + ch->dirent_len + ch->susp.non_CE_len;
|
||||||
if ((newlen % 2048) < (dir->dir.len % 2048)) {
|
if ((newlen % 2048) < (dir->info.dir.len % 2048)) {
|
||||||
dir->dir.len = newlen + (2048 - (dir->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->info.dir.CE_len += ch->susp.CE_len;
|
||||||
dir->dir.len += ch->dirent_len + ch->susp.non_CE_len;
|
|
||||||
}
|
}
|
||||||
dir->dir.CE_len += ch->susp.CE_len;
|
t->total_dir_size += round_up(dir->info.dir.len + dir->info.dir.CE_len,
|
||||||
}
|
|
||||||
t->total_dir_size += round_up(dir->dir.len + dir->dir.CE_len,
|
|
||||||
t->block_size);
|
t->block_size);
|
||||||
|
|
||||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||||
struct iso_tree_node *iso = ch->iso_self;
|
//struct iso_tree_node *iso = ch->iso_self;
|
||||||
if (ch->type == ECMA119_DIR) {
|
if (ch->type == ECMA119_DIR) {
|
||||||
calc_dir_size(t, ch);
|
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);
|
assert(dir->type == ECMA119_DIR);
|
||||||
|
|
||||||
/* we don't need to set iso_self->block since each tree writes
|
dir->info.dir.block = t->curblock;
|
||||||
* its own directories */
|
t->curblock += div_up(dir->info.dir.len + dir->info.dir.CE_len, t->block_size);
|
||||||
dir->block = t->curblock;
|
|
||||||
t->curblock += div_up(dir->dir.len + dir->dir.CE_len, t->block_size);
|
|
||||||
t->dirlist[t->curfile++] = dir;
|
t->dirlist[t->curfile++] = dir;
|
||||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||||
if (ch->type == ECMA119_DIR)
|
if (ch->type == ECMA119_DIR)
|
||||||
calc_dir_pos(t, ch);
|
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
|
* Fill out the block field for each file and fill out t->filelist.
|
||||||
* out t->filelist.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
calc_file_pos(struct ecma119_write_target *t,
|
calc_file_pos(struct ecma119_write_target *t,
|
||||||
@ -224,31 +231,40 @@ calc_file_pos(struct ecma119_write_target *t,
|
|||||||
|
|
||||||
assert(dir->type == ECMA119_DIR);
|
assert(dir->type == ECMA119_DIR);
|
||||||
|
|
||||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
t->filelist = calloc(1, sizeof(struct iso_file *) * t->file_table->count);
|
||||||
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;
|
|
||||||
|
|
||||||
iso->block = ch->block = t->curblock;
|
for (i = 0; i < FILE_HASH_NODES; ++i) {
|
||||||
t->curblock += div_up(size, t->block_size);
|
|
||||||
if (size && iso->loc.type == LIBISO_FILESYS
|
struct iso_file_hash_node *node;
|
||||||
&& 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++) {
|
t->filelist_len = t->curfile;
|
||||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
|
||||||
if (ch->type == ECMA119_DIR)
|
/* sort */
|
||||||
calc_file_pos(t, ch);
|
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 */
|
/* reset curfile when we're finished */
|
||||||
if (!dir->parent) {
|
|
||||||
t->curfile = 0;
|
t->curfile = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
struct ecma119_write_target*
|
struct ecma119_write_target*
|
||||||
ecma119_target_new(struct iso_volset *volset,
|
ecma119_target_new(struct iso_volset *volset,
|
||||||
@ -259,33 +275,48 @@ ecma119_target_new(struct iso_volset *volset,
|
|||||||
struct ecma119_write_target *t =
|
struct ecma119_write_target *t =
|
||||||
calloc(1, sizeof(struct ecma119_write_target));
|
calloc(1, sizeof(struct ecma119_write_target));
|
||||||
size_t i, j, cur;
|
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++;
|
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->joliet = (flags & ECMA119_JOLIET) ? 1 : 0;
|
||||||
|
|
||||||
|
t->root = ecma119_tree_create(t, iso_root);
|
||||||
if (t->joliet)
|
if (t->joliet)
|
||||||
t->joliet_root = joliet_tree_create(t, iso_root);
|
t->joliet_root = joliet_tree_create(t, iso_root);
|
||||||
t->volset = volset;
|
t->volset = volset;
|
||||||
t->volnum = volnum;
|
t->volnum = volnum;
|
||||||
t->now = time(NULL);
|
t->now = time(NULL);
|
||||||
|
|
||||||
t->rockridge = (flags & ECMA119_ROCKRIDGE) ? 1 : 0;
|
|
||||||
t->iso_level = level;
|
|
||||||
t->block_size = 2048;
|
|
||||||
|
|
||||||
if (t->rockridge)
|
if (t->rockridge)
|
||||||
add_susp_fields(t);
|
add_susp_fields(t);
|
||||||
|
|
||||||
calc_dir_size(t, t->root);
|
calc_dir_size(t, t->root);
|
||||||
if (t->joliet) {
|
if (t->joliet) {
|
||||||
joliet_calc_dir_size(t, t->joliet_root);
|
joliet_calc_dir_size(t, t->joliet_root);
|
||||||
t->pathlist_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);
|
t->dirlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len_joliet);
|
||||||
}
|
}
|
||||||
|
|
||||||
t->dirlist = calloc(1, sizeof(void*) * t->dirlist_len);
|
t->dirlist = calloc(1, sizeof(void*) * t->dirlist_len);
|
||||||
t->pathlist = 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 */
|
/* fill out the pathlist */
|
||||||
t->pathlist[0] = t->root;
|
t->pathlist[0] = t->root;
|
||||||
@ -293,10 +324,10 @@ ecma119_target_new(struct iso_volset *volset,
|
|||||||
cur = 1;
|
cur = 1;
|
||||||
for (i = 0; i < t->dirlist_len; i++) {
|
for (i = 0; i < t->dirlist_len; i++) {
|
||||||
struct ecma119_tree_node *dir = t->pathlist[i];
|
struct ecma119_tree_node *dir = t->pathlist[i];
|
||||||
for (j = 0; j < dir->dir.nchildren; j++) {
|
for (j = 0; j < dir->info.dir.nchildren; j++) {
|
||||||
struct ecma119_tree_node *ch = dir->dir.children[j];
|
struct ecma119_tree_node *ch = dir->info.dir.children[j];
|
||||||
if (ch->type == ECMA119_DIR) {
|
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->pathlist[cur++] = ch;
|
||||||
t->path_table_size += len + len % 2;
|
t->path_table_size += len + len % 2;
|
||||||
}
|
}
|
||||||
@ -323,11 +354,19 @@ ecma119_target_new(struct iso_volset *volset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
calc_dir_pos(t, t->root);
|
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);
|
joliet_calc_dir_pos(t, t->joliet_root);
|
||||||
|
|
||||||
|
/* reset curfile when we're finished */
|
||||||
|
t->curfile = 0;
|
||||||
|
}
|
||||||
calc_file_pos(t, t->root);
|
calc_file_pos(t, t->root);
|
||||||
if (t->joliet)
|
//if (t->joliet)
|
||||||
joliet_update_file_pos (t, t->joliet_root);
|
// joliet_update_file_pos (t, t->joliet_root);
|
||||||
|
|
||||||
if (t->rockridge) {
|
if (t->rockridge) {
|
||||||
susp_finalize(t, t->root);
|
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;
|
struct state_files *f_st = &t->state_files;
|
||||||
size_t nread;
|
size_t nread;
|
||||||
struct ecma119_tree_node *f = t->filelist[f_st->file];
|
struct iso_file *f = t->filelist[f_st->file];
|
||||||
const char *path = f->iso_self->loc.path;
|
const char *path = f->path;
|
||||||
|
|
||||||
|
|
||||||
if (!f_st->fd) {
|
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");
|
f_st->fd = fopen(path, "r");
|
||||||
if (!f_st->fd)
|
if (!f_st->fd)
|
||||||
err(1, "couldn't open %s for reading", path);
|
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 ecma119_pri_vol_desc *vol = (struct ecma119_pri_vol_desc*)buf;
|
||||||
struct iso_volume *volume = t->volset->volume[t->volnum];
|
struct iso_volume *volume = t->volset->volume[t->volnum];
|
||||||
char *vol_id = str2d_char(volume->volume_id);
|
char *vol_id = str2d_char(volume->volume_id, t->input_charset);
|
||||||
char *pub_id = str2a_char(volume->publisher_id);
|
char *pub_id = str2a_char(volume->publisher_id, t->input_charset);
|
||||||
char *data_id = str2a_char(volume->data_preparer_id);
|
char *data_id = str2a_char(volume->data_preparer_id, t->input_charset);
|
||||||
char *volset_id = str2d_char(t->volset->volset_id);
|
char *volset_id = str2d_char(t->volset->volset_id, t->input_charset);
|
||||||
|
|
||||||
char *system_id = str2a_char(volume->system_id);
|
char *system_id = str2a_char(volume->system_id, t->input_charset);
|
||||||
char *application_id = str2a_char(volume->application_id);
|
char *application_id = str2a_char(volume->application_id, t->input_charset);
|
||||||
char *copyright_file_id = str2d_char(volume->copyright_file_id);
|
char *copyright_file_id = str2d_char(volume->copyright_file_id, t->input_charset);
|
||||||
char *abstract_file_id = str2d_char(volume->abstract_file_id);
|
char *abstract_file_id = str2d_char(volume->abstract_file_id, t->input_charset);
|
||||||
char *biblio_file_id = str2d_char(volume->biblio_file_id);
|
char *biblio_file_id = str2d_char(volume->biblio_file_id, t->input_charset);
|
||||||
|
|
||||||
vol->vol_desc_type[0] = 1;
|
vol->vol_desc_type[0] = 1;
|
||||||
memcpy(vol->std_identifier, "CD001", 5);
|
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++) {
|
for (i = 0; i < t->dirlist_len; i++) {
|
||||||
dir = t->pathlist[i];
|
dir = t->pathlist[i];
|
||||||
|
assert(dir->type == ECMA119_DIR);
|
||||||
while ((i) && t->pathlist[parent] != dir->parent)
|
while ((i) && t->pathlist[parent] != dir->parent)
|
||||||
parent++;
|
parent++;
|
||||||
assert(parent < i || i == 0);
|
assert(parent < i || i == 0);
|
||||||
|
|
||||||
rec = (struct ecma119_path_table_record*) buf;
|
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;
|
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);
|
write_int(rec->parent, parent + 1, 2);
|
||||||
if (dir->parent)
|
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);
|
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,
|
int file_id,
|
||||||
uint8_t *buf)
|
uint8_t *buf)
|
||||||
{
|
{
|
||||||
|
uint32_t len;
|
||||||
|
uint32_t block;
|
||||||
uint8_t len_dr = (file_id >= 0) ? 34 : node->dirent_len;
|
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 f_id = (uint8_t) ((file_id == 3) ? 0 : file_id);
|
||||||
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->name;
|
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->iso_name;
|
||||||
uint32_t len = (node->type == ECMA119_DIR) ? node->dir.len
|
|
||||||
: node->file.real_me ? 0 : node->iso_self->attrib.st_size;
|
|
||||||
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
|
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 */
|
/* we don't write out susp fields for the root node */
|
||||||
if (t->rockridge) {
|
if (t->rockridge) {
|
||||||
if (file_id == 0) {
|
if (file_id == 0) {
|
||||||
susp_write(t, &node->dir.self_susp, &buf[len_dr]);
|
assert(node->type == ECMA119_DIR);
|
||||||
len_dr += node->dir.self_susp.non_CE_len;
|
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) {
|
} else if (file_id == 1) {
|
||||||
susp_write(t, &node->dir.parent_susp, &buf[len_dr]);
|
assert(node->type == ECMA119_DIR);
|
||||||
len_dr += node->dir.parent_susp.non_CE_len;
|
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) {
|
} else if (file_id < 0) {
|
||||||
susp_write(t, &node->susp, &buf[len_dr]);
|
susp_write(t, &node->susp, &buf[len_dr]);
|
||||||
len_dr += node->susp.non_CE_len;
|
len_dr += node->susp.non_CE_len;
|
||||||
@ -583,7 +639,7 @@ write_one_dir_record(struct ecma119_write_target *t,
|
|||||||
node = node->parent;
|
node = node->parent;
|
||||||
|
|
||||||
rec->len_dr[0] = len_dr;
|
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_bb(rec->length, len, 4);
|
||||||
iso_datetime_7(rec->recording_time, t->now);
|
iso_datetime_7(rec->recording_time, t->now);
|
||||||
rec->flags[0] = (node->type == ECMA119_DIR) ? 2 : 0;
|
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);
|
write_one_dir_record(t, dir, 1, buf);
|
||||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||||
|
|
||||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||||
write_one_dir_record(t, dir->dir.children[i], -1, buf);
|
write_one_dir_record(t, dir->info.dir.children[i], -1, buf);
|
||||||
len = ((struct ecma119_dir_record*) buf)->len_dr[0];
|
len = ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||||
if ((buf + len - prior_buf) >= 2048) {
|
if ((buf + len - prior_buf) >= 2048) {
|
||||||
for (j = len - 1; j >= 0; j--) {
|
for (j = len - 1; j >= 0; j--) {
|
||||||
@ -629,16 +685,16 @@ write_one_dir(struct ecma119_write_target *t,
|
|||||||
|
|
||||||
/* write the susp continuation areas */
|
/* write the susp continuation areas */
|
||||||
if (t->rockridge) {
|
if (t->rockridge) {
|
||||||
susp_write_CE(t, &dir->dir.self_susp, buf);
|
susp_write_CE(t, &dir->info.dir.self_susp, buf);
|
||||||
buf += dir->dir.self_susp.CE_len;
|
buf += dir->info.dir.self_susp.CE_len;
|
||||||
susp_write_CE(t, &dir->dir.parent_susp, buf);
|
susp_write_CE(t, &dir->info.dir.parent_susp, buf);
|
||||||
buf += dir->dir.parent_susp.CE_len;
|
buf += dir->info.dir.parent_susp.CE_len;
|
||||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||||
susp_write_CE(t, &dir->dir.children[i]->susp, buf);
|
susp_write_CE(t, &dir->info.dir.children[i]->susp, buf);
|
||||||
buf += dir->dir.children[i]->susp.CE_len;
|
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
|
static void
|
||||||
@ -649,7 +705,7 @@ write_dirs(struct ecma119_write_target *t, uint8_t *buf)
|
|||||||
for (i = 0; i < t->dirlist_len; i++) {
|
for (i = 0; i < t->dirlist_len; i++) {
|
||||||
dir = t->dirlist[i];
|
dir = t->dirlist[i];
|
||||||
write_one_dir(t, dir, buf);
|
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;
|
struct ecma119_write_target *t = (struct ecma119_write_target*)bs->data;
|
||||||
ecma119_tree_free(t->root);
|
ecma119_tree_free(t->root);
|
||||||
|
iso_file_table_clear(t->file_table);
|
||||||
|
|
||||||
|
//FIXME free joliet tree
|
||||||
free(t->dirlist);
|
free(t->dirlist);
|
||||||
free(t->pathlist);
|
free(t->pathlist);
|
||||||
free(t->dirlist_joliet);
|
free(t->dirlist_joliet);
|
||||||
|
@ -62,6 +62,35 @@ struct ecma119_write_target
|
|||||||
unsigned int joliet:1;
|
unsigned int joliet:1;
|
||||||
unsigned int iso_level:2;
|
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;
|
int curblock;
|
||||||
uint16_t block_size;
|
uint16_t block_size;
|
||||||
uint32_t path_table_size;
|
uint32_t path_table_size;
|
||||||
@ -86,10 +115,13 @@ struct ecma119_write_target
|
|||||||
size_t dirlist_len; /**< The length of the previous 2 lists.
|
size_t dirlist_len; /**< The length of the previous 2 lists.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct ecma119_tree_node **filelist;
|
|
||||||
/**< A pre-order list of files with
|
struct iso_file_table *file_table;
|
||||||
* non-NULL paths and non-zero sizes.
|
/**<
|
||||||
|
* 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. */
|
size_t filelist_len; /* Length of the previous list. */
|
||||||
|
|
||||||
int curfile; /**< Used as a helper field for writing
|
int curfile; /**< Used as a helper field for writing
|
||||||
@ -102,6 +134,8 @@ struct ecma119_write_target
|
|||||||
struct joliet_tree_node **dirlist_joliet;
|
struct joliet_tree_node **dirlist_joliet;
|
||||||
struct joliet_tree_node **pathlist_joliet;
|
struct joliet_tree_node **pathlist_joliet;
|
||||||
|
|
||||||
|
size_t dirlist_len_joliet;
|
||||||
|
|
||||||
enum ecma119_write_state state; /* The current state of the writer. */
|
enum ecma119_write_state state; /* The current state of the writer. */
|
||||||
|
|
||||||
/* Most writers work by
|
/* Most writers work by
|
||||||
|
@ -12,54 +12,191 @@
|
|||||||
|
|
||||||
static size_t calc_dirent_len(struct ecma119_tree_node *n)
|
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++;
|
if (ret % 2) ret++;
|
||||||
return 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*
|
static struct ecma119_tree_node*
|
||||||
create_dir(struct ecma119_write_target *t,
|
create_dir(struct ecma119_write_target *t,
|
||||||
struct ecma119_tree_node *parent,
|
struct ecma119_tree_node *parent,
|
||||||
struct iso_tree_node *iso)
|
struct iso_tree_node_dir *iso)
|
||||||
{
|
{
|
||||||
struct ecma119_tree_node *ret;
|
struct ecma119_tree_node *ret;
|
||||||
|
|
||||||
assert(t && (!parent || parent->type == ECMA119_DIR)
|
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 = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||||
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->type = ECMA119_DIR;
|
ret->type = ECMA119_DIR;
|
||||||
ret->parent = ret->dir.real_parent = parent;
|
ret->info.dir.real_parent = parent;
|
||||||
ret->dir.depth = parent ? parent->dir.depth + 1 : 1;
|
ret->info.dir.depth = parent ? parent->info.dir.depth + 1 : 1;
|
||||||
ret->dir.nchildren = iso->nchildren;
|
ret->info.dir.nchildren = 0;
|
||||||
ret->dir.children = calloc(1, sizeof(void*) * iso->nchildren);
|
ret->info.dir.children = calloc(1, sizeof(void*) * iso->nchildren);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ecma119_tree_node*
|
static struct ecma119_tree_node*
|
||||||
create_file(struct ecma119_write_target *t,
|
create_file(struct ecma119_write_target *t,
|
||||||
struct ecma119_tree_node *parent,
|
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;
|
struct ecma119_tree_node *ret;
|
||||||
|
|
||||||
assert(t && iso && parent && parent->type == ECMA119_DIR);
|
assert(t && iso && parent && parent->type == ECMA119_DIR);
|
||||||
|
|
||||||
ret = calloc(1, sizeof(struct ecma119_tree_node));
|
ret = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||||
ret->name = iso->name ? ((t->iso_level == 1) ? iso_1_fileid(iso->name)
|
ret->iso_name = iso->node.name ? ((t->iso_level == 1) ?
|
||||||
: iso_2_fileid(iso->name))
|
iso_1_fileid(iso->node.name, t->input_charset)
|
||||||
|
: iso_2_fileid(iso->node.name, t->input_charset))
|
||||||
: NULL;
|
: NULL;
|
||||||
ret->dirent_len = calc_dirent_len(ret);
|
ret->type = ECMA119_SYMLINK;
|
||||||
ret->parent = parent;
|
ret->info.dest = iso->dest; /* TODO strdup? */
|
||||||
ret->iso_self = iso;
|
ret->attrib.st_nlink = 1;
|
||||||
ret->target = t;
|
ret->attrib.st_ino = ++t->ino;
|
||||||
ret->type = ECMA119_FILE;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,15 +205,41 @@ create_tree(struct ecma119_write_target *t,
|
|||||||
struct ecma119_tree_node *parent,
|
struct ecma119_tree_node *parent,
|
||||||
struct iso_tree_node *iso)
|
struct iso_tree_node *iso)
|
||||||
{
|
{
|
||||||
struct ecma119_tree_node *ret;
|
struct ecma119_tree_node *ret = NULL;
|
||||||
size_t i;
|
|
||||||
|
|
||||||
assert(t && iso);
|
assert(t && iso);
|
||||||
|
|
||||||
ret = (S_ISDIR(iso->attrib.st_mode) ? create_dir : create_file)
|
if ( iso->hide_flags & LIBISO_HIDE_ON_RR )
|
||||||
(t, parent, iso);
|
return NULL;
|
||||||
for (i = 0; i < iso->nchildren; i++) {
|
|
||||||
ret->dir.children[i] = create_tree(t, ret, iso->children[i]);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -87,12 +250,13 @@ ecma119_tree_free(struct ecma119_tree_node *root)
|
|||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (root->type == ECMA119_DIR) {
|
if (root->type == ECMA119_DIR) {
|
||||||
for (i=0; i < root->dir.nchildren; i++) {
|
for (i=0; i < root->info.dir.nchildren; i++) {
|
||||||
ecma119_tree_free(root->dir.children[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);
|
free(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,8 +266,8 @@ max_child_name_len(struct ecma119_tree_node *root)
|
|||||||
size_t ret = 0, i;
|
size_t ret = 0, i;
|
||||||
|
|
||||||
assert(root->type == ECMA119_DIR);
|
assert(root->type == ECMA119_DIR);
|
||||||
for (i=0; i < root->dir.nchildren; i++) {
|
for (i=0; i < root->info.dir.nchildren; i++) {
|
||||||
size_t len = strlen(root->dir.children[i]->name);
|
size_t len = strlen(root->info.dir.children[i]->iso_name);
|
||||||
ret = MAX(ret, len);
|
ret = MAX(ret, len);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -120,13 +284,11 @@ reparent(struct ecma119_tree_node *child,
|
|||||||
assert(child && parent && parent->type == ECMA119_DIR && child->parent);
|
assert(child && parent && parent->type == ECMA119_DIR && child->parent);
|
||||||
|
|
||||||
/* replace the child in the original parent with a placeholder */
|
/* replace the child in the original parent with a placeholder */
|
||||||
for (i=0; i < child->parent->dir.nchildren; i++) {
|
for (i=0; i < child->parent->info.dir.nchildren; i++) {
|
||||||
if (child->parent->dir.children[i] == child) {
|
if (child->parent->info.dir.children[i] == child) {
|
||||||
placeholder = create_file(child->target,
|
placeholder = create_placeholder(child->target,
|
||||||
child->parent,
|
child->parent, child);
|
||||||
child->iso_self);
|
child->parent->info.dir.children[i] = placeholder;
|
||||||
placeholder->file.real_me = child;
|
|
||||||
child->parent->dir.children[i] = placeholder;
|
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -135,10 +297,10 @@ reparent(struct ecma119_tree_node *child,
|
|||||||
|
|
||||||
/* add the child to its new parent */
|
/* add the child to its new parent */
|
||||||
child->parent = parent;
|
child->parent = parent;
|
||||||
parent->dir.nchildren++;
|
parent->info.dir.nchildren++;
|
||||||
parent->dir.children = realloc( parent->dir.children,
|
parent->info.dir.children = realloc( parent->info.dir.children,
|
||||||
sizeof(void*) * parent->dir.nchildren );
|
sizeof(void*) * parent->info.dir.nchildren );
|
||||||
parent->dir.children[parent->dir.nchildren-1] = child;
|
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
|
* - each path length is at most 255 characters
|
||||||
*/
|
*/
|
||||||
static void
|
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)
|
struct ecma119_tree_node *cur)
|
||||||
{
|
{
|
||||||
size_t max_path;
|
size_t max_path;
|
||||||
|
|
||||||
assert(root && cur && cur->type == ECMA119_DIR);
|
assert(root && cur && cur->type == ECMA119_DIR);
|
||||||
|
|
||||||
cur->dir.depth = cur->parent ? cur->parent->dir.depth + 1 : 1;
|
cur->info.dir.depth = cur->parent ? cur->parent->info.dir.depth + 1 : 1;
|
||||||
cur->dir.path_len = cur->parent ? cur->parent->dir.path_len
|
cur->info.dir.path_len = cur->parent ? cur->parent->info.dir.path_len
|
||||||
+ strlen(cur->name) : 0;
|
+ strlen(cur->iso_name) : 0;
|
||||||
max_path = cur->dir.path_len + cur->dir.depth + max_child_name_len(cur);
|
max_path = cur->info.dir.path_len + cur->info.dir.depth
|
||||||
|
+ max_child_name_len(cur);
|
||||||
|
|
||||||
if (cur->dir.depth > 8 || max_path > 255) {
|
if (cur->info.dir.depth > 8 || max_path > 255) {
|
||||||
|
|
||||||
|
if (t->rockridge) {
|
||||||
reparent(cur, root);
|
reparent(cur, root);
|
||||||
/* we are appended to the root's children now, so there is no
|
/* we are appended to the root's children now, so there is no
|
||||||
* need to recurse (the root will hit us again) */
|
* 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 {
|
} else {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i=0; i < cur->dir.nchildren; i++) {
|
for (i=0; i < cur->info.dir.nchildren; i++) {
|
||||||
if (cur->dir.children[i]->type == ECMA119_DIR)
|
if (cur->info.dir.children[i]->type == ECMA119_DIR)
|
||||||
reorder_tree(root, cur->dir.children[i]);
|
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 *f = *((struct ecma119_tree_node**)f1);
|
||||||
struct ecma119_tree_node *g = *((struct ecma119_tree_node**)f2);
|
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
|
static void
|
||||||
@ -188,10 +372,11 @@ sort_tree(struct ecma119_tree_node *root)
|
|||||||
|
|
||||||
assert(root && root->type == ECMA119_DIR);
|
assert(root && root->type == ECMA119_DIR);
|
||||||
|
|
||||||
qsort(root->dir.children, root->dir.nchildren, sizeof(void*), cmp_node);
|
qsort(root->info.dir.children, root->info.dir.nchildren,
|
||||||
for (i=0; i < root->dir.nchildren; i++) {
|
sizeof(void*), cmp_node);
|
||||||
if (root->dir.children[i]->type == ECMA119_DIR)
|
for (i=0; i < root->info.dir.nchildren; i++) {
|
||||||
sort_tree(root->dir.children[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)
|
mangle_all(struct ecma119_tree_node *dir)
|
||||||
{
|
{
|
||||||
size_t i, j, k;
|
size_t i, j, k;
|
||||||
struct ecma119_dir_info d = dir->dir;
|
struct ecma119_dir_info d = dir->info.dir;
|
||||||
size_t n_change;
|
size_t n_change;
|
||||||
int changed;
|
int changed;
|
||||||
|
|
||||||
@ -257,8 +442,8 @@ mangle_all(struct ecma119_tree_node *dir)
|
|||||||
/* find the number of consecutive equal names */
|
/* find the number of consecutive equal names */
|
||||||
j = 1;
|
j = 1;
|
||||||
while ( i+j < d.nchildren &&
|
while ( i+j < d.nchildren &&
|
||||||
!strcmp(d.children[i]->name,
|
!strcmp(d.children[i]->iso_name,
|
||||||
d.children[i+j]->name) )
|
d.children[i+j]->iso_name) )
|
||||||
j++;
|
j++;
|
||||||
if (j == 1) continue;
|
if (j == 1) continue;
|
||||||
|
|
||||||
@ -266,7 +451,7 @@ mangle_all(struct ecma119_tree_node *dir)
|
|||||||
changed = 1;
|
changed = 1;
|
||||||
n_change = j / 10 + 1;
|
n_change = j / 10 + 1;
|
||||||
for (k=0; k < j; k++) {
|
for (k=0; k < j; k++) {
|
||||||
mangle_name(&(d.children[i+k]->name),
|
mangle_name(&(d.children[i+k]->iso_name),
|
||||||
n_change,
|
n_change,
|
||||||
dir->target->iso_level,
|
dir->target->iso_level,
|
||||||
k);
|
k);
|
||||||
@ -290,7 +475,7 @@ ecma119_tree_create(struct ecma119_write_target *t,
|
|||||||
struct iso_tree_node *iso_root)
|
struct iso_tree_node *iso_root)
|
||||||
{
|
{
|
||||||
t->root = create_tree(t, NULL, 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);
|
sort_tree(t->root);
|
||||||
mangle_all(t->root);
|
mangle_all(t->root);
|
||||||
return t->root;
|
return t->root;
|
||||||
@ -305,8 +490,8 @@ ecma119_tree_print(struct ecma119_tree_node *root, int spaces)
|
|||||||
memset(sp, ' ', spaces);
|
memset(sp, ' ', spaces);
|
||||||
sp[spaces] = '\0';
|
sp[spaces] = '\0';
|
||||||
|
|
||||||
printf("%s%s\n", sp, root->name);
|
printf("%s%s\n", sp, root->iso_name);
|
||||||
if (root->type == ECMA119_DIR)
|
if (root->type == ECMA119_DIR)
|
||||||
for (i=0; i < root->dir.nchildren; i++)
|
for (i=0; i < root->info.dir.nchildren; i++)
|
||||||
ecma119_tree_print(root->dir.children[i], spaces+2);
|
ecma119_tree_print(root->info.dir.children[i], spaces+2);
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,18 @@
|
|||||||
#ifndef LIBISO_ECMA119_TREE_H
|
#ifndef LIBISO_ECMA119_TREE_H
|
||||||
#define LIBISO_ECMA119_TREE_H
|
#define LIBISO_ECMA119_TREE_H
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
struct ecma119_write_target;
|
struct ecma119_write_target;
|
||||||
|
struct iso_tree_node;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ECMA119_FILE,
|
ECMA119_FILE,
|
||||||
ECMA119_DIR
|
ECMA119_SYMLINK,
|
||||||
|
ECMA119_DIR,
|
||||||
|
ECMA119_PLACEHOLDER /**< placeholder for a relocated dir. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ecma119_dir_info {
|
struct ecma119_dir_info {
|
||||||
@ -25,6 +32,7 @@ struct ecma119_dir_info {
|
|||||||
* Directory Records (including SU) */
|
* Directory Records (including SU) */
|
||||||
size_t CE_len; /**< sum of the lengths of children's
|
size_t CE_len; /**< sum of the lengths of children's
|
||||||
* SUSP CE areas */
|
* SUSP CE areas */
|
||||||
|
size_t block;
|
||||||
|
|
||||||
int depth;
|
int depth;
|
||||||
size_t path_len; /**< The length of a path up to, and
|
size_t path_len; /**< The length of a path up to, and
|
||||||
@ -37,39 +45,35 @@ struct ecma119_dir_info {
|
|||||||
/**< The parent before relocation */
|
/**< 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
|
* A node for a tree containing all the information necessary for writing
|
||||||
* an ISO9660 volume.
|
* an ISO9660 volume.
|
||||||
*/
|
*/
|
||||||
struct ecma119_tree_node
|
struct ecma119_tree_node
|
||||||
{
|
{
|
||||||
char *name; /**< in ASCII, conforming to the
|
char *iso_name; /**< in ASCII, conforming to the
|
||||||
* current ISO level. */
|
* 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,
|
size_t dirent_len; /**< Length of the directory record,
|
||||||
* not including SU. */
|
* not including SU. */
|
||||||
size_t block;
|
|
||||||
|
|
||||||
struct ecma119_tree_node *parent;
|
struct ecma119_tree_node *parent;
|
||||||
struct iso_tree_node *iso_self;
|
/*struct iso_tree_node *iso_self;*/
|
||||||
struct ecma119_write_target *target;
|
struct ecma119_write_target *target;
|
||||||
|
|
||||||
|
struct stat attrib;
|
||||||
|
|
||||||
struct susp_info susp;
|
struct susp_info susp;
|
||||||
|
|
||||||
int type; /**< file or directory */
|
int type; /**< file, symlink, directory or placeholder */
|
||||||
/* union {*/
|
union {
|
||||||
|
struct iso_file *file;
|
||||||
|
char *dest;
|
||||||
struct ecma119_dir_info dir;
|
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"
|
#include "exclude.h"
|
||||||
|
|
||||||
static struct iso_hash_node *table[HASH_NODES]={0,};
|
|
||||||
static int num=0;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
iso_exclude_add_path(const char *path)
|
iso_exclude_add_path(struct iso_hash_table *table, const char *path)
|
||||||
{
|
{
|
||||||
if (!path)
|
if (!path)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
num += iso_hash_insert(table, path);
|
table->num += iso_hash_insert(table->table, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/*void
|
||||||
iso_exclude_remove_path(const char *path)
|
iso_exclude_remove_path(struct iso_hash_table *table, const char *path)
|
||||||
{
|
{
|
||||||
if (!num || !path)
|
if (!table->num || !path)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
num -= iso_hash_remove(table, path);
|
table->num -= iso_hash_remove(table->table, path);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void
|
void
|
||||||
iso_exclude_empty(void)
|
iso_exclude_empty(struct iso_hash_table *table)
|
||||||
{
|
{
|
||||||
if (!num)
|
if (!table->num)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
iso_hash_empty(table);
|
iso_hash_empty(table->table);
|
||||||
num=0;
|
table->num=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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 0;
|
||||||
|
|
||||||
return iso_hash_lookup(table, path);
|
return iso_hash_lookup(table->table, path);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,37 @@
|
|||||||
#ifndef ISO_EXCLUDE_H
|
#ifndef ISO_EXCLUDE_H
|
||||||
#define 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.
|
* Add a path to ignore when adding a directory recursively.
|
||||||
*
|
*
|
||||||
* \param path The path, on the local filesystem, of the file.
|
* \param path The path, on the local filesystem, of the file.
|
||||||
*/
|
*/
|
||||||
int
|
int iso_exclude_lookup(struct iso_hash_table *table, const char *path);
|
||||||
iso_exclude_lookup(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 */
|
#endif /* ISO_EXCLUDE */
|
||||||
|
@ -19,33 +19,66 @@ create_node(struct ecma119_write_target *t,
|
|||||||
struct joliet_tree_node *ret =
|
struct joliet_tree_node *ret =
|
||||||
calloc(1, sizeof(struct joliet_tree_node));
|
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->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->parent = parent;
|
||||||
ret->iso_self = iso;
|
|
||||||
ret->target = t;
|
ret->target = t;
|
||||||
ret->nchildren = iso->nchildren;
|
|
||||||
if (ret->nchildren)
|
if ( ISO_ISDIR(iso) ) {
|
||||||
ret->children = calloc(sizeof(void*), ret->nchildren);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct joliet_tree_node*
|
static struct joliet_tree_node*
|
||||||
create_tree(struct ecma119_write_target *t,
|
create_tree(struct ecma119_write_target *t,
|
||||||
struct joliet_tree_node *parent,
|
struct joliet_tree_node *parent,
|
||||||
struct iso_tree_node *iso_root)
|
struct iso_tree_node *iso)
|
||||||
{
|
{
|
||||||
struct joliet_tree_node *root = create_node(t, parent, iso_root);
|
struct joliet_tree_node *root;
|
||||||
size_t i;
|
assert(t && iso);
|
||||||
|
|
||||||
for (i = 0; i < root->nchildren; i++) {
|
if ( iso->hide_flags & LIBISO_HIDE_ON_JOLIET )
|
||||||
struct iso_tree_node *iso_ch = iso_root->children[i];
|
return NULL;
|
||||||
if (ISO_ISDIR(iso_ch))
|
|
||||||
root->children[i] = create_tree(t, root, iso_ch);
|
switch (iso->attrib.st_mode & S_IFMT) {
|
||||||
else
|
case S_IFREG:
|
||||||
root->children[i] = create_node(t, root, iso_ch);
|
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;
|
return root;
|
||||||
}
|
}
|
||||||
@ -63,12 +96,15 @@ sort_tree(struct joliet_tree_node *root)
|
|||||||
{
|
{
|
||||||
size_t i;
|
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);
|
qsort(root->info.dir.children, root->info.dir.nchildren,
|
||||||
for (i = 0; i < root->nchildren; i++)
|
sizeof(void*), cmp_node);
|
||||||
if (ISO_ISDIR(root->children[i]->iso_self))
|
for (i = 0; i < root->info.dir.nchildren; i++) {
|
||||||
sort_tree(root->children[i]);
|
struct joliet_tree_node *child = root->info.dir.children[i];
|
||||||
|
if ( child->type == JOLIET_DIR )
|
||||||
|
sort_tree(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -80,11 +116,11 @@ joliet_prepare_path_tables(struct ecma119_write_target *t)
|
|||||||
t->path_table_size_joliet = 10; /* root directory record */
|
t->path_table_size_joliet = 10; /* root directory record */
|
||||||
cur = 1;
|
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];
|
struct joliet_tree_node *dir = t->pathlist_joliet[i];
|
||||||
for (j = 0; j < dir->nchildren; j++) {
|
for (j = 0; j < dir->info.dir.nchildren; j++) {
|
||||||
struct joliet_tree_node *ch = dir->children[j];
|
struct joliet_tree_node *ch = dir->info.dir.children[j];
|
||||||
if (ISO_ISDIR(ch->iso_self)) {
|
if (ch->type == JOLIET_DIR) {
|
||||||
size_t len = 8 + ucslen(ch->name)*2;
|
size_t len = 8 + ucslen(ch->name)*2;
|
||||||
t->pathlist_joliet[cur++] = ch;
|
t->pathlist_joliet[cur++] = ch;
|
||||||
t->path_table_size_joliet += len;
|
t->path_table_size_joliet += len;
|
||||||
@ -104,22 +140,22 @@ joliet_calc_dir_size(struct ecma119_write_target *t,
|
|||||||
size_t newlen;
|
size_t newlen;
|
||||||
struct joliet_tree_node *ch;
|
struct joliet_tree_node *ch;
|
||||||
|
|
||||||
assert(root && ISO_ISDIR(root->iso_self));
|
assert(root && (root->type == JOLIET_DIR) );
|
||||||
|
|
||||||
root->len = 68; /* for "." and ".." entries */
|
t->dirlist_len_joliet++;
|
||||||
for (i = 0; i < root->nchildren; i++) {
|
root->info.dir.len = 68; /* for "." and ".." entries */
|
||||||
ch = root->children[i];
|
for (i = 0; i < root->info.dir.nchildren; ++i) {
|
||||||
newlen = root->len + ch->dirent_len;
|
ch = root->info.dir.children[i];
|
||||||
if ((newlen % 2048) < (root->len % 2048)) {
|
newlen = root->info.dir.len + ch->dirent_len;
|
||||||
root->len = newlen + (2048 - (root->len % 2048));
|
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 {
|
if (ch->type == JOLIET_DIR)
|
||||||
root->len += ch->dirent_len;
|
|
||||||
}
|
|
||||||
if (ISO_ISDIR(ch->iso_self))
|
|
||||||
joliet_calc_dir_size(t, ch);
|
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;
|
size_t i;
|
||||||
struct joliet_tree_node *ch;
|
struct joliet_tree_node *ch;
|
||||||
|
|
||||||
assert(root && ISO_ISDIR(root->iso_self));
|
assert(root && (root->type == JOLIET_DIR));
|
||||||
|
|
||||||
root->block = t->curblock;
|
root->info.dir.block = t->curblock;
|
||||||
t->curblock += div_up(root->len, t->block_size);
|
t->curblock += div_up(root->info.dir.len, t->block_size);
|
||||||
|
|
||||||
t->dirlist_joliet[t->curfile++] = root;
|
t->dirlist_joliet[t->curfile++] = root;
|
||||||
for (i = 0; i < root->nchildren; i++) {
|
for (i = 0; i < root->info.dir.nchildren; i++) {
|
||||||
ch = root->children[i];
|
ch = root->info.dir.children[i];
|
||||||
if (ISO_ISDIR(ch->iso_self))
|
if (ch->type == JOLIET_DIR)
|
||||||
joliet_calc_dir_pos(t, ch);
|
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*
|
struct joliet_tree_node*
|
||||||
@ -209,7 +217,7 @@ write_path_table(struct ecma119_write_target *t,
|
|||||||
rec->len_di[0] = dir->parent ?
|
rec->len_di[0] = dir->parent ?
|
||||||
(uint8_t) ucslen(dir->name) * 2 : 1;
|
(uint8_t) ucslen(dir->name) * 2 : 1;
|
||||||
rec->len_xa[0] = 0;
|
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);
|
write_int(rec->parent, parent + 1, 2);
|
||||||
if (dir->parent)
|
if (dir->parent)
|
||||||
memcpy(rec->dir_id, dir->name, rec->len_di[0]);
|
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,
|
int file_id,
|
||||||
uint8_t *buf)
|
uint8_t *buf)
|
||||||
{
|
{
|
||||||
|
uint32_t len;
|
||||||
|
uint32_t block;
|
||||||
uint8_t len_dr = (file_id >= 0) ? 34 : node->dirent_len;
|
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 len_fi = (file_id >= 0) ? 1 : ucslen(node->name) * 2;
|
||||||
uint8_t f_id = (uint8_t) ((file_id == 3) ? 0 : file_id);
|
uint8_t f_id = (uint8_t) ((file_id == 3) ? 0 : file_id);
|
||||||
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->name;
|
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->name;
|
||||||
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
|
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)
|
if (file_id == 1 && node->parent)
|
||||||
node = node->parent;
|
node = node->parent;
|
||||||
|
|
||||||
rec->len_dr[0] = len_dr;
|
rec->len_dr[0] = len_dr;
|
||||||
iso_bb(rec->block, node->block, 4);
|
iso_bb(rec->block, block, 4);
|
||||||
iso_bb(rec->length, node->len, 4);
|
iso_bb(rec->length, len, 4);
|
||||||
iso_datetime_7(rec->recording_time, t->now);
|
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);
|
iso_bb(rec->vol_seq_number, t->volnum + 1, 2);
|
||||||
rec->len_fi[0] = len_fi;
|
rec->len_fi[0] = len_fi;
|
||||||
memcpy(rec->file_id, name, len_fi);
|
memcpy(rec->file_id, name, len_fi);
|
||||||
@ -263,15 +282,26 @@ 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 ecma119_sup_vol_desc *vol = (struct ecma119_sup_vol_desc*)buf;
|
||||||
struct iso_volume *volume = t->volset->volume[t->volnum];
|
struct iso_volume *volume = t->volset->volume[t->volnum];
|
||||||
uint16_t *vol_id = str2ucs(volume->volume_id);
|
uint16_t *vol_id = str2ucs(volume->volume_id, t->input_charset);
|
||||||
uint16_t *pub_id = str2ucs(volume->publisher_id);
|
uint16_t *pub_id = str2ucs(volume->publisher_id, t->input_charset);
|
||||||
uint16_t *data_id = str2ucs(volume->data_preparer_id);
|
uint16_t *data_id = str2ucs(volume->data_preparer_id, t->input_charset);
|
||||||
uint16_t *volset_id = str2ucs(t->volset->volset_id);
|
uint16_t *volset_id = str2ucs(t->volset->volset_id, t->input_charset);
|
||||||
int vol_id_len = MIN(32, ucslen(vol_id) * 2);
|
int vol_id_len = MIN(32, ucslen(vol_id) * 2);
|
||||||
int pub_id_len = MIN(128, ucslen(pub_id) * 2);
|
int pub_id_len = MIN(128, ucslen(pub_id) * 2);
|
||||||
int data_id_len = MIN(128, ucslen(data_id) * 2);
|
int data_id_len = MIN(128, ucslen(data_id) * 2);
|
||||||
int volset_id_len = MIN(128, ucslen(volset_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;
|
vol->vol_desc_type[0] = 2;
|
||||||
memcpy(vol->std_identifier, "CD001", 5);
|
memcpy(vol->std_identifier, "CD001", 5);
|
||||||
vol->vol_desc_version[0] = 1;
|
vol->vol_desc_version[0] = 1;
|
||||||
@ -292,7 +322,12 @@ write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
|||||||
memcpy(vol->vol_set_id, volset_id, volset_id_len);
|
memcpy(vol->vol_set_id, volset_id, volset_id_len);
|
||||||
memcpy(vol->publisher_id, pub_id, pub_id_len);
|
memcpy(vol->publisher_id, pub_id, pub_id_len);
|
||||||
memcpy(vol->data_prep_id, data_id, data_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_creation_time, t->now);
|
||||||
iso_datetime_17(vol->vol_modification_time, t->now);
|
iso_datetime_17(vol->vol_modification_time, t->now);
|
||||||
@ -303,6 +338,11 @@ write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
|||||||
free(volset_id);
|
free(volset_id);
|
||||||
free(pub_id);
|
free(pub_id);
|
||||||
free(data_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 *orig_buf = buf;
|
||||||
uint8_t *prior_buf = buf;
|
uint8_t *prior_buf = buf;
|
||||||
|
|
||||||
assert(ISO_ISDIR (dir->iso_self));
|
assert(dir->type == JOLIET_DIR);
|
||||||
/* write the "." and ".." entries first */
|
/* write the "." and ".." entries first */
|
||||||
write_one_dir_record(t, dir, 0, buf);
|
write_one_dir_record(t, dir, 0, buf);
|
||||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
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);
|
write_one_dir_record(t, dir, 1, buf);
|
||||||
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||||
|
|
||||||
for (i = 0; i < dir->nchildren; i++) {
|
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||||
write_one_dir_record(t, dir->children[i], -1, buf);
|
write_one_dir_record(t, dir->info.dir.children[i], -1, buf);
|
||||||
len = ((struct ecma119_dir_record*) buf)->len_dr[0];
|
len = ((struct ecma119_dir_record*) buf)->len_dr[0];
|
||||||
if ((buf + len - prior_buf) >= 2048) {
|
if ((buf + len - prior_buf) >= 2048) {
|
||||||
for (j = len - 1; j >= 0; j--) {
|
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
|
static void
|
||||||
@ -350,11 +390,11 @@ write_dirs(struct ecma119_write_target *t, uint8_t *buf)
|
|||||||
size_t i;
|
size_t i;
|
||||||
struct joliet_tree_node *dir;
|
struct joliet_tree_node *dir;
|
||||||
|
|
||||||
assert (t->curblock == t->dirlist_joliet[0]->block);
|
assert (t->curblock == t->dirlist_joliet[0]->info.dir.block);
|
||||||
for (i = 0; i < t->dirlist_len; i++) {
|
for (i = 0; i < t->dirlist_len_joliet; i++) {
|
||||||
dir = t->dirlist_joliet[i];
|
dir = t->dirlist_joliet[i];
|
||||||
write_one_dir(t, dir, buf);
|
write_one_dir(t, dir, buf);
|
||||||
buf += round_up(dir->len, t->block_size);
|
buf += round_up(dir->info.dir.len, t->block_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,19 +17,34 @@
|
|||||||
struct ecma119_write_target;
|
struct ecma119_write_target;
|
||||||
struct iso_tree_node;
|
struct iso_tree_node;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
JOLIET_FILE,
|
||||||
|
JOLIET_DIR
|
||||||
|
};
|
||||||
|
|
||||||
|
struct joliet_dir_info {
|
||||||
|
struct joliet_tree_node **children;
|
||||||
|
size_t nchildren;
|
||||||
|
size_t len;
|
||||||
|
size_t block;
|
||||||
|
};
|
||||||
|
|
||||||
struct joliet_tree_node
|
struct joliet_tree_node
|
||||||
{
|
{
|
||||||
uint16_t *name; /**< In UCS-2BE. */
|
uint16_t *name; /**< In UCS-2BE. */
|
||||||
size_t dirent_len;
|
size_t dirent_len;
|
||||||
size_t len;
|
//size_t len;??
|
||||||
size_t block;
|
/*size_t block;*/
|
||||||
|
|
||||||
struct joliet_tree_node *parent;
|
struct joliet_tree_node *parent;
|
||||||
struct iso_tree_node *iso_self;
|
/* struct iso_tree_node *iso_self; */
|
||||||
struct ecma119_write_target *target;
|
struct ecma119_write_target *target;
|
||||||
|
|
||||||
struct joliet_tree_node **children;
|
int type;
|
||||||
size_t nchildren;
|
union {
|
||||||
|
struct iso_file *file;
|
||||||
|
struct joliet_dir_info dir;
|
||||||
|
} info;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,9 +70,10 @@ joliet_calc_dir_pos(struct ecma119_write_target *t, struct joliet_tree_node*);
|
|||||||
/**
|
/**
|
||||||
* Update the position of each file in the joliet hierarchy (to be called
|
* Update the position of each file in the joliet hierarchy (to be called
|
||||||
* AFTER the file positions in the iso tree have been set).
|
* AFTER the file positions in the iso tree have been set).
|
||||||
|
* TODO not needed, block info is kept away in hash table
|
||||||
*/
|
*/
|
||||||
void
|
//void
|
||||||
joliet_update_file_pos(struct ecma119_write_target *t, struct joliet_tree_node*);
|
//joliet_update_file_pos(struct ecma119_write_target *t, struct joliet_tree_node*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the size of the joliet path table and fill in the list of
|
* Calculate the size of the joliet path table and fill in the list of
|
||||||
|
@ -33,11 +33,44 @@ struct iso_volset;
|
|||||||
*/
|
*/
|
||||||
struct iso_tree_node;
|
struct iso_tree_node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A directory in the filesystem tree.
|
||||||
|
* The first member of this is an iso_tree_node.
|
||||||
|
* \see tree.h
|
||||||
|
*/
|
||||||
|
struct iso_tree_node_dir;
|
||||||
|
|
||||||
enum ecma119_extension_flag {
|
enum ecma119_extension_flag {
|
||||||
ECMA119_ROCKRIDGE = (1<<0),
|
ECMA119_ROCKRIDGE = (1<<0),
|
||||||
ECMA119_JOLIET = (1<<1)
|
ECMA119_JOLIET = (1<<1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will hold the error code for some functions, if them fail.
|
||||||
|
*/
|
||||||
|
int libisofs_errno;
|
||||||
|
|
||||||
|
/* an unexpected internal error */
|
||||||
|
#define INTERNAL_ERROR -1
|
||||||
|
/* file don't exists, or can't be stat'ed */
|
||||||
|
#define NO_FILE 1
|
||||||
|
/* user haven't read access to file */
|
||||||
|
#define NO_READ_ACCESS 2
|
||||||
|
/* unexpected file type, eg., passing a dir instead of a regular file */
|
||||||
|
#define UNEXPECTED_FILE_TYPE 3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls the bahavior of iso_tree_radd_dir function
|
||||||
|
*/
|
||||||
|
struct iso_tree_radd_dir_behavior {
|
||||||
|
char** excludes; /**< List of paths (file or directory) to be ignored. */
|
||||||
|
//int follow_sym_link;
|
||||||
|
int stop_on_error; /**< Stop when an error was found?. */
|
||||||
|
int error; /**< set to 1 on error */
|
||||||
|
//int notify_errors;
|
||||||
|
//char** errors;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new volume.
|
* Create a new volume.
|
||||||
* The parameters can be set to NULL if you wish to set them later.
|
* The parameters can be set to NULL if you wish to set them later.
|
||||||
@ -49,7 +82,7 @@ struct iso_volume *iso_volume_new(const char *volume_id,
|
|||||||
struct iso_volume *iso_volume_new_with_root(const char *volume_id,
|
struct iso_volume *iso_volume_new_with_root(const char *volume_id,
|
||||||
const char *publisher_id,
|
const char *publisher_id,
|
||||||
const char *data_preparer_id,
|
const char *data_preparer_id,
|
||||||
struct iso_tree_node *root);
|
struct iso_tree_node_dir *root);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free a volume.
|
* Free a volume.
|
||||||
@ -64,7 +97,7 @@ void iso_volset_free(struct iso_volset *volume);
|
|||||||
/**
|
/**
|
||||||
* Get the root directory for a volume.
|
* Get the root directory for a volume.
|
||||||
*/
|
*/
|
||||||
struct iso_tree_node *iso_volume_get_root(const struct iso_volume *volume);
|
struct iso_tree_node_dir *iso_volume_get_root(const struct iso_volume *volume);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill in the volume identifier for a volume.
|
* Fill in the volume identifier for a volume.
|
||||||
@ -126,7 +159,7 @@ void iso_volume_set_biblio_file_id(struct iso_volume *volume,
|
|||||||
* \return The node found or NULL.
|
* \return The node found or NULL.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct iso_tree_node *iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path);
|
//struct iso_tree_node *iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a file or a directory (recursively) to a volume by specifying its path on the volume.
|
* Add a file or a directory (recursively) to a volume by specifying its path on the volume.
|
||||||
@ -137,9 +170,9 @@ struct iso_tree_node *iso_tree_volume_path_to_node(struct iso_volume *volume, co
|
|||||||
*
|
*
|
||||||
* \return The node for the file or NULL if the parent doesn't exists on the disc.
|
* \return The node for the file or NULL if the parent doesn't exists on the disc.
|
||||||
*/
|
*/
|
||||||
struct iso_tree_node *iso_tree_volume_add_path(struct iso_volume *volume,
|
//struct iso_tree_node *iso_tree_volume_add_path(struct iso_volume *volume,
|
||||||
const char *disc_path,
|
// const char *disc_path,
|
||||||
const char *path);
|
// const char *path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new, empty directory on the volume.
|
* Creates a new, empty directory on the volume.
|
||||||
@ -149,8 +182,8 @@ struct iso_tree_node *iso_tree_volume_add_path(struct iso_volume *volume,
|
|||||||
*
|
*
|
||||||
* \return A pointer to the newly created directory.
|
* \return A pointer to the newly created directory.
|
||||||
*/
|
*/
|
||||||
struct iso_tree_node *iso_tree_volume_add_new_dir(struct iso_volume *volume,
|
//struct iso_tree_node *iso_tree_volume_add_new_dir(struct iso_volume *volume,
|
||||||
const char *disc_path);
|
// const char *disc_path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Volume Set consisting of only one volume.
|
* Create a new Volume Set consisting of only one volume.
|
||||||
@ -161,54 +194,96 @@ struct iso_tree_node *iso_tree_volume_add_new_dir(struct iso_volume *volume,
|
|||||||
struct iso_volset *iso_volset_new(struct iso_volume *volume,
|
struct iso_volset *iso_volset_new(struct iso_volume *volume,
|
||||||
const char *volset_id);
|
const char *volset_id);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new root dir for a filesystem tree
|
||||||
|
*/
|
||||||
|
struct iso_tree_node_dir *iso_tree_new_root();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a file to a directory.
|
* Add a file to a directory.
|
||||||
*
|
*
|
||||||
* \param path The path, on the local filesystem, of the file.
|
* \param path The path, on the local filesystem, of the file.
|
||||||
*
|
*
|
||||||
* \pre \p parent is NULL or is a directory.
|
* \pre \p parent is non-NULL.
|
||||||
* \pre \p path is non-NULL and is a valid path to a non-directory on the local
|
* \pre \p path is non-NULL.
|
||||||
|
* \return An iso_tree_node_file whose path is \p path and whose parent is
|
||||||
|
* \p parent.
|
||||||
|
* On error, returns NULL and libisofs_errno is set appropriately:
|
||||||
|
* NO_FILE if path doesn't point to a valid file.
|
||||||
|
* NO_READ_ACCESS if user haven't read access on file
|
||||||
|
* UNEXPECTED_FILE_TYPE if path doesn't point to a regular file
|
||||||
|
*/
|
||||||
|
struct iso_tree_node *iso_tree_add_file(struct iso_tree_node_dir *parent,
|
||||||
|
const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a symbolic link to a directory.
|
||||||
|
*
|
||||||
|
* \param name The name of the symbolic link
|
||||||
|
* \param dest The distination of the link, i.e., the file this link points
|
||||||
|
* to
|
||||||
|
*
|
||||||
|
* \pre \p parent, name and dest are non-NULL.
|
||||||
|
*
|
||||||
|
* \return An iso_tree_node_symlink
|
||||||
|
*/
|
||||||
|
struct iso_tree_node *iso_tree_add_symlink(struct iso_tree_node_dir *parent,
|
||||||
|
const char *name, const char *dest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new, empty directory to the tree.
|
||||||
|
*
|
||||||
|
* \pre \p parent is non-NULL.
|
||||||
|
* \pre \p name is unique among the children and files belonging to \p parent.
|
||||||
|
* Also, it doesn't contain '/' characters.
|
||||||
|
*
|
||||||
|
* \post \p parent contains a child directory whose name is \p name and whose
|
||||||
|
* POSIX attributes are the same as \p parent's.
|
||||||
|
* \return a pointer to the newly created directory.
|
||||||
|
*/
|
||||||
|
struct iso_tree_node_dir *iso_tree_add_dir(struct iso_tree_node_dir *parent,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
/* TODO iso_tree_new_special */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a file to a directory.
|
||||||
|
*
|
||||||
|
* \param path The path, on the local filesystem, of the file.
|
||||||
|
*
|
||||||
|
* \pre \p parent is non-NULL.
|
||||||
|
* \pre \p path is non-NULL and is a valid path to a file or directory on the local
|
||||||
* filesystem.
|
* filesystem.
|
||||||
* \return An iso_tree_node whose path is \p path and whose parent is \p parent.
|
* \return An iso_tree_node whose path is \p path and whose parent is \p parent.
|
||||||
|
* On error, returns NULL and libisofs_errno is set appropriately:
|
||||||
|
* NO_FILE if path doesn't point to a valid file.
|
||||||
|
* NO_READ_ACCESS if user haven't read access on file
|
||||||
|
* UNEXPECTED_FILE_TYPE if path refers to non supported file type
|
||||||
|
* (at the momment, only dirs, symlinks and regular
|
||||||
|
* files are supported).
|
||||||
*/
|
*/
|
||||||
struct iso_tree_node *iso_tree_add_node(struct iso_tree_node *parent,
|
struct iso_tree_node *iso_tree_add_node(struct iso_tree_node_dir *parent,
|
||||||
const char *path);
|
const char *path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively add an existing directory to the tree.
|
* Recursively add an existing directory to the tree.
|
||||||
* Warning: when using this, you'll lose pointers to files or subdirectories.
|
* Warning: when using this, you'll lose pointers to files or subdirectories.
|
||||||
* If you want to have pointers to all files and directories,
|
* If you want to have pointers to all files and directories,
|
||||||
* use iso_tree_add_file and iso_tree_add_dir.
|
* use iso_tree_add_file, iso_tree_add_node and iso_tree_add_dir.
|
||||||
*
|
*
|
||||||
* \param path The path, on the local filesystem, of the directory to add.
|
* \param path The path, on the local filesystem, of the directory to add.
|
||||||
*
|
*
|
||||||
* \pre \p parent is NULL or is a directory.
|
* \pre \p parent is non-NULL.
|
||||||
* \pre \p path is non-NULL and is a valid path to a directory on the local
|
* \pre \p path is non-NULL and is a valid path to a directory on the local
|
||||||
* filesystem.
|
* filesystem.
|
||||||
* \return a pointer to the newly created directory.
|
* \return a pointer to the newly created directory.
|
||||||
*/
|
*/
|
||||||
struct iso_tree_node *iso_tree_radd_dir(struct iso_tree_node *parent,
|
struct iso_tree_node_dir *iso_tree_radd_dir(struct iso_tree_node_dir *parent,
|
||||||
const char *path);
|
const char *path, struct iso_tree_radd_dir_behavior *behavior);
|
||||||
|
|
||||||
|
//struct iso_tree_node *iso_tree_radd_dir(struct iso_tree_node *parent,
|
||||||
/**
|
// 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(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(const char *path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all paths that were set to be ignored when adding a directory recusively.
|
|
||||||
*/
|
|
||||||
void iso_exclude_empty(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new, empty directory on the volume.
|
* Creates a new, empty directory on the volume.
|
||||||
@ -221,13 +296,18 @@ void iso_exclude_empty(void);
|
|||||||
* POSIX attributes are the same as \p parent's.
|
* POSIX attributes are the same as \p parent's.
|
||||||
* \return a pointer to the newly created directory.
|
* \return a pointer to the newly created directory.
|
||||||
*/
|
*/
|
||||||
struct iso_tree_node *iso_tree_add_new_dir(struct iso_tree_node *parent,
|
/*struct iso_tree_node *iso_tree_add_new_dir(struct iso_tree_node *parent,
|
||||||
const char *name);
|
const char *name);*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the name of a file (using the current locale).
|
* Set the name of a tree node (using the current locale).
|
||||||
*/
|
*/
|
||||||
void iso_tree_node_set_name(struct iso_tree_node *file, const char *name);
|
void iso_tree_node_set_name(struct iso_tree_node *node, const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if the node will be hidden in RR/ISO tree, Joliet tree or both.
|
||||||
|
*/
|
||||||
|
void iso_tree_node_set_hidden(struct iso_tree_node *node, int hide_attrs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively print a directory to stdout.
|
* Recursively print a directory to stdout.
|
||||||
|
@ -24,11 +24,11 @@ uint8_t *rrip_make_PX(struct ecma119_write_target *t,
|
|||||||
PX[1] = 'X';
|
PX[1] = 'X';
|
||||||
PX[2] = 44;
|
PX[2] = 44;
|
||||||
PX[3] = 1;
|
PX[3] = 1;
|
||||||
iso_bb(&PX[4], node->iso_self->attrib.st_mode, 4);
|
iso_bb(&PX[4], node->attrib.st_mode, 4);
|
||||||
iso_bb(&PX[12], node->iso_self->attrib.st_nlink, 4);
|
iso_bb(&PX[12], node->attrib.st_nlink, 4);
|
||||||
iso_bb(&PX[20], node->iso_self->attrib.st_uid, 4);
|
iso_bb(&PX[20], node->attrib.st_uid, 4);
|
||||||
iso_bb(&PX[28], node->iso_self->attrib.st_gid, 4);
|
iso_bb(&PX[28], node->attrib.st_gid, 4);
|
||||||
iso_bb(&PX[36], node->iso_self->attrib.st_ino, 4);
|
iso_bb(&PX[36], node->attrib.st_ino, 4);
|
||||||
return PX;
|
return PX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,8 +37,8 @@ void rrip_add_PX(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
|||||||
{
|
{
|
||||||
susp_append(t, &node->susp, rrip_make_PX(t, node));
|
susp_append(t, &node->susp, rrip_make_PX(t, node));
|
||||||
if (node->type == ECMA119_DIR) {
|
if (node->type == ECMA119_DIR) {
|
||||||
susp_append(t, &node->dir.self_susp, rrip_make_PX(t, node));
|
susp_append(t, &node->info.dir.self_susp, rrip_make_PX(t, node));
|
||||||
susp_append(t, &node->dir.parent_susp, rrip_make_PX(t, node));
|
susp_append(t, &node->info.dir.parent_susp, rrip_make_PX(t, node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +50,8 @@ void rrip_add_PN(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
|||||||
PN[1] = 'N';
|
PN[1] = 'N';
|
||||||
PN[2] = 20;
|
PN[2] = 20;
|
||||||
PN[3] = 1;
|
PN[3] = 1;
|
||||||
iso_bb(&PN[4], node->iso_self->attrib.st_dev >> 32, 4);
|
iso_bb(&PN[4], node->attrib.st_dev >> 32, 4);
|
||||||
iso_bb(&PN[12], node->iso_self->attrib.st_dev & 0xffffffff, 4);
|
iso_bb(&PN[12], node->attrib.st_dev & 0xffffffff, 4);
|
||||||
susp_append(t, &node->susp, PN);
|
susp_append(t, &node->susp, PN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ static void rrip_SL_add_component(char *prev, char *cur, int *n_comp,
|
|||||||
|
|
||||||
void rrip_add_SL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
void rrip_add_SL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||||
{
|
{
|
||||||
int ret, pathsize = 0;
|
int path_size;
|
||||||
char *path = NULL, *cur, *prev;
|
char *path = NULL, *cur, *prev;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
@ -113,18 +113,8 @@ void rrip_add_SL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
|||||||
|
|
||||||
uint8_t *SL;
|
uint8_t *SL;
|
||||||
|
|
||||||
do {
|
path = node->info.dest;
|
||||||
pathsize += 128;
|
path_size = strlen(path);
|
||||||
path = realloc(path, pathsize);
|
|
||||||
/* FIXME: what if the file is not on the local fs? */
|
|
||||||
ret = readlink(node->iso_self->loc.path, path, pathsize);
|
|
||||||
} while (ret == pathsize);
|
|
||||||
if (ret == -1) {
|
|
||||||
fprintf(stderr, "Error: couldn't read symlink: %s\n",
|
|
||||||
strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
path[ret] = '\0';
|
|
||||||
|
|
||||||
prev = path;
|
prev = path;
|
||||||
for (cur = strchr(path, '/'); cur && *cur; cur = strchr(cur, '/')) {
|
for (cur = strchr(path, '/'); cur && *cur; cur = strchr(cur, '/')) {
|
||||||
@ -134,8 +124,8 @@ void rrip_add_SL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* if there was no trailing '/', we need to add the last component. */
|
/* if there was no trailing '/', we need to add the last component. */
|
||||||
if (prev == path || prev != &path[ret - 1]) {
|
if (prev == path || prev != &path[path_size - 1]) {
|
||||||
rrip_SL_add_component(prev, &path[ret], &n_comp, &comp);
|
rrip_SL_add_component(prev, &path[path_size], &n_comp, &comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < n_comp; i++) {
|
for (i = 0; i < n_comp; i++) {
|
||||||
@ -172,7 +162,6 @@ void rrip_add_SL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
|||||||
}
|
}
|
||||||
susp_append(t, &node->susp, SL);
|
susp_append(t, &node->susp, SL);
|
||||||
|
|
||||||
free(path);
|
|
||||||
/* free the components */
|
/* free the components */
|
||||||
for (i = 0; i < n_comp; i++) {
|
for (i = 0; i < n_comp; i++) {
|
||||||
free(comp[i]);
|
free(comp[i]);
|
||||||
@ -200,7 +189,7 @@ static void rrip_add_NM_single(struct ecma119_write_target *t,
|
|||||||
void
|
void
|
||||||
rrip_add_NM(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
rrip_add_NM(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||||
{
|
{
|
||||||
char *name = iso_p_fileid(node->iso_self->name);
|
char *name = node->full_name;
|
||||||
int len = name ? strlen(name) : 0;
|
int len = name ? strlen(name) : 0;
|
||||||
char *pos = name;
|
char *pos = name;
|
||||||
|
|
||||||
@ -208,8 +197,8 @@ rrip_add_NM(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (node->type == ECMA119_DIR) {
|
if (node->type == ECMA119_DIR) {
|
||||||
rrip_add_NM_single(t, &node->dir.self_susp, pos, 0, 1 << 1);
|
rrip_add_NM_single(t, &node->info.dir.self_susp, pos, 0, 1 << 1);
|
||||||
rrip_add_NM_single(t, &node->dir.parent_susp, pos, 0, 1 << 2);
|
rrip_add_NM_single(t, &node->info.dir.parent_susp, pos, 0, 1 << 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len > 250) {
|
while (len > 250) {
|
||||||
@ -240,7 +229,7 @@ rrip_add_PL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
|||||||
PL[1] = 'L';
|
PL[1] = 'L';
|
||||||
PL[2] = 12;
|
PL[2] = 12;
|
||||||
PL[3] = 1;
|
PL[3] = 1;
|
||||||
susp_append(t, &node->dir.parent_susp, PL);
|
susp_append(t, &node->info.dir.parent_susp, PL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -264,10 +253,10 @@ rrip_add_TF(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
|||||||
TF[1] = 'F';
|
TF[1] = 'F';
|
||||||
TF[2] = 5 + 3 * 7;
|
TF[2] = 5 + 3 * 7;
|
||||||
TF[3] = 1;
|
TF[3] = 1;
|
||||||
TF[4] = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 7);
|
TF[4] = (1 << 1) | (1 << 2) | (1 << 3);
|
||||||
iso_datetime_7(&TF[5], node->iso_self->attrib.st_mtime);
|
iso_datetime_7(&TF[5], node->attrib.st_mtime);
|
||||||
iso_datetime_7(&TF[12], node->iso_self->attrib.st_atime);
|
iso_datetime_7(&TF[12], node->attrib.st_atime);
|
||||||
iso_datetime_7(&TF[19], node->iso_self->attrib.st_ctime);
|
iso_datetime_7(&TF[19], node->attrib.st_ctime);
|
||||||
susp_append(t, &node->susp, TF);
|
susp_append(t, &node->susp, TF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,21 +267,21 @@ rrip_finalize(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
|||||||
|
|
||||||
assert(dir->type == ECMA119_DIR);
|
assert(dir->type == ECMA119_DIR);
|
||||||
|
|
||||||
if (dir->parent != dir->dir.real_parent) {
|
if (dir->parent != dir->info.dir.real_parent) {
|
||||||
uint8_t *PL = susp_find(&dir->dir.parent_susp, "PL");
|
uint8_t *PL = susp_find(&dir->info.dir.parent_susp, "PL");
|
||||||
|
|
||||||
assert(PL);
|
assert(PL);
|
||||||
iso_bb(&PL[4], dir->dir.real_parent->block, 4);
|
iso_bb(&PL[4], dir->info.dir.real_parent->info.dir.block, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||||
|
|
||||||
if (ch->type == ECMA119_FILE && ch->file.real_me) {
|
if (ch->type == ECMA119_PLACEHOLDER) {
|
||||||
uint8_t *CL = susp_find(&ch->susp, "CL");
|
uint8_t *CL = susp_find(&ch->susp, "CL");
|
||||||
|
|
||||||
assert(CL);
|
assert(CL);
|
||||||
iso_bb(&CL[4], ch->file.real_me->block, 4);
|
iso_bb(&CL[4], ch->info.real_me->info.dir.block, 4);
|
||||||
} else if (ch->type == ECMA119_DIR) {
|
} else if (ch->type == ECMA119_DIR) {
|
||||||
rrip_finalize(t, ch);
|
rrip_finalize(t, ch);
|
||||||
}
|
}
|
||||||
|
@ -117,8 +117,8 @@ susp_add_CE(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
|||||||
{
|
{
|
||||||
try_add_CE(t, &node->susp, node->dirent_len);
|
try_add_CE(t, &node->susp, node->dirent_len);
|
||||||
if (node->type == ECMA119_DIR) {
|
if (node->type == ECMA119_DIR) {
|
||||||
try_add_CE(t, &node->dir.self_susp, 34);
|
try_add_CE(t, &node->info.dir.self_susp, 34);
|
||||||
try_add_CE(t, &node->dir.parent_susp, 34);
|
try_add_CE(t, &node->info.dir.parent_susp, 34);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ susp_add_SP(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
|||||||
SP[4] = 0xbe;
|
SP[4] = 0xbe;
|
||||||
SP[5] = 0xef;
|
SP[5] = 0xef;
|
||||||
SP[6] = 0;
|
SP[6] = 0;
|
||||||
susp_append(t, &dir->dir.self_susp, SP);
|
susp_append(t, &dir->info.dir.self_susp, SP);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -176,7 +176,7 @@ rrip_add_ER(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
|||||||
"FILE SYSTEM SEMANTICS.", 72);
|
"FILE SYSTEM SEMANTICS.", 72);
|
||||||
memcpy(&ER[89], "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, "
|
memcpy(&ER[89], "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, "
|
||||||
"PISCATAWAY, NJ, USA FOR THE 1282 SPECIFICATION.", 93);
|
"PISCATAWAY, NJ, USA FOR THE 1282 SPECIFICATION.", 93);
|
||||||
susp_append(t, &dir->dir.self_susp, ER);
|
susp_append(t, &dir->info.dir.self_susp, ER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate the location of the CE areas. Since CE areas don't need to be
|
/* calculate the location of the CE areas. Since CE areas don't need to be
|
||||||
@ -184,9 +184,9 @@ rrip_add_ER(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
|||||||
* directory and dump them immediately after all the directory records.
|
* directory and dump them immediately after all the directory records.
|
||||||
*
|
*
|
||||||
* Requires that the following be known:
|
* Requires that the following be known:
|
||||||
* - position of the current directory (dir->block)
|
* - position of the current directory (dir->info.dir.block)
|
||||||
* - length of the current directory (dir->dir.len)
|
* - length of the current directory (dir->info.dir.len)
|
||||||
* - sum of the children's CE lengths (dir->dir.CE_len)
|
* - sum of the children's CE lengths (dir->info.dir.CE_len)
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
susp_fin_1_CE(struct ecma119_write_target *t,
|
susp_fin_1_CE(struct ecma119_write_target *t,
|
||||||
@ -208,18 +208,18 @@ static void susp_fin_CE(struct ecma119_write_target *t,
|
|||||||
struct ecma119_tree_node *dir)
|
struct ecma119_tree_node *dir)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
size_t CE_offset = dir->dir.len;
|
size_t CE_offset = dir->info.dir.len;
|
||||||
|
|
||||||
assert(dir->type == ECMA119_DIR);
|
assert(dir->type == ECMA119_DIR);
|
||||||
|
|
||||||
susp_fin_1_CE(t, &dir->dir.self_susp, dir->block, &CE_offset);
|
susp_fin_1_CE(t, &dir->info.dir.self_susp, dir->info.dir.block, &CE_offset);
|
||||||
susp_fin_1_CE(t, &dir->dir.parent_susp, dir->block, &CE_offset);
|
susp_fin_1_CE(t, &dir->info.dir.parent_susp, dir->info.dir.block, &CE_offset);
|
||||||
|
|
||||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||||
susp_fin_1_CE(t, &ch->susp, dir->block, &CE_offset);
|
susp_fin_1_CE(t, &ch->susp, dir->info.dir.block, &CE_offset);
|
||||||
}
|
}
|
||||||
assert(CE_offset == dir->dir.len + dir->dir.CE_len);
|
assert(CE_offset == dir->info.dir.len + dir->info.dir.CE_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -229,13 +229,13 @@ susp_finalize(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
|||||||
|
|
||||||
assert(dir->type = ECMA119_DIR);
|
assert(dir->type = ECMA119_DIR);
|
||||||
|
|
||||||
if (dir->dir.depth != 1) {
|
if (dir->info.dir.depth != 1) {
|
||||||
susp_fin_CE(t, dir);
|
susp_fin_CE(t, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||||
if (dir->dir.children[i]->type == ECMA119_DIR)
|
if (dir->info.dir.children[i]->type == ECMA119_DIR)
|
||||||
susp_finalize(t, dir->dir.children[i]);
|
susp_finalize(t, dir->info.dir.children[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
337
libisofs/tree.c
337
libisofs/tree.c
@ -20,8 +20,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
#include "util.h"
|
|
||||||
#include "volume.h"
|
|
||||||
#include "exclude.h"
|
#include "exclude.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -30,117 +28,223 @@ set_default_stat(struct stat *s)
|
|||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
|
|
||||||
memset(s, 0, sizeof(struct stat));
|
memset(s, 0, sizeof(struct stat));
|
||||||
s->st_mode = 0777 | S_IFREG;
|
s->st_mode = 0555;
|
||||||
s->st_atime = s->st_mtime = s->st_ctime = now;
|
s->st_atime = s->st_mtime = s->st_ctime = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct stat
|
|
||||||
get_attrib(const struct iso_tree_node *node)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (node) {
|
|
||||||
return node->attrib;
|
|
||||||
}
|
|
||||||
set_default_stat(&st);
|
|
||||||
return st;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
append_node(struct iso_tree_node *parent,
|
append_node(struct iso_tree_node_dir *parent,
|
||||||
struct iso_tree_node *child)
|
struct iso_tree_node *child)
|
||||||
{
|
{
|
||||||
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && child);
|
assert( parent && child);
|
||||||
if (!parent)
|
|
||||||
return;
|
|
||||||
|
|
||||||
parent->nchildren++;
|
parent->nchildren++;
|
||||||
parent->children =
|
parent->children =
|
||||||
realloc(parent->children, parent->nchildren * sizeof(void*));
|
realloc(parent->children, parent->nchildren * sizeof(void*));
|
||||||
parent->children[parent->nchildren-1] = child;
|
parent->children[parent->nchildren-1] = child;
|
||||||
|
child->parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iso_tree_node_dir*
|
||||||
|
iso_tree_new_root()
|
||||||
|
{
|
||||||
|
struct iso_tree_node_dir *root;
|
||||||
|
|
||||||
|
root = calloc(1, sizeof(struct iso_tree_node_dir));
|
||||||
|
|
||||||
|
set_default_stat(&root->node.attrib);
|
||||||
|
root->node.attrib.st_mode = S_IFDIR | 0777;
|
||||||
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iso_tree_node*
|
struct iso_tree_node*
|
||||||
iso_tree_new_root(struct iso_volume *vol)
|
iso_tree_add_file(struct iso_tree_node_dir *parent, const char *path)
|
||||||
{
|
|
||||||
assert(vol);
|
|
||||||
|
|
||||||
if (vol->root) {
|
|
||||||
iso_tree_free(vol->root);
|
|
||||||
}
|
|
||||||
|
|
||||||
vol->root = calloc(1, sizeof(struct iso_tree_node));
|
|
||||||
vol->root->volume = vol;
|
|
||||||
set_default_stat(&vol->root->attrib);
|
|
||||||
vol->root->attrib.st_mode = S_IFDIR | 0777;
|
|
||||||
vol->root->loc.type = LIBISO_NONE;
|
|
||||||
return vol->root;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct iso_tree_node*
|
|
||||||
iso_tree_add_new_file(struct iso_tree_node *parent, const char *name)
|
|
||||||
{
|
|
||||||
struct iso_tree_node *f = calloc(1, sizeof(struct iso_tree_node));
|
|
||||||
|
|
||||||
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && name);
|
|
||||||
|
|
||||||
f->volume = parent ? parent->volume : NULL;
|
|
||||||
f->parent = parent;
|
|
||||||
f->name = parent ? strdup(name) : NULL;
|
|
||||||
f->attrib = get_attrib(parent);
|
|
||||||
f->attrib.st_mode = 0777 | S_IFREG;
|
|
||||||
f->loc.type = LIBISO_NONE;
|
|
||||||
append_node(parent, f);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct iso_tree_node*
|
|
||||||
iso_tree_add_new_dir(struct iso_tree_node *parent, const char *name)
|
|
||||||
{
|
|
||||||
struct iso_tree_node *d = iso_tree_add_new_file(parent, name);
|
|
||||||
|
|
||||||
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && name);
|
|
||||||
|
|
||||||
d->attrib.st_mode = (d->attrib.st_mode & ~S_IFMT) | S_IFDIR;
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct iso_tree_node*
|
|
||||||
iso_tree_add_node(struct iso_tree_node *parent, const char *path)
|
|
||||||
{
|
{
|
||||||
|
struct iso_tree_node_file *f;
|
||||||
char *p;
|
char *p;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct iso_tree_node *ret;
|
|
||||||
|
|
||||||
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && path);
|
assert( parent && path);
|
||||||
|
|
||||||
if (lstat(path, &st) == -1)
|
if (lstat(path, &st) == -1) {
|
||||||
|
libisofs_errno = NO_FILE;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !S_ISREG(st.st_mode) ) {
|
||||||
|
libisofs_errno = UNEXPECTED_FILE_TYPE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( access(path, R_OK) ) {
|
||||||
|
libisofs_errno = NO_READ_ACCESS;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = calloc(1, sizeof(struct iso_tree_node_file));
|
||||||
|
|
||||||
|
/* fill fields */
|
||||||
|
f->node.attrib = st;
|
||||||
|
f->path = strdup(path);
|
||||||
|
|
||||||
p = strdup(path); /* because basename() might modify its arg */
|
p = strdup(path); /* because basename() might modify its arg */
|
||||||
|
f->node.name = strdup( basename(p) );
|
||||||
/* it doesn't matter if we add a file or directory since we modify
|
|
||||||
* attrib anyway. */
|
|
||||||
ret = iso_tree_add_new_file(parent, basename(p));
|
|
||||||
ret->attrib = st;
|
|
||||||
ret->loc.type = LIBISO_FILESYS;
|
|
||||||
ret->loc.path = strdup(path);
|
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
return ret;
|
/* add to parent (this also sets f->node->parent) */
|
||||||
|
append_node(parent, (struct iso_tree_node*) f);
|
||||||
|
|
||||||
|
return (struct iso_tree_node*) f;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iso_tree_node*
|
struct iso_tree_node*
|
||||||
iso_tree_radd_dir (struct iso_tree_node *parent, const char *path)
|
iso_tree_add_symlink(struct iso_tree_node_dir *parent,
|
||||||
|
const char *name, const char *dest)
|
||||||
|
{
|
||||||
|
struct iso_tree_node_symlink *link;
|
||||||
|
|
||||||
|
assert( parent && name && dest);
|
||||||
|
|
||||||
|
link = calloc(1, sizeof(struct iso_tree_node_symlink));
|
||||||
|
|
||||||
|
/* fill fields */
|
||||||
|
set_default_stat(&link->node.attrib);
|
||||||
|
link->node.attrib.st_mode |= S_IFLNK;
|
||||||
|
link->node.name = strdup(name);
|
||||||
|
link->dest = strdup(dest);
|
||||||
|
|
||||||
|
/* add to parent (this also sets link->node->parent) */
|
||||||
|
append_node(parent, (struct iso_tree_node*) link);
|
||||||
|
|
||||||
|
return (struct iso_tree_node*) link;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iso_tree_node_dir*
|
||||||
|
iso_tree_add_dir(struct iso_tree_node_dir *parent,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct iso_tree_node_dir *dir;
|
||||||
|
|
||||||
|
assert( parent && name );
|
||||||
|
|
||||||
|
dir = calloc(1, sizeof(struct iso_tree_node_dir));
|
||||||
|
|
||||||
|
dir->node.attrib = parent->node.attrib;
|
||||||
|
dir->node.name = strdup(name);
|
||||||
|
|
||||||
|
append_node(parent, (struct iso_tree_node*) dir);
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
iso_tree_node_set_name(struct iso_tree_node *node, const char *name)
|
||||||
|
{
|
||||||
|
free(node->name);
|
||||||
|
node->name = strdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
iso_tree_node_set_hidden(struct iso_tree_node *node, int hide_attrs)
|
||||||
|
{
|
||||||
|
node->hide_flags = hide_attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iso_tree_node*
|
||||||
|
iso_tree_add_node(struct iso_tree_node_dir *parent,
|
||||||
|
const char *path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
struct iso_tree_node *node;
|
||||||
|
|
||||||
|
assert( parent && path);
|
||||||
|
|
||||||
|
if (lstat(path, &st) == -1) {
|
||||||
|
libisofs_errno = NO_FILE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( access(path, R_OK) ) {
|
||||||
|
libisofs_errno = NO_READ_ACCESS;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (st.st_mode & S_IFMT) {
|
||||||
|
case S_IFREG:
|
||||||
|
/* regular file */
|
||||||
|
node = iso_tree_add_file(parent, path);
|
||||||
|
break;
|
||||||
|
case S_IFLNK:
|
||||||
|
/* symlink */
|
||||||
|
{
|
||||||
|
char dest[PATH_MAX];
|
||||||
|
char *p;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = readlink(path, dest, PATH_MAX);
|
||||||
|
if ( n == -1 ) {
|
||||||
|
libisofs_errno = INTERNAL_ERROR;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dest[n] = '\0';
|
||||||
|
p = strdup(path); /* because basename() might modify its arg */
|
||||||
|
node = iso_tree_add_symlink(parent, basename(p), dest);
|
||||||
|
free(p);
|
||||||
|
node->attrib = st;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case S_IFDIR:
|
||||||
|
/* directory */
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
p = strdup(path); /* because basename() might modify its arg */
|
||||||
|
node = (struct iso_tree_node*) iso_tree_add_dir(parent, basename(p));
|
||||||
|
free(p);
|
||||||
|
node->attrib = st;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
libisofs_errno = UNEXPECTED_FILE_TYPE;
|
||||||
|
node = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
iso_tree_free(struct iso_tree_node *root)
|
||||||
|
{
|
||||||
|
if ( ISO_ISDIR(root) ) {
|
||||||
|
size_t i;
|
||||||
|
struct iso_tree_node_dir *dir;
|
||||||
|
dir = (struct iso_tree_node_dir *) root;
|
||||||
|
for (i=0; i < dir->nchildren; i++) {
|
||||||
|
iso_tree_free(dir->children[i]);
|
||||||
|
}
|
||||||
|
free(dir->children);
|
||||||
|
} else if ( ISO_ISLNK(root) ) {
|
||||||
|
struct iso_tree_node_symlink *link;
|
||||||
|
link = (struct iso_tree_node_symlink *) root;
|
||||||
|
free(link->dest);
|
||||||
|
} else if ( ISO_ISREG(root) ) {
|
||||||
|
struct iso_tree_node_file *file;
|
||||||
|
file = (struct iso_tree_node_file *) root;
|
||||||
|
free(file->path);
|
||||||
|
}
|
||||||
|
free(root->name);
|
||||||
|
free(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct iso_tree_node*
|
||||||
|
iso_tree_radd_dir_aux(struct iso_tree_node_dir *parent, const char *path,
|
||||||
|
struct iso_tree_radd_dir_behavior *behavior,
|
||||||
|
struct iso_hash_table *excludes)
|
||||||
{
|
{
|
||||||
struct iso_tree_node *new;
|
struct iso_tree_node *new;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
|
|
||||||
assert((!parent || S_ISDIR(parent->attrib.st_mode)) && path);
|
|
||||||
|
|
||||||
new = iso_tree_add_node(parent, path);
|
new = iso_tree_add_node(parent, path);
|
||||||
if (!new || !S_ISDIR(new->attrib.st_mode)) {
|
if (!new || !ISO_ISDIR(new)) {
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,44 +261,74 @@ iso_tree_radd_dir (struct iso_tree_node *parent, const char *path)
|
|||||||
strcmp(ent->d_name, "..") == 0)
|
strcmp(ent->d_name, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
//check if path already finished in '/'
|
||||||
sprintf(child, "%s/%s", path, ent->d_name);
|
sprintf(child, "%s/%s", path, ent->d_name);
|
||||||
|
|
||||||
/* see if this child is excluded. */
|
/* see if this child is excluded. */
|
||||||
if (iso_exclude_lookup(child))
|
if (iso_exclude_lookup(excludes, child))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
iso_tree_radd_dir(new, child);
|
if ( !iso_tree_radd_dir_aux( (struct iso_tree_node_dir *) new, child,
|
||||||
|
behavior, excludes) ) {
|
||||||
|
/* error */
|
||||||
|
behavior->error = 1;
|
||||||
|
if (behavior->stop_on_error)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
struct iso_tree_node_dir*
|
||||||
iso_tree_free(struct iso_tree_node *root)
|
iso_tree_radd_dir(struct iso_tree_node_dir *parent, const char *path,
|
||||||
|
struct iso_tree_radd_dir_behavior *behavior)
|
||||||
{
|
{
|
||||||
size_t i;
|
struct iso_tree_node_dir *dir;
|
||||||
|
struct iso_hash_table table = { {0,}, 0};
|
||||||
|
|
||||||
for (i=0; i < root->nchildren; i++) {
|
assert ( parent && path );
|
||||||
iso_tree_free(root->children[i]);
|
|
||||||
|
behavior->error = 0;
|
||||||
|
|
||||||
|
/* initialize exclude hash_table */
|
||||||
|
if ( behavior->excludes ) {
|
||||||
|
char *exclude;
|
||||||
|
int i = 0;
|
||||||
|
while ( (exclude = behavior->excludes[i++]) ) {
|
||||||
|
iso_exclude_add_path(&table, exclude);
|
||||||
}
|
}
|
||||||
free(root->name);
|
}
|
||||||
free(root->children);
|
|
||||||
free(root);
|
/* recurse into dir */
|
||||||
|
dir = (struct iso_tree_node_dir*) iso_tree_radd_dir_aux(
|
||||||
|
parent, path, behavior, &table);
|
||||||
|
|
||||||
|
/* clear hashtable */
|
||||||
|
iso_exclude_empty(&table);
|
||||||
|
|
||||||
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iso_tree_print(const struct iso_tree_node *root, int spaces)
|
iso_tree_print(const struct iso_tree_node *root, int spaces)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
char sp[spaces+1];
|
char sp[spaces+1];
|
||||||
|
|
||||||
memset(sp, ' ', spaces);
|
memset(sp, ' ', spaces);
|
||||||
sp[spaces] = '\0';
|
sp[spaces] = '\0';
|
||||||
|
|
||||||
printf("%s%s\n", sp, root->name);
|
printf("%s%s\n", sp, root->name);
|
||||||
for (i=0; i < root->nchildren; i++) {
|
|
||||||
iso_tree_print(root->children[i], spaces+2);
|
if ( ISO_ISDIR(root) ) {
|
||||||
|
size_t i;
|
||||||
|
struct iso_tree_node_dir *dir;
|
||||||
|
|
||||||
|
dir = (struct iso_tree_node_dir *) root;
|
||||||
|
for (i=0; i < dir->nchildren; i++) {
|
||||||
|
iso_tree_print(dir->children[i], spaces+2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,19 +339,18 @@ iso_tree_print_verbose(const struct iso_tree_node *root,
|
|||||||
void *callback_data,
|
void *callback_data,
|
||||||
int spaces)
|
int spaces)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
|
|
||||||
(S_ISDIR(root->attrib.st_mode) ? dir : file)
|
(S_ISDIR(root->attrib.st_mode) ? dir : file)
|
||||||
(root, callback_data, spaces);
|
(root, callback_data, spaces);
|
||||||
for (i=0; i < root->nchildren; i++) {
|
|
||||||
iso_tree_print_verbose(root->children[i], dir,
|
if ( ISO_ISDIR(root) ) {
|
||||||
|
size_t i;
|
||||||
|
struct iso_tree_node_dir *dir_node;
|
||||||
|
|
||||||
|
dir_node = (struct iso_tree_node_dir *) root;
|
||||||
|
for (i=0; i < dir_node->nchildren; i++) {
|
||||||
|
iso_tree_print_verbose(dir_node->children[i], dir,
|
||||||
file, callback_data, spaces+2);
|
file, callback_data, spaces+2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
iso_tree_node_set_name(struct iso_tree_node *file, const char *name)
|
|
||||||
{
|
|
||||||
free(file->name);
|
|
||||||
file->name = strdup(name);
|
|
||||||
}
|
}
|
||||||
|
111
libisofs/tree.h
111
libisofs/tree.h
@ -24,46 +24,46 @@
|
|||||||
|
|
||||||
#include "libisofs.h"
|
#include "libisofs.h"
|
||||||
|
|
||||||
enum file_location {
|
//enum file_location {
|
||||||
LIBISO_FILESYS,
|
// LIBISO_FILESYS,
|
||||||
LIBISO_PREVSESSION,
|
// LIBISO_PREVSESSION,
|
||||||
LIBISO_NONE /**< for files/dirs that were added with
|
// LIBISO_NONE /**< for files/dirs that were added with
|
||||||
* iso_tree_add_new_XXX. */
|
// * iso_tree_add_new_XXX. */
|
||||||
|
//};
|
||||||
|
|
||||||
|
enum hide_node {
|
||||||
|
LIBISO_HIDE_ON_RR = 1 << 0,
|
||||||
|
LIBISO_HIDE_ON_JOLIET = 1 << 1
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This tells us where to read the data from a file. Either we read from the
|
* This tells us where to read the data from a file. Either we read from the
|
||||||
* local filesystem or we just point to the block on a previous session.
|
* local filesystem or we just point to the block on a previous session.
|
||||||
*/
|
*/
|
||||||
struct iso_file_location
|
//struct iso_file_location
|
||||||
{
|
//{
|
||||||
enum file_location type;
|
// enum file_location type;
|
||||||
/* union {*/
|
// /* union {*/
|
||||||
char *path; /* in the current locale */
|
// char *path; /* in the current locale */
|
||||||
uint32_t block;
|
// uint32_t block;
|
||||||
/* };*/
|
// /* };*/
|
||||||
};
|
//};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node in the filesystem tree.
|
* A node in the filesystem tree.
|
||||||
*/
|
*/
|
||||||
struct iso_tree_node
|
struct iso_tree_node
|
||||||
{
|
{
|
||||||
struct iso_volume *volume;
|
/*struct iso_volume *volume; TODO not needed? */
|
||||||
struct iso_tree_node *parent;
|
struct iso_tree_node_dir *parent;
|
||||||
char *name;
|
char *name;
|
||||||
struct stat attrib; /**< The POSIX attributes of this node as
|
struct stat attrib; /**< The POSIX attributes of this node as
|
||||||
* documented in "man 2 stat". */
|
* documented in "man 2 stat". */
|
||||||
struct iso_file_location loc;
|
|
||||||
/**< Only used for regular files and symbolic
|
|
||||||
* links (ie. files for which we might have to
|
|
||||||
* copy data). */
|
|
||||||
|
|
||||||
size_t nchildren; /**< The number of children of this
|
int hide_flags; /**< If the node is to be hidden in RR/ISO or
|
||||||
* directory (if this is a directory). */
|
* Joilet tree */
|
||||||
struct iso_tree_node **children;
|
|
||||||
|
|
||||||
size_t block; /**< The block at which this file will
|
/*size_t block;*/ /**< The block at which this file will
|
||||||
* reside on disk. We store this here as
|
* reside on disk. We store this here as
|
||||||
* well as in the various mangled trees
|
* well as in the various mangled trees
|
||||||
* because many different trees might point
|
* because many different trees might point
|
||||||
@ -72,34 +72,49 @@ struct iso_tree_node
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new root directory for a volume.
|
* A node in the filesystem tree that represents a regular file
|
||||||
*
|
|
||||||
* \param vol The volume for which to create a new root directory.
|
|
||||||
*
|
|
||||||
* \pre \p vol is non-NULL.
|
|
||||||
* \post \p vol has a non-NULL, empty root directory with permissions 777.
|
|
||||||
* \return \p vol's new non-NULL, empty root directory.
|
|
||||||
*/
|
*/
|
||||||
struct iso_tree_node *iso_tree_new_root(struct iso_volume *vol);
|
struct iso_tree_node_file
|
||||||
|
{
|
||||||
|
struct iso_tree_node node;
|
||||||
|
|
||||||
|
char *path; /**< the path of the file on local filesystem */
|
||||||
|
int sort_weight; /**< It sorts the order in which the file data is
|
||||||
|
* written to the CD image. Higher weighting files
|
||||||
|
* are written at the beginning of image */
|
||||||
|
|
||||||
|
/* when read from an existing ISO image, we need to store the
|
||||||
|
* block where file contents are written, and not the path.
|
||||||
|
* Maybe instead of a char *path we will need to go back to
|
||||||
|
* struct iso_file_location loc;
|
||||||
|
*/
|
||||||
|
/* struct iso_file_location loc; */
|
||||||
|
/**< Only used for regular files and symbolic
|
||||||
|
* links (ie. files for which we might have to
|
||||||
|
* copy data). */
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new, empty, file.
|
* A node in the filesystem tree that represents a symbolic link
|
||||||
*
|
|
||||||
* \param parent The parent directory of the new file. If this is null, create
|
|
||||||
* and return a new file node without adding it to any tree.
|
|
||||||
* \param name The name of the new file, encoded in the current locale.
|
|
||||||
* \pre \p name is non-NULL and it does not match any other file or directory
|
|
||||||
* name in \p parent.
|
|
||||||
* \post \p parent (if non-NULL) contains a file with the following properties:
|
|
||||||
* - the file's name is \p name (converted to wchar_t)
|
|
||||||
* - the file's POSIX permissions are the same as \p parent's
|
|
||||||
* - the file is a regular file
|
|
||||||
* - the file is empty
|
|
||||||
*
|
|
||||||
* \return \p parent's newly created file.
|
|
||||||
*/
|
*/
|
||||||
struct iso_tree_node *iso_tree_add_new_file(struct iso_tree_node *parent,
|
struct iso_tree_node_symlink
|
||||||
const char *name);
|
{
|
||||||
|
struct iso_tree_node node;
|
||||||
|
|
||||||
|
char *dest; /**< Destination of the link */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A directory on the filesystem tree
|
||||||
|
*/
|
||||||
|
struct iso_tree_node_dir
|
||||||
|
{
|
||||||
|
struct iso_tree_node node;
|
||||||
|
|
||||||
|
size_t nchildren; /**< The number of children of this
|
||||||
|
* directory (if this is a directory). */
|
||||||
|
struct iso_tree_node **children;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively free a directory.
|
* Recursively free a directory.
|
||||||
@ -155,5 +170,7 @@ void iso_tree_print_verbose(const struct iso_tree_node *root,
|
|||||||
int spaces);
|
int spaces);
|
||||||
|
|
||||||
#define ISO_ISDIR(n) S_ISDIR(n->attrib.st_mode)
|
#define ISO_ISDIR(n) S_ISDIR(n->attrib.st_mode)
|
||||||
|
#define ISO_ISREG(n) S_ISREG(n->attrib.st_mode)
|
||||||
|
#define ISO_ISLNK(n) S_ISLNK(n->attrib.st_mode)
|
||||||
|
|
||||||
#endif /* LIBISO_TREE_H */
|
#endif /* LIBISO_TREE_H */
|
||||||
|
147
libisofs/util.c
147
libisofs/util.c
@ -17,6 +17,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@ -35,6 +36,53 @@ int round_up(int n, int mul)
|
|||||||
return div_up(n, mul) * mul;
|
return div_up(n, mul) * mul;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a string between charsets.
|
||||||
|
* This assumes '\0' means end-of-string, what is not necessarily true,
|
||||||
|
* but given there are lots of strdup around there, it will fail in other
|
||||||
|
* places anyway...
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
convert_str(const char *str, const char *icharset, const char *ocharset)
|
||||||
|
{
|
||||||
|
char *ret;
|
||||||
|
size_t inbytes;
|
||||||
|
size_t outbytes;
|
||||||
|
|
||||||
|
inbytes = strlen(str);
|
||||||
|
outbytes = (inbytes+1) * MB_LEN_MAX;
|
||||||
|
{
|
||||||
|
/* ensure enought space */
|
||||||
|
char out[outbytes];
|
||||||
|
char *src;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
iconv_t conv = iconv_open(ocharset, icharset);
|
||||||
|
if (conv == (iconv_t)(-1)) {
|
||||||
|
printf("Can't convert from %s to %s\n", icharset, ocharset);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
src = (char *)str;
|
||||||
|
ret = (char *)out;
|
||||||
|
|
||||||
|
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||||
|
if (n == -1) {
|
||||||
|
/* error just return input stream */
|
||||||
|
perror("Convert error.");
|
||||||
|
printf("Maybe string %s is not encoded in %s\n", str, icharset);
|
||||||
|
|
||||||
|
iconv_close(conv);
|
||||||
|
return strdup(str);
|
||||||
|
}
|
||||||
|
iconv_close(conv);
|
||||||
|
*ret = '\0';
|
||||||
|
|
||||||
|
ret = strdup(out);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a str in a specified codeset to WCHAR_T.
|
* Convert a str in a specified codeset to WCHAR_T.
|
||||||
* The result must be free() when no more needed
|
* The result must be free() when no more needed
|
||||||
@ -64,18 +112,23 @@ static wchar_t *str2wchar(const char *str, const char *codeset)
|
|||||||
src = (char *)str;
|
src = (char *)str;
|
||||||
|
|
||||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||||
if (n == -1) {
|
while (n == -1) {
|
||||||
|
|
||||||
|
if( errno != EINVAL ) {
|
||||||
/* error, should never occur */
|
/* error, should never occur */
|
||||||
/*
|
iconv_close(conv);
|
||||||
* FIXME
|
|
||||||
* The above assumption is not always true, because the str could
|
|
||||||
* actually not be encoded in specified codeset. This can lead to
|
|
||||||
* problems if, for example, a file is not in UTF-8. You should
|
|
||||||
* take care about this in a way like str2ascii
|
|
||||||
*/
|
|
||||||
perror("Convert error\n");
|
perror("Convert error\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* invalid input string charset, just log and ignore */
|
||||||
|
printf("String %s is not encoded in %s\n", str, codeset);
|
||||||
|
inbytes--;
|
||||||
|
|
||||||
|
if(!inbytes)
|
||||||
|
break;
|
||||||
|
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||||
|
}
|
||||||
iconv_close(conv);
|
iconv_close(conv);
|
||||||
|
|
||||||
*( (wchar_t *)ret )='\0';
|
*( (wchar_t *)ret )='\0';
|
||||||
@ -85,7 +138,7 @@ static wchar_t *str2wchar(const char *str, const char *codeset)
|
|||||||
/* this function must always return a name
|
/* this function must always return a name
|
||||||
* since the caller never checks if a NULL
|
* since the caller never checks if a NULL
|
||||||
* is returned. It also avoids some warnings. */
|
* is returned. It also avoids some warnings. */
|
||||||
char *str2ascii(const char *src_arg)
|
char *str2ascii(const char *src_arg, const char *icharset)
|
||||||
{
|
{
|
||||||
wchar_t *wsrc_;
|
wchar_t *wsrc_;
|
||||||
char *ret;
|
char *ret;
|
||||||
@ -97,6 +150,8 @@ char *str2ascii(const char *src_arg)
|
|||||||
size_t inbytes;
|
size_t inbytes;
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
|
assert(icharset);
|
||||||
|
|
||||||
if (!src_arg)
|
if (!src_arg)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -108,7 +163,7 @@ char *str2ascii(const char *src_arg)
|
|||||||
* this later.
|
* this later.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wsrc_ = str2wchar(src_arg, "UTF-8");
|
wsrc_ = str2wchar(src_arg, icharset);
|
||||||
|
|
||||||
if (!wsrc_)
|
if (!wsrc_)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -172,13 +227,12 @@ char *str2ascii(const char *src_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: C&P */
|
/* FIXME: C&P */
|
||||||
uint16_t *str2ucs(const char *src_arg)
|
uint16_t *str2ucs(const char *src_arg, const char *icharset)
|
||||||
{
|
{
|
||||||
wchar_t wsrc_[NAME_BUFFER_SIZE];
|
wchar_t *wsrc_;
|
||||||
char *src = (char*)wsrc_;
|
char *src;
|
||||||
char *ret_;
|
char *ret_;
|
||||||
char *ret;
|
char *ret;
|
||||||
mbstate_t state;
|
|
||||||
iconv_t conv;
|
iconv_t conv;
|
||||||
size_t outbytes;
|
size_t outbytes;
|
||||||
size_t numchars;
|
size_t numchars;
|
||||||
@ -188,13 +242,17 @@ uint16_t *str2ucs(const char *src_arg)
|
|||||||
if (!src_arg)
|
if (!src_arg)
|
||||||
return calloc(2, 1); /* empty UCS string */
|
return calloc(2, 1); /* empty UCS string */
|
||||||
|
|
||||||
|
|
||||||
/* convert the string to a wide character string. Note: outbytes
|
/* convert the string to a wide character string. Note: outbytes
|
||||||
* is in fact the number of characters in the string and doesn't
|
* is in fact the number of characters in the string and doesn't
|
||||||
* include the last NULL character. */
|
* include the last NULL character.
|
||||||
memset(&state, 0, sizeof(state));
|
*/
|
||||||
numchars = mbsrtowcs(wsrc_, &src_arg, NAME_BUFFER_SIZE-1, &state);
|
|
||||||
if (numchars < 0)
|
wsrc_ = str2wchar(src_arg, icharset);
|
||||||
|
if (!wsrc_)
|
||||||
return calloc(2, 1); /* empty UCS string */
|
return calloc(2, 1); /* empty UCS string */
|
||||||
|
src = (char*)wsrc_;
|
||||||
|
numchars = wcslen(wsrc_);
|
||||||
|
|
||||||
inbytes = numchars * sizeof(wchar_t);
|
inbytes = numchars * sizeof(wchar_t);
|
||||||
|
|
||||||
@ -276,14 +334,14 @@ static int valid_p_char(char c)
|
|||||||
|| (c == '.') || (c == '_') || (c == '-');
|
|| (c == '.') || (c == '_') || (c == '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
char *str2d_char(const char *str) {
|
char *str2d_char(const char *str, const char *icharset) {
|
||||||
char *ret;
|
char *ret;
|
||||||
size_t len, i;
|
size_t len, i;
|
||||||
|
|
||||||
if (!str)
|
if (!str)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret = str2ascii(str);
|
ret = str2ascii(str, icharset);
|
||||||
len = strlen(ret);
|
len = strlen(ret);
|
||||||
|
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
@ -294,14 +352,14 @@ char *str2d_char(const char *str) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *str2a_char(const char *str) {
|
char *str2a_char(const char *str, const char *icharset) {
|
||||||
char *ret;
|
char *ret;
|
||||||
size_t len, i;
|
size_t len, i;
|
||||||
|
|
||||||
if (!str)
|
if (!str)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret = str2ascii(str);
|
ret = str2ascii(str, icharset);
|
||||||
len = strlen(ret);
|
len = strlen(ret);
|
||||||
|
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
@ -312,9 +370,9 @@ char *str2a_char(const char *str) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *iso_dirid(const char *src, int size)
|
static char *iso_dirid(const char *src, int size, const char *icharset)
|
||||||
{
|
{
|
||||||
char *ret = str2ascii(src);
|
char *ret = str2ascii(src, icharset);
|
||||||
size_t len, i;
|
size_t len, i;
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
@ -333,19 +391,19 @@ static char *iso_dirid(const char *src, int size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *iso_1_dirid(const char *src)
|
char *iso_1_dirid(const char *src, const char *icharset)
|
||||||
{
|
{
|
||||||
return iso_dirid(src, 8);
|
return iso_dirid(src, 8, icharset);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *iso_2_dirid(const char *src)
|
char *iso_2_dirid(const char *src, const char *icharset)
|
||||||
{
|
{
|
||||||
return iso_dirid(src, 31);
|
return iso_dirid(src, 31, icharset);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *iso_1_fileid(const char *src_arg)
|
char *iso_1_fileid(const char *src_arg, const char *icharset)
|
||||||
{
|
{
|
||||||
char *src = str2ascii(src_arg);
|
char *src = str2ascii(src_arg, icharset);
|
||||||
char *dest;
|
char *dest;
|
||||||
char *dot; /* Position of the last dot in the
|
char *dot; /* Position of the last dot in the
|
||||||
filename, will be used to calculate
|
filename, will be used to calculate
|
||||||
@ -394,9 +452,9 @@ char *iso_1_fileid(const char *src_arg)
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *iso_2_fileid(const char *src_arg)
|
char *iso_2_fileid(const char *src_arg, const char *icharset)
|
||||||
{
|
{
|
||||||
char *src = str2ascii(src_arg);
|
char *src = str2ascii(src_arg, icharset);
|
||||||
char *dest;
|
char *dest;
|
||||||
char *dot;
|
char *dot;
|
||||||
int lname, lext, lnname, lnext, pos, i;
|
int lname, lext, lnname, lnext, pos, i;
|
||||||
@ -454,9 +512,9 @@ char *iso_2_fileid(const char *src_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
iso_p_fileid(const char *src)
|
iso_p_fileid(const char *src, const char *icharset)
|
||||||
{
|
{
|
||||||
char *ret = str2ascii(src);
|
char *ret = str2ascii(src, icharset);
|
||||||
size_t i, len;
|
size_t i, len;
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
@ -471,9 +529,9 @@ iso_p_fileid(const char *src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t *
|
uint16_t *
|
||||||
iso_j_id(const char *src_arg)
|
iso_j_id(const char *src_arg, const char *icharset)
|
||||||
{
|
{
|
||||||
uint16_t *j_str = str2ucs(src_arg);
|
uint16_t *j_str = str2ucs(src_arg, icharset);
|
||||||
size_t len = ucslen(j_str);
|
size_t len = ucslen(j_str);
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
@ -514,7 +572,6 @@ void iso_bb(uint8_t *buf, uint32_t num, int bytes)
|
|||||||
iso_msb(buf+bytes, num, bytes);
|
iso_msb(buf+bytes, num, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void iso_datetime_7(unsigned char *buf, time_t t)
|
void iso_datetime_7(unsigned char *buf, time_t t)
|
||||||
{
|
{
|
||||||
static int tzsetup = 0;
|
static int tzsetup = 0;
|
||||||
@ -535,12 +592,12 @@ void iso_datetime_7(unsigned char *buf, time_t t)
|
|||||||
buf[4] = tm.tm_min;
|
buf[4] = tm.tm_min;
|
||||||
buf[5] = tm.tm_sec;
|
buf[5] = tm.tm_sec;
|
||||||
#ifdef HAVE_TM_GMTOFF
|
#ifdef HAVE_TM_GMTOFF
|
||||||
tzoffset = -tm.tm_gmtoff / 60 / 15;
|
tzoffset = tm.tm_gmtoff / 60 / 15;
|
||||||
#else
|
#else
|
||||||
tzoffset = -timezone / 60 / 15;
|
tzoffset = timezone / 60 / 15;
|
||||||
#endif
|
#endif
|
||||||
if (tzoffset < -48)
|
if (tzoffset > 52)
|
||||||
tzoffset += 101;
|
tzoffset -= 101;
|
||||||
buf[6] = tzoffset;
|
buf[6] = tzoffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,12 +641,12 @@ void iso_datetime_17(unsigned char *buf, time_t t)
|
|||||||
sprintf((char*)&buf[12], "%02d", MIN(59, tm.tm_sec));
|
sprintf((char*)&buf[12], "%02d", MIN(59, tm.tm_sec));
|
||||||
memcpy(&buf[14], "00", 2);
|
memcpy(&buf[14], "00", 2);
|
||||||
#ifdef HAVE_TM_GMTOFF
|
#ifdef HAVE_TM_GMTOFF
|
||||||
tzoffset = -tm.tm_gmtoff / 60 / 15;
|
tzoffset = tm.tm_gmtoff / 60 / 15;
|
||||||
#else
|
#else
|
||||||
tzoffset = -timezone / 60 / 15;
|
tzoffset = timezone / 60 / 15;
|
||||||
#endif
|
#endif
|
||||||
if (tzoffset < -48)
|
if (tzoffset > 52)
|
||||||
tzoffset += 101;
|
tzoffset -= 101;
|
||||||
buf[16] = tzoffset;
|
buf[16] = tzoffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,22 +30,24 @@ extern inline int round_up(int n, int mul)
|
|||||||
return div_up(n, mul) * mul;
|
return div_up(n, mul) * mul;
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *towcs(const char *);
|
char *convert_str(const char *str, const char *icharset, const char *ocharset);
|
||||||
char *str2ascii(const char*);
|
|
||||||
uint16_t *str2ucs(const char*);
|
|
||||||
|
|
||||||
char *str2d_char(const char*);
|
wchar_t *towcs(const char *);
|
||||||
char *str2a_char(const char*);
|
char *str2ascii(const char*, const char *);
|
||||||
|
uint16_t *str2ucs(const char *, const char *);
|
||||||
|
|
||||||
|
char *str2d_char(const char*, const char *);
|
||||||
|
char *str2a_char(const char*, const char *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a level 1 directory identifier.
|
* Create a level 1 directory identifier.
|
||||||
*/
|
*/
|
||||||
char *iso_1_dirid(const char *src);
|
char *iso_1_dirid(const char *src, const char *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a level 2 directory identifier.
|
* Create a level 2 directory identifier.
|
||||||
*/
|
*/
|
||||||
char *iso_2_dirid(const char *src);
|
char *iso_2_dirid(const char *src, const char *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a level 1 file identifier that consists of a name, extension and
|
* Create a level 1 file identifier that consists of a name, extension and
|
||||||
@ -54,7 +56,7 @@ char *iso_2_dirid(const char *src);
|
|||||||
* length 3, followed by a separator (;) and a version number (digit 1).
|
* length 3, followed by a separator (;) and a version number (digit 1).
|
||||||
* @return NULL if the original name and extension both are of length 0.
|
* @return NULL if the original name and extension both are of length 0.
|
||||||
*/
|
*/
|
||||||
char *iso_1_fileid(const char *src);
|
char *iso_1_fileid(const char *src, const char *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a level 2 file identifier that consists of a name, extension and
|
* Create a level 2 file identifier that consists of a name, extension and
|
||||||
@ -63,7 +65,7 @@ char *iso_1_fileid(const char *src);
|
|||||||
* followed by a separator (;) and a version number (digit 1).
|
* followed by a separator (;) and a version number (digit 1).
|
||||||
* @return NULL if the original name and extension both are of length 0.
|
* @return NULL if the original name and extension both are of length 0.
|
||||||
*/
|
*/
|
||||||
char *iso_2_fileid(const char *src);
|
char *iso_2_fileid(const char *src, const char *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Joliet file or directory identifier that consists of a name,
|
* Create a Joliet file or directory identifier that consists of a name,
|
||||||
@ -76,7 +78,7 @@ char *iso_2_fileid(const char *src);
|
|||||||
* @param size will be set to the size (in bytes) of the identifier.
|
* @param size will be set to the size (in bytes) of the identifier.
|
||||||
* @return NULL if the original name and extension both are of length 0 or the conversion from the current codeset to UCS-2BE is not available.
|
* @return NULL if the original name and extension both are of length 0 or the conversion from the current codeset to UCS-2BE is not available.
|
||||||
*/
|
*/
|
||||||
uint16_t *iso_j_id(const char *src);
|
uint16_t *iso_j_id(const char *src, const char *icharset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FIXME: what are the requirements for these next two? Is this for RR?
|
* FIXME: what are the requirements for these next two? Is this for RR?
|
||||||
@ -85,7 +87,7 @@ uint16_t *iso_j_id(const char *src);
|
|||||||
* The resulting file name will not exceed 250 characters.
|
* The resulting file name will not exceed 250 characters.
|
||||||
* @return NULL if the original name and extension both are of length 0.
|
* @return NULL if the original name and extension both are of length 0.
|
||||||
*/
|
*/
|
||||||
char *iso_p_fileid(const char *src);
|
char *iso_p_fileid(const char *src, const char *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a POSIX portable directory name.
|
* Create a POSIX portable directory name.
|
||||||
|
@ -52,14 +52,14 @@ struct iso_volume*
|
|||||||
iso_volume_new_with_root(const char *volume_id,
|
iso_volume_new_with_root(const char *volume_id,
|
||||||
const char *publisher_id,
|
const char *publisher_id,
|
||||||
const char *data_preparer_id,
|
const char *data_preparer_id,
|
||||||
struct iso_tree_node *root)
|
struct iso_tree_node_dir *root)
|
||||||
{
|
{
|
||||||
struct iso_volume *volume;
|
struct iso_volume *volume;
|
||||||
|
|
||||||
volume = calloc(1, sizeof(struct iso_volume));
|
volume = calloc(1, sizeof(struct iso_volume));
|
||||||
volume->refcount = 1;
|
volume->refcount = 1;
|
||||||
|
|
||||||
volume->root = root ? root : iso_tree_new_root(volume);
|
volume->root = root ? root : iso_tree_new_root();
|
||||||
|
|
||||||
if (volume_id != NULL)
|
if (volume_id != NULL)
|
||||||
volume->volume_id = strdup(volume_id);
|
volume->volume_id = strdup(volume_id);
|
||||||
@ -75,7 +75,7 @@ iso_volume_free(struct iso_volume *volume)
|
|||||||
{
|
{
|
||||||
/* Only free if no references are in use. */
|
/* Only free if no references are in use. */
|
||||||
if (--volume->refcount < 1) {
|
if (--volume->refcount < 1) {
|
||||||
iso_tree_free(volume->root);
|
iso_tree_free( (struct iso_tree_node*) volume->root);
|
||||||
|
|
||||||
free(volume->volume_id);
|
free(volume->volume_id);
|
||||||
free(volume->publisher_id);
|
free(volume->publisher_id);
|
||||||
@ -85,7 +85,7 @@ iso_volume_free(struct iso_volume *volume)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iso_tree_node *
|
struct iso_tree_node_dir *
|
||||||
iso_volume_get_root(const struct iso_volume *volume)
|
iso_volume_get_root(const struct iso_volume *volume)
|
||||||
{
|
{
|
||||||
return volume->root;
|
return volume->root;
|
||||||
@ -139,98 +139,98 @@ void iso_volume_set_biblio_file_id(struct iso_volume *volume,
|
|||||||
volume->biblio_file_id = strdup(biblio_file_id);
|
volume->biblio_file_id = strdup(biblio_file_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iso_tree_node *
|
//struct iso_tree_node *
|
||||||
iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path)
|
//iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path)
|
||||||
{
|
//{
|
||||||
struct iso_tree_node *node;
|
// struct iso_tree_node *node;
|
||||||
char *ptr, *brk_info, *component;
|
// char *ptr, *brk_info, *component;
|
||||||
|
//
|
||||||
/* get the first child at the root of the volume
|
// /* get the first child at the root of the volume
|
||||||
* that is "/" */
|
// * that is "/" */
|
||||||
node=iso_volume_get_root(volume);
|
// node=iso_volume_get_root(volume);
|
||||||
if (!strcmp (path, "/"))
|
// if (!strcmp (path, "/"))
|
||||||
return node;
|
// return node;
|
||||||
|
//
|
||||||
if (!node->nchildren)
|
// if (!node->nchildren)
|
||||||
return NULL;
|
// return NULL;
|
||||||
|
//
|
||||||
/* the name of the nodes is in wide characters so first convert path
|
// /* the name of the nodes is in wide characters so first convert path
|
||||||
* into wide characters. */
|
// * into wide characters. */
|
||||||
ptr = strdup(path);
|
// ptr = strdup(path);
|
||||||
|
//
|
||||||
/* get the first component of the path */
|
// /* get the first component of the path */
|
||||||
component=strtok_r(ptr, "/", &brk_info);
|
// component=strtok_r(ptr, "/", &brk_info);
|
||||||
while (component) {
|
// while (component) {
|
||||||
size_t max;
|
// size_t max;
|
||||||
size_t i;
|
// size_t i;
|
||||||
|
//
|
||||||
/* search among all the children of this directory if this path component exists */
|
// /* search among all the children of this directory if this path component exists */
|
||||||
max=node->nchildren;
|
// max=node->nchildren;
|
||||||
for (i=0; i < max; i++) {
|
// for (i=0; i < max; i++) {
|
||||||
if (!strcmp(component, node->children[i]->name)) {
|
// if (!strcmp(component, node->children[i]->name)) {
|
||||||
node=node->children[i];
|
// node=node->children[i];
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/* see if a node could be found */
|
// /* see if a node could be found */
|
||||||
if (i==max) {
|
// if (i==max) {
|
||||||
node=NULL;
|
// node=NULL;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
component=strtok_r(NULL, "/", &brk_info);
|
// component=strtok_r(NULL, "/", &brk_info);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
free(ptr);
|
// free(ptr);
|
||||||
return node;
|
// return node;
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
struct iso_tree_node *
|
//struct iso_tree_node *
|
||||||
iso_tree_volume_add_path(struct iso_volume *volume,
|
//iso_tree_volume_add_path(struct iso_volume *volume,
|
||||||
const char *disc_path,
|
// const char *disc_path,
|
||||||
const char *path)
|
// const char *path)
|
||||||
{
|
//{
|
||||||
char *tmp;
|
// char *tmp;
|
||||||
struct iso_tree_node *node;
|
// struct iso_tree_node *node;
|
||||||
struct iso_tree_node *parent_node;
|
// struct iso_tree_node *parent_node;
|
||||||
|
//
|
||||||
tmp=strdup(disc_path);
|
// tmp=strdup(disc_path);
|
||||||
parent_node = iso_tree_volume_path_to_node(volume, dirname(tmp));
|
// parent_node = iso_tree_volume_path_to_node(volume, dirname(tmp));
|
||||||
free(tmp);
|
// free(tmp);
|
||||||
|
//
|
||||||
if (!parent_node)
|
// if (!parent_node)
|
||||||
return NULL;
|
// return NULL;
|
||||||
|
//
|
||||||
node = iso_tree_radd_dir(parent_node, path);
|
// node = iso_tree_radd_dir(parent_node, path);
|
||||||
if (!node)
|
// if (!node)
|
||||||
return NULL;
|
// return NULL;
|
||||||
|
//
|
||||||
tmp=strdup(disc_path);
|
// tmp=strdup(disc_path);
|
||||||
iso_tree_node_set_name(node, basename(tmp));
|
// iso_tree_node_set_name(node, basename(tmp));
|
||||||
free(tmp);
|
// free(tmp);
|
||||||
|
//
|
||||||
return node;
|
// return node;
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
struct iso_tree_node *
|
//struct iso_tree_node *
|
||||||
iso_tree_volume_add_new_dir(struct iso_volume *volume,
|
//iso_tree_volume_add_new_dir(struct iso_volume *volume,
|
||||||
const char *disc_path)
|
// const char *disc_path)
|
||||||
{
|
//{
|
||||||
char *tmp;
|
// char *tmp;
|
||||||
struct iso_tree_node *node;
|
// struct iso_tree_node *node;
|
||||||
struct iso_tree_node *parent_node;
|
// struct iso_tree_node *parent_node;
|
||||||
|
//
|
||||||
tmp=strdup(disc_path);
|
// tmp=strdup(disc_path);
|
||||||
parent_node = iso_tree_volume_path_to_node(volume, dirname(tmp));
|
// parent_node = iso_tree_volume_path_to_node(volume, dirname(tmp));
|
||||||
free(tmp);
|
// free(tmp);
|
||||||
|
//
|
||||||
if (!parent_node)
|
// if (!parent_node)
|
||||||
return NULL;
|
// return NULL;
|
||||||
|
//
|
||||||
tmp=strdup(disc_path);
|
// tmp=strdup(disc_path);
|
||||||
node = iso_tree_add_new_dir(parent_node, basename(tmp));
|
// node = iso_tree_add_new_dir(parent_node, basename(tmp));
|
||||||
free(tmp);
|
// free(tmp);
|
||||||
|
//
|
||||||
return node;
|
// return node;
|
||||||
}
|
//}
|
||||||
|
@ -18,7 +18,7 @@ struct iso_volume
|
|||||||
int refcount; /**< Number of used references to this
|
int refcount; /**< Number of used references to this
|
||||||
volume. */
|
volume. */
|
||||||
|
|
||||||
struct iso_tree_node *root; /**< Root of the directory tree for the
|
struct iso_tree_node_dir *root; /**< Root of the directory tree for the
|
||||||
volume. */
|
volume. */
|
||||||
|
|
||||||
char *volume_id; /**< Volume identifier. */
|
char *volume_id; /**< Volume identifier. */
|
||||||
|
@ -44,11 +44,12 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
struct iso_volset *volset;
|
struct iso_volset *volset;
|
||||||
struct iso_volume *volume;
|
struct iso_volume *volume;
|
||||||
struct iso_tree_node *root;
|
struct iso_tree_node_dir *root;
|
||||||
struct burn_source *src;
|
struct burn_source *src;
|
||||||
unsigned char buf[2048];
|
unsigned char buf[2048];
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
int c;
|
int c;
|
||||||
|
struct iso_tree_radd_dir_behavior behav = {0,0,0};
|
||||||
int level=1, flags=0;
|
int level=1, flags=0;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, optstring)) != -1) {
|
while ((c = getopt(argc, argv, optstring)) != -1) {
|
||||||
@ -89,7 +90,8 @@ int main(int argc, char **argv)
|
|||||||
err(1, "error opening output file");
|
err(1, "error opening output file");
|
||||||
}
|
}
|
||||||
|
|
||||||
root = iso_tree_radd_dir(NULL, argv[optind]);
|
root = iso_tree_new_root();
|
||||||
|
iso_tree_radd_dir(root, argv[optind], &behav);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
err(1, "error opening input directory");
|
err(1, "error opening input directory");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user