diff --git a/src/fsource.h b/src/fsource.h index a17646d..a8973a7 100644 --- a/src/fsource.h +++ b/src/fsource.h @@ -33,10 +33,11 @@ struct Iso_Filesystem */ int (*get_root)(IsoFilesystem *fs, IsoFileSource **root); - /** - * - * - */ + /** + * + * @return + * 1 success, < 0 error + */ int (*get_by_path)(IsoFilesystem *fs, const char *path, IsoFileSource **file); @@ -208,8 +209,7 @@ struct Iso_File_Source * TODO #00004 Add a get_mime_type() function. * This can be useful for GUI apps, to choose the icon of the file */ - - //TODO define the refcount behavior for FileSources. + int refcount; void *data; }; diff --git a/src/image.c b/src/image.c index 7420492..5d8a0be 100644 --- a/src/image.c +++ b/src/image.c @@ -41,9 +41,26 @@ int iso_image_new(const char *name, IsoImage **image) return ISO_MEM_ERROR; } + /* local filesystem will be used by default */ + res = iso_local_filesystem_new(&(img->fs)); + if (res < 0) { + free(img); + return ISO_MEM_ERROR; + } + + /* use basic builder as default */ + res = iso_node_basic_builder_new(&(img->builder)); + if (res < 0) { + iso_filesystem_unref(img->fs); + free(img); + return ISO_MEM_ERROR; + } + /* create message messenger */ res = libiso_msgs_new(&img->messenger, 0); if (res <= 0) { + iso_node_builder_unref(img->builder); + iso_filesystem_unref(img->fs); free(img); return ISO_MEM_ERROR; } @@ -54,6 +71,8 @@ int iso_image_new(const char *name, IsoImage **image) res = iso_node_new_root(&img->root); if (res < 0) { libiso_msgs_destroy(&img->messenger, 0); + iso_node_builder_unref(img->builder); + iso_filesystem_unref(img->fs); free(img); return res; } @@ -85,6 +104,8 @@ void iso_image_unref(IsoImage *image) /* we need to free the image */ iso_node_unref((IsoNode*)image->root); libiso_msgs_destroy(&image->messenger, 0); + iso_node_builder_unref(image->builder); + iso_filesystem_unref(image->fs); free(image->volset_id); free(image->volume_id); free(image->publisher_id); diff --git a/src/image.h b/src/image.h index 126ced7..6f9e03b 100644 --- a/src/image.h +++ b/src/image.h @@ -10,7 +10,9 @@ #include "libisofs.h" #include "node.h" - +#include "fsource.h" +#include "builder.h" + /* * Image is a context for image manipulation. * Global objects such as the message_queues must belogn to that @@ -39,6 +41,16 @@ struct Iso_Image { /* message messenger for the image */ struct libiso_msgs *messenger; + + /** + * Default filesystem to use when adding files to the image tree. + */ + IsoFilesystem *fs; + + /* + * Default builder to use when adding files to the image tree. + */ + IsoNodeBuilder *builder; }; #endif /*LIBISO_IMAGE_H_*/ diff --git a/src/libisofs.h b/src/libisofs.h index e0ba2d0..6b49f3b 100644 --- a/src/libisofs.h +++ b/src/libisofs.h @@ -573,6 +573,35 @@ int iso_tree_add_new_symlink(IsoDir *parent, const char *name, int iso_tree_add_new_special(IsoDir *parent, const char *name, mode_t mode, dev_t dev, IsoSpecial **special); +/** + * Add a new node to the image tree, from an existing file. + * + * TODO comment Builder and Filesystem related issues when exposing both + * + * All attributes will be taken from the source file. The appropriate file + * type will be created. + * + * @param image + * The image + * @param parent + * The directory in the image tree where the node will be added. + * @param path + * The path of the file to add in the filesystem. + * @param node + * place where to store a pointer to the newly added file. No + * extra ref is addded, so you will need to call iso_node_ref() if you + * really need it. You can pass NULL in this parameter if you don't need + * the pointer. + * @return + * number of nodes in parent if success, < 0 otherwise + * Possible errors: + * ISO_NULL_POINTER, if image, parent or path are NULL + * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists + * ISO_MEM_ERROR + */ +int iso_tree_add_node(IsoImage *image, IsoDir *parent, const char *path, + IsoNode **node); + #define ISO_MSGS_MESSAGE_LEN 4096 /** diff --git a/src/tree.c b/src/tree.c index 9a0679d..12935d7 100644 --- a/src/tree.c +++ b/src/tree.c @@ -13,10 +13,14 @@ #include "libisofs.h" #include "node.h" #include "error.h" +#include "image.h" +#include "fsource.h" +#include "builder.h" #include #include #include +#include /** * Add a new directory to the iso tree. @@ -289,3 +293,151 @@ int iso_tree_add_new_special(IsoDir *parent, const char *name, mode_t mode, } return ++parent->nchildren; } + +static +int iso_tree_add_node_builder(IsoDir *parent, IsoFileSource *src, + IsoNodeBuilder *builder, IsoNode **node) +{ + int result; + struct stat info; + IsoNode *new; + IsoNode **pos; + char *name; + + if (parent == NULL || src == NULL || builder == NULL) { + return ISO_NULL_POINTER; + } + if (node) { + *node = NULL; + } + + name = src->get_name(src); + + /* find place where to insert */ + pos = &(parent->children); + while (*pos != NULL && strcmp((*pos)->name, name) < 0) { + pos = &((*pos)->next); + } + if (*pos != NULL && !strcmp((*pos)->name, name)) { + /* a node with same name already exists */ + return ISO_NODE_NAME_NOT_UNIQUE; + } + + /* get info about source */ + result = src->lstat(src, &info); + if (result < 0) { + return result; + } + + new = NULL; + switch (info.st_mode & S_IFMT) { + case S_IFREG: + { + /* source is a regular file */ + IsoStream *stream; + IsoFile *file; + result = iso_file_source_stream_new(src, &stream); + if (result < 0) { + return result; + } + file = malloc(sizeof(IsoFile)); + if (file == NULL) { + iso_stream_unref(stream); + return ISO_MEM_ERROR; + } + file->msblock = 0; + file->sort_weight = 0; + file->stream = stream; + file->node.type = LIBISO_FILE; + new = (IsoNode*) file; + } + break; + case S_IFDIR: + { + /* source is a directory */ + new = calloc(1, sizeof(IsoDir)); + if (new == NULL) { + return ISO_MEM_ERROR; + } + new->type = LIBISO_DIR; + } + break; + case S_IFLNK: + { + /* source is a symbolic link */ + char dest[PATH_MAX]; + IsoSymlink *link; + + result = src->readlink(src, dest, PATH_MAX); + if (result < 0) { + return result; + } + link = malloc(sizeof(IsoSymlink)); + if (link == NULL) { + return ISO_MEM_ERROR; + } + link->dest = strdup(dest); + link->node.type = LIBISO_SYMLINK; + new = (IsoNode*) link; + } + break; + case S_IFSOCK: + case S_IFBLK: + case S_IFCHR: + case S_IFIFO: + { + /* source is an special file */ + IsoSpecial *special; + special = malloc(sizeof(IsoSpecial)); + if (special == NULL) { + return ISO_MEM_ERROR; + } + special->dev = info.st_rdev; + special->node.type = LIBISO_SPECIAL; + new = (IsoNode*) special; + } + break; + } + + /* fill fields */ + new->refcount = 1; + new->name = strdup(name); + new->mode = info.st_mode; + new->uid = info.st_uid; + new->gid = info.st_gid; + new->atime = info.st_atime; + new->mtime = info.st_mtime; + new->ctime = info.st_ctime; + + new->hidden = 0; + + /* finally, add node to parent */ + new->parent = parent; + new->next = *pos; + *pos = new; + + if (node) { + *node = new; + } + return ++parent->nchildren; +} + +int iso_tree_add_node(IsoImage *image, IsoDir *parent, const char *path, + IsoNode **node) +{ + int result; + IsoFilesystem *fs; + IsoFileSource *file; + + if (image == NULL || parent == NULL || path == NULL) { + return ISO_NULL_POINTER; + } + + fs = image->fs; + result = fs->get_by_path(fs, path, &file); + if (result < 0) { + return result; + } + result = iso_tree_add_node_builder(parent, file, image->builder, node); + return result; +}