diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index 6b53469..07154ce 100755 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -316,7 +316,6 @@ ecma119_target_new(struct iso_volset *volset, t->dirlist = calloc(1, sizeof(void*) * t->dirlist_len); t->pathlist = calloc(1, sizeof(void*) * t->dirlist_len); - //t->filelist = calloc(1, sizeof(void*) * t->filelist_len); /* fill out the pathlist */ t->pathlist[0] = t->root; @@ -365,8 +364,6 @@ ecma119_target_new(struct iso_volset *volset, t->curfile = 0; } calc_file_pos(t, t->root); - //if (t->joliet) - // joliet_update_file_pos (t, t->joliet_root); if (t->rockridge) { susp_finalize(t, t->root); @@ -772,13 +769,14 @@ bs_free_data(struct burn_source *bs) ecma119_tree_free(t->root); iso_file_table_clear(t->file_table); - //FIXME free joliet tree free(t->dirlist); free(t->pathlist); free(t->dirlist_joliet); free(t->pathlist_joliet); free(t->filelist); free(t->state_data); + if (t->joliet) + joliet_tree_free(t->joliet_root); if (t->state_files.fd) fclose(t->state_files.fd); } diff --git a/libisofs/file.c b/libisofs/file.c index 4074f73..b7660c9 100644 --- a/libisofs/file.c +++ b/libisofs/file.c @@ -185,380 +185,3 @@ iso_file_table_lookup(struct iso_file_table *ft, struct iso_tree_node_file *f) return NULL; } - -#include -#include -#include -#include -#include -#include - -#include "file.h" -#include "tree.h" - -//TODO: refactor both hash and this hash table into a single one!! - -struct iso_file * -iso_file_new(struct iso_tree_node_file *f) -{ - struct iso_file *file = calloc(1, sizeof(struct iso_file)); - file->path = f->path; /*TODO strdup? it needs to be free on clear then */ - file->size = f->node.attrib.st_size; - file->nlink = 1; - file->real_dev = f->node.attrib.st_dev; - file->real_ino = f->node.attrib.st_ino; - file->sort_weight = f->sort_weight; - return file; -} - -static unsigned int -iso_file_table_hash(const char *path) -{ - unsigned int hash_num=0; - const char *c; - - c=path; - while(*c) - hash_num = (hash_num << 15) + (hash_num << 3) + (hash_num >> 3) + *c++; - - return hash_num % FILE_HASH_NODES; -} - -static inline unsigned int -iso_file_table_hash_inode(dev_t dev, ino_t ino) -{ - return (dev ^ ino) % FILE_HASH_NODES; -} - -struct iso_file_table* -iso_file_table_new(int cache_inodes) -{ - struct iso_file_table *table = calloc(1, sizeof(struct iso_file_table)); - table->cache_inodes = cache_inodes; - return table; -} - -static struct iso_file_hash_node * -iso_file_table_node_new(struct iso_file *file) -{ - struct iso_file_hash_node *node; - node = calloc(1, sizeof(struct iso_file_hash_node) ); - node->file = file; - return node; -} - -static void -iso_file_table_node_free(struct iso_file_hash_node *node) -{ - free(node->file); - free(node); -} - -void -iso_file_table_clear(struct iso_file_table *ft) -{ - int i; - - for (i=0; i < FILE_HASH_NODES; i++) { - struct iso_file_hash_node *node; - - node=ft->table[i]; - if (!node) - continue; - - ft->table[i] = NULL; - - do { - struct iso_file_hash_node *next; - - next = node->next; - iso_file_table_node_free(node); - node = next; - } while (node); - } -} - -/** - * return 0 if equal, != 0 if not - */ -static int -iso_table_compare_files(struct iso_file_table *ft, - struct iso_file *f1, struct iso_file *f2) -{ - if (ft->cache_inodes) { - return (f1->real_dev != f2->real_dev) || (f1->real_ino != f2->real_ino); - } else { - return strcmp(f1->path, f2->path); - } -} - -int -iso_file_table_add_file(struct iso_file_table *ft, struct iso_file *f) -{ - struct iso_file_hash_node *node; - unsigned int hash_num; - - /* find the hash number */ - if (ft->cache_inodes) - hash_num = iso_file_table_hash_inode(f->real_dev, f->real_ino); - else - hash_num = iso_file_table_hash(f->path); - - /* insert it */ - node = ft->table[hash_num]; - - /* unfortunately, we can't safely consider that a file - * won't be twice in the hash table so make sure it - * doesn't already exists */ - if (!node) { - ft->table[hash_num]=iso_file_table_node_new(f); - ft->count++; - return 1; - } - - /* if it's already in, we don't do anything */ - if (!iso_table_compare_files(ft, f, node->file)) - return 0; - - while (node->next) { - node = node->next; - - /* if it's already in, we don't do anything */ - if (!iso_table_compare_files(ft, f, node->file)) - return 0; - } - - node->next = iso_file_table_node_new(f); - ft->count++; - return 1; -} - -struct iso_file * -iso_file_table_lookup(struct iso_file_table *ft, struct iso_tree_node_file *f) -{ - struct iso_file_hash_node *node; - unsigned int hash_num; - int equal; - - /* find the hash number */ - if ( ft->cache_inodes ) - hash_num = iso_file_table_hash_inode(f->node.attrib.st_dev, - f->node.attrib.st_ino); - else - hash_num = iso_file_table_hash(f->path); - - node = ft->table[hash_num]; - - if (!node) - return NULL; - - equal = ft->cache_inodes ? - ((f->node.attrib.st_dev == node->file->real_dev) - && (f->node.attrib.st_ino == node->file->real_ino)) - : !strcmp(f->path, node->file->path); - if (equal) - return node->file; - - while (node->next) { - node = node->next; - - equal = ft->cache_inodes ? - ((f->node.attrib.st_dev == node->file->real_dev) - && (f->node.attrib.st_ino == node->file->real_ino)) - : !strcmp(f->path, node->file->path); - if (equal) - return node->file; - } - - return NULL; -} - - -#include -#include -#include -#include -#include -#include - -#include "file.h" -#include "tree.h" - -//TODO: refactor both hash and this hash table into a single one!! - -struct iso_file * -iso_file_new(struct iso_tree_node_file *f) -{ - struct iso_file *file = calloc(1, sizeof(struct iso_file)); - file->path = f->path; /*TODO strdup? it needs to be free on clear then */ - file->size = f->node.attrib.st_size; - file->nlink = 1; - file->real_dev = f->node.attrib.st_dev; - file->real_ino = f->node.attrib.st_ino; - file->sort_weight = f->sort_weight; - return file; -} - -static unsigned int -iso_file_table_hash(const char *path) -{ - unsigned int hash_num=0; - const char *c; - - c=path; - while(*c) - hash_num = (hash_num << 15) + (hash_num << 3) + (hash_num >> 3) + *c++; - - return hash_num % FILE_HASH_NODES; -} - -static inline unsigned int -iso_file_table_hash_inode(dev_t dev, ino_t ino) -{ - return (dev ^ ino) % FILE_HASH_NODES; -} - -struct iso_file_table* -iso_file_table_new(int cache_inodes) -{ - struct iso_file_table *table = calloc(1, sizeof(struct iso_file_table)); - table->cache_inodes = cache_inodes; - return table; -} - -static struct iso_file_hash_node * -iso_file_table_node_new(struct iso_file *file) -{ - struct iso_file_hash_node *node; - node = calloc(1, sizeof(struct iso_file_hash_node) ); - node->file = file; - return node; -} - -static void -iso_file_table_node_free(struct iso_file_hash_node *node) -{ - free(node->file); - free(node); -} - -void -iso_file_table_clear(struct iso_file_table *ft) -{ - int i; - - for (i=0; i < FILE_HASH_NODES; i++) { - struct iso_file_hash_node *node; - - node=ft->table[i]; - if (!node) - continue; - - ft->table[i] = NULL; - - do { - struct iso_file_hash_node *next; - - next = node->next; - iso_file_table_node_free(node); - node = next; - } while (node); - } -} - -/** - * return 0 if equal, != 0 if not - */ -static int -iso_table_compare_files(struct iso_file_table *ft, - struct iso_file *f1, struct iso_file *f2) -{ - if (ft->cache_inodes) { - return (f1->real_dev != f2->real_dev) || (f1->real_ino != f2->real_ino); - } else { - return strcmp(f1->path, f2->path); - } -} - -int -iso_file_table_add_file(struct iso_file_table *ft, struct iso_file *f) -{ - struct iso_file_hash_node *node; - unsigned int hash_num; - - /* find the hash number */ - if (ft->cache_inodes) - hash_num = iso_file_table_hash_inode(f->real_dev, f->real_ino); - else - hash_num = iso_file_table_hash(f->path); - - /* insert it */ - node = ft->table[hash_num]; - - /* unfortunately, we can't safely consider that a file - * won't be twice in the hash table so make sure it - * doesn't already exists */ - if (!node) { - ft->table[hash_num]=iso_file_table_node_new(f); - ft->count++; - return 1; - } - - /* if it's already in, we don't do anything */ - if (!iso_table_compare_files(ft, f, node->file)) - return 0; - - while (node->next) { - node = node->next; - - /* if it's already in, we don't do anything */ - if (!iso_table_compare_files(ft, f, node->file)) - return 0; - } - - node->next = iso_file_table_node_new(f); - ft->count++; - return 1; -} - -struct iso_file * -iso_file_table_lookup(struct iso_file_table *ft, struct iso_tree_node_file *f) -{ - struct iso_file_hash_node *node; - unsigned int hash_num; - int equal; - - /* find the hash number */ - if ( ft->cache_inodes ) - hash_num = iso_file_table_hash_inode(f->node.attrib.st_dev, - f->node.attrib.st_ino); - else - hash_num = iso_file_table_hash(f->path); - - node = ft->table[hash_num]; - - if (!node) - return NULL; - - equal = ft->cache_inodes ? - ((f->node.attrib.st_dev == node->file->real_dev) - && (f->node.attrib.st_ino == node->file->real_ino)) - : !strcmp(f->path, node->file->path); - if (equal) - return node->file; - - while (node->next) { - node = node->next; - - equal = ft->cache_inodes ? - ((f->node.attrib.st_dev == node->file->real_dev) - && (f->node.attrib.st_ino == node->file->real_ino)) - : !strcmp(f->path, node->file->path); - if (equal) - return node->file; - } - - return NULL; -} - - diff --git a/libisofs/file.h b/libisofs/file.h index 1d84f9a..9c2745b 100644 --- a/libisofs/file.h +++ b/libisofs/file.h @@ -53,113 +53,3 @@ struct iso_file *iso_file_table_lookup(struct iso_file_table *ft, struct iso_tree_node_file *f); #endif /*FILE_H_*/ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ -/* vim: set noet ts=8 sts=8 sw=8 : */ - -/** - * \file file.h - * - * Declare the structs to keep track of the files to be written into image. - * - */ - -#ifndef FILE_H_ -#define FILE_H_ - -#define FILE_HASH_NODES 2048 - -struct iso_file { - char *path; - off_t size; /**< size of this file */ - ino_t ino; /**< This will be the inode number on CD of the file (RR) */ - nlink_t nlink; /**< Number of hard links of the file on CD (RR) */ - size_t block; /**< Block where this file is to be written on image */ - dev_t real_dev; - ino_t real_ino; /**< for lookup by inode caching */ - int sort_weight; -}; - -struct iso_file_hash_node { - struct iso_file_hash_node *next; - struct iso_file *file; -}; - -struct iso_file_table { - struct iso_file_hash_node *table[FILE_HASH_NODES]; - size_t count; - int cache_inodes; /**< 1 to index by inode number */ -}; - -struct iso_tree_node_file; - -struct iso_file *iso_file_new(struct iso_tree_node_file*); - -struct iso_file_table *iso_file_table_new(int cache_inodes); - -/** - * Clear a hash table. All iso_file structs stored will also be freed, - * but not the path of each iso_file - */ -void iso_file_table_clear(struct iso_file_table *ft); - -int iso_file_table_add_file(struct iso_file_table *ft, struct iso_file *f); - -struct iso_file *iso_file_table_lookup(struct iso_file_table *ft, - struct iso_tree_node_file *f); - -#endif /*FILE_H_*/ -/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ -/* vim: set noet ts=8 sts=8 sw=8 : */ - -/** - * \file file.h - * - * Declare the structs to keep track of the files to be written into image. - * - */ - -#ifndef FILE_H_ -#define FILE_H_ - -#define FILE_HASH_NODES 2048 - -struct iso_file { - char *path; - off_t size; /**< size of this file */ - ino_t ino; /**< This will be the inode number on CD of the file (RR) */ - nlink_t nlink; /**< Number of hard links of the file on CD (RR) */ - size_t block; /**< Block where this file is to be written on image */ - dev_t real_dev; - ino_t real_ino; /**< for lookup by inode caching */ - int sort_weight; -}; - -struct iso_file_hash_node { - struct iso_file_hash_node *next; - struct iso_file *file; -}; - -struct iso_file_table { - struct iso_file_hash_node *table[FILE_HASH_NODES]; - size_t count; - int cache_inodes; /**< 1 to index by inode number */ -}; - -struct iso_tree_node_file; - -struct iso_file *iso_file_new(struct iso_tree_node_file*); - -struct iso_file_table *iso_file_table_new(int cache_inodes); - -/** - * Clear a hash table. All iso_file structs stored will also be freed, - * but not the path of each iso_file - */ -void iso_file_table_clear(struct iso_file_table *ft); - -int iso_file_table_add_file(struct iso_file_table *ft, struct iso_file *f); - -struct iso_file *iso_file_table_lookup(struct iso_file_table *ft, - struct iso_tree_node_file *f); - -#endif /*FILE_H_*/ diff --git a/libisofs/joliet.c b/libisofs/joliet.c index 5447a48..10b4347 100644 --- a/libisofs/joliet.c +++ b/libisofs/joliet.c @@ -191,6 +191,21 @@ joliet_tree_create(struct ecma119_write_target *t, return root; } +void +joliet_tree_free(struct joliet_tree_node *root) +{ + size_t i; + + if (root->type == JOLIET_DIR) { + for (i=0; i < root->info.dir.nchildren; i++) { + joliet_tree_free(root->info.dir.children[i]); + } + free(root->info.dir.children); + } + free(root->name); + free(root); +} + /* ugh. this is mostly C&P */ static void write_path_table(struct ecma119_write_target *t, diff --git a/libisofs/joliet.h b/libisofs/joliet.h index cce7c89..a54866e 100644 --- a/libisofs/joliet.h +++ b/libisofs/joliet.h @@ -33,11 +33,8 @@ struct joliet_tree_node { uint16_t *name; /**< In UCS-2BE. */ size_t dirent_len; - //size_t len;?? - /*size_t block;*/ struct joliet_tree_node *parent; - /* struct iso_tree_node *iso_self; */ struct ecma119_write_target *target; int type; @@ -67,14 +64,6 @@ joliet_calc_dir_size(struct ecma119_write_target *t, struct joliet_tree_node*); void 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 - * AFTER the file positions in the iso tree have been set). - * TODO not needed, block info is kept away in hash table - */ -//void -//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 * directories. diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 537b01a..8d62366 100755 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -12,6 +12,8 @@ #ifndef LIBISO_LIBISOFS_H #define LIBISO_LIBISOFS_H +#include + /* #include */ struct burn_source; @@ -45,6 +47,11 @@ enum ecma119_extension_flag { ECMA119_JOLIET = (1<<1) }; +enum hide_node_flag { + LIBISO_HIDE_ON_RR = 1 << 0, + LIBISO_HIDE_ON_JOLIET = 1 << 1 +}; + /** * This will hold the error code for some functions, if them fail. */ @@ -282,23 +289,6 @@ struct iso_tree_node *iso_tree_add_node(struct iso_tree_node_dir *parent, struct iso_tree_node_dir *iso_tree_radd_dir(struct iso_tree_node_dir *parent, 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); - -/** - * Creates a new, empty directory on the volume. - * - * \pre \p parent is NULL or is a directory. - * \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 *iso_tree_add_new_dir(struct iso_tree_node *parent, - const char *name);*/ - /** * Set the name of a tree node (using the current locale). */ @@ -306,9 +296,56 @@ 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. + * + * If the file is setted as hidden in one tree, it won't be included there, so + * it won't be visible in a OS accessing CD using that tree. For example, + * GNU/Linux systems access to Rock Ridge / ISO9960 tree in order to see + * what is recorded on CD, while MS Windows make use of the Joliet tree. If a + * file is hidden only in Joliet, it won't be visible in Windows systems, + * while still visible in Linux. + * + * If a file is hidden in both trees, it won't be written to image. + * + * \param node The node that is to be hidden. + * \param hide_attrs hide_node_flag's to set the trees in which file + * will be hidden. */ void iso_tree_node_set_hidden(struct iso_tree_node *node, int hide_attrs); +/** + * Set the group id for the node. This attribute is only useful when + * Rock Ridge extensions are enabled. + */ +void iso_tree_node_set_gid(struct iso_tree_node *node, gid_t gid); + +/** + * Set the user id for the node. This attribute is only useful when + * Rock Ridge extensions are enabled. + */ +void iso_tree_node_set_uid(struct iso_tree_node *node, uid_t uid); + +/** + * Set the permissions for the node. This attribute is only useful when + * Rock Ridge extensions are enabled. + * + * \param mode bitmask with the permissions of the node, as specified + * in 'man 2 stat'. The file type bitfields will be ignored, + * only file permissions will be modified. + */ +void iso_tree_node_set_permissions(struct iso_tree_node *node, mode_t mode); + +/** + * Sets the order in which a node will be written on image. High weihted files + * will be written first, so in a disc them will be written near the center. + * + * \param node The node which weight will be changed. If it's a dir, this + * function will change the weight of all its children. For nodes + * other that dirs or regular files, this function has no effect. + * \param w The weight as a integer number, the greater this value is, the + * closer from the begining of image the file will be written. + */ +void iso_tree_node_set_sort_weight(struct iso_tree_node *node, int w); + /** * Recursively print a directory to stdout. * \param spaces The initial number of spaces on the left. Set to 0 if you diff --git a/libisofs/tree.c b/libisofs/tree.c index 7880845..dfab662 100755 --- a/libisofs/tree.c +++ b/libisofs/tree.c @@ -146,9 +146,51 @@ iso_tree_node_set_name(struct iso_tree_node *node, const char *name) void iso_tree_node_set_hidden(struct iso_tree_node *node, int hide_attrs) { + assert(node); node->hide_flags = hide_attrs; } +void +iso_tree_node_set_gid(struct iso_tree_node *node, gid_t gid) +{ + assert(node); + node->attrib.st_gid = gid; +} + +void +iso_tree_node_set_uid(struct iso_tree_node *node, uid_t uid) +{ + assert(node); + node->attrib.st_uid = uid; +} + +void +iso_tree_node_set_permissions(struct iso_tree_node *node, mode_t mode) +{ + assert(node); + node->attrib.st_mode = (node->attrib.st_mode & S_IFMT) | + (mode & ~S_IFMT); +} + +void +iso_tree_node_set_sort_weight(struct iso_tree_node *node, int w) +{ + assert(node); + if ( ISO_ISDIR(node) ) { + size_t i; + struct iso_tree_node_dir *dir; + dir = (struct iso_tree_node_dir *) node; + for (i=0; i < dir->nchildren; i++) { + iso_tree_node_set_sort_weight(dir->children[i], w); + } + free(dir->children); + } else if ( ISO_ISREG(node) ) { + struct iso_tree_node_file *file; + file = (struct iso_tree_node_file *) node; + file->sort_weight = w; + } +} + struct iso_tree_node* iso_tree_add_node(struct iso_tree_node_dir *parent, const char *path) @@ -261,7 +303,7 @@ iso_tree_radd_dir_aux(struct iso_tree_node_dir *parent, const char *path, strcmp(ent->d_name, "..") == 0) continue; - //check if path already finished in '/' + //TODO check if path already finished in '/' sprintf(child, "%s/%s", path, ent->d_name); /* see if this child is excluded. */ diff --git a/libisofs/tree.h b/libisofs/tree.h index ec8c0d2..a40a220 100755 --- a/libisofs/tree.h +++ b/libisofs/tree.h @@ -31,11 +31,6 @@ // * 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 * local filesystem or we just point to the block on a previous session. @@ -54,7 +49,6 @@ enum hide_node { */ struct iso_tree_node { - /*struct iso_volume *volume; TODO not needed? */ struct iso_tree_node_dir *parent; char *name; struct stat attrib; /**< The POSIX attributes of this node as @@ -62,13 +56,6 @@ struct iso_tree_node int hide_flags; /**< If the node is to be hidden in RR/ISO or * Joilet tree */ - - /*size_t block;*/ /**< The block at which this file will - * reside on disk. We store this here as - * well as in the various mangled trees - * because many different trees might point - * to the same file and they need to share the - * block location. */ }; /**