From 2f535abe855c3d3a1edd236839e589e5c056b77a Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Thu, 3 Jan 2008 17:16:27 +0100 Subject: [PATCH 1/4] Fix bug related with reading of images with reallocated dirs. --- src/fs_image.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fs_image.c b/src/fs_image.c index 73683e6..3352ca8 100644 --- a/src/fs_image.c +++ b/src/fs_image.c @@ -331,7 +331,7 @@ int read_dir(ImageFileSourceData *data) } /* add to the child list */ - { + if (ret != 0) { struct child_list *node; node = malloc(sizeof(struct child_list)); if (node == NULL) { @@ -365,7 +365,7 @@ int ifs_open(IsoFileSource *src) return ISO_NULL_POINTER; } data = (ImageFileSourceData*)src->data; - + if (data->opened) { return ISO_FILE_ALREADY_OPENNED; } @@ -558,7 +558,7 @@ int ifs_readdir(IsoFileSource *src, IsoFileSource **child) /* free the first element of the list */ data->data.content = children->next; free(children); - + return ISO_SUCCESS; } @@ -925,7 +925,7 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent, ret = iso_file_source_new_ifs(fs, parent, (struct ecma119_dir_record*) buffer, src); - if (ret < 0) { + if (ret <= 0) { return ret; } From 58a7d8e8534137f3bd94ea4baa479438baa73620 Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Thu, 3 Jan 2008 19:17:55 +0100 Subject: [PATCH 2/4] First functions and structures for image import. --- demo/iso_cat.c | 10 +++--- demo/iso_read.c | 12 +++---- src/fs_image.c | 50 +++++++++++++++++++++++++++- src/fs_image.h | 61 ++-------------------------------- src/libisofs.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+), 71 deletions(-) diff --git a/demo/iso_cat.c b/demo/iso_cat.c index bec54e2..cfe7bc8 100644 --- a/demo/iso_cat.c +++ b/demo/iso_cat.c @@ -27,6 +27,7 @@ int main(int argc, char **argv) IsoFileSource *file; struct stat info; IsoDataSource *src; + struct libiso_msgs *messenger; struct iso_read_opts opts = { 0, /* block */ 0, /* norock */ @@ -35,7 +36,6 @@ int main(int argc, char **argv) 0, /* uid; */ 0, /* gid; */ 0, /* mode */ - NULL, /* messenger */ "UTF-8" /* input_charset */ }; @@ -44,12 +44,12 @@ int main(int argc, char **argv) return 1; } - res = libiso_msgs_new(&opts.messenger, 0); + res = libiso_msgs_new(&messenger, 0); if (res <= 0) { printf ("Can't create messenger\n"); return 1; } - libiso_msgs_set_severities(opts.messenger, LIBISO_MSGS_SEV_NEVER, + libiso_msgs_set_severities(messenger, LIBISO_MSGS_SEV_NEVER, LIBISO_MSGS_SEV_ALL, "", 0); res = iso_data_source_new_from_file(argv[1], &src); @@ -58,7 +58,7 @@ int main(int argc, char **argv) return 1; } - res = iso_image_filesystem_new(src, &opts, &fs); + res = iso_image_filesystem_new(src, &opts, messenger, &fs); if (res < 0) { printf ("Error creating filesystem\n"); return 1; @@ -99,6 +99,6 @@ int main(int argc, char **argv) iso_file_source_unref(file); iso_filesystem_unref(fs); iso_data_source_unref(src); - libiso_msgs_destroy(&opts.messenger, 0); + libiso_msgs_destroy(&messenger, 0); return 0; } diff --git a/demo/iso_read.c b/demo/iso_read.c index 3ba3781..a4213ae 100644 --- a/demo/iso_read.c +++ b/demo/iso_read.c @@ -111,6 +111,7 @@ int main(int argc, char **argv) IsoImageFilesystem *fs; IsoDataSource *src; IsoFileSource *root; + struct libiso_msgs *messenger; struct iso_read_opts opts = { 0, /* block */ 0, /* norock */ @@ -119,7 +120,6 @@ int main(int argc, char **argv) 0, /* uid; */ 0, /* gid; */ 0, /* mode */ - NULL, /* messenger */ "UTF-8" /* input_charset */ }; @@ -128,12 +128,12 @@ int main(int argc, char **argv) return 1; } - result = libiso_msgs_new(&opts.messenger, 0); + result = libiso_msgs_new(&messenger, 0); if (result <= 0) { printf ("Can't create messenger\n"); return 1; } - libiso_msgs_set_severities(opts.messenger, LIBISO_MSGS_SEV_NEVER, + libiso_msgs_set_severities(messenger, LIBISO_MSGS_SEV_NEVER, LIBISO_MSGS_SEV_ALL, "", 0); result = iso_data_source_new_from_file(argv[1], &src); @@ -142,7 +142,7 @@ int main(int argc, char **argv) return 1; } - result = iso_image_filesystem_new(src, &opts, &fs); + result = iso_image_filesystem_new(src, &opts, messenger, &fs); if (result < 0) { printf ("Error creating filesystem\n"); return 1; @@ -160,6 +160,6 @@ int main(int argc, char **argv) fs->close(fs); iso_filesystem_unref((IsoFilesystem*)fs); iso_data_source_unref(src); - libiso_msgs_destroy(&opts.messenger, 0); - return 0; + libiso_msgs_destroy(&messenger, 0); + return 0; } diff --git a/src/fs_image.c b/src/fs_image.c index 3352ca8..c5121d5 100644 --- a/src/fs_image.c +++ b/src/fs_image.c @@ -16,6 +16,7 @@ #include "ecma119.h" #include "messages.h" #include "rockridge.h" +#include "image.h" #include #include @@ -1424,6 +1425,7 @@ int read_pvm(_ImageFsData *data, uint32_t block) } int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts, + struct libiso_msgs *messenger, IsoImageFilesystem **fs) { int ret; @@ -1460,7 +1462,7 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts, data->uid = opts->uid; data->mode = opts->mode & ~S_IFMT; data->input_charset = strdup(opts->input_charset); - data->messenger = opts->messenger; + data->messenger = messenger; ifs->open = ifs_fs_open; ifs->close = ifs_fs_close; @@ -1582,3 +1584,49 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts, free(ifs); return ret; } + +int iso_image_import(IsoImage *image, IsoDataSource *src, + struct iso_read_opts *opts, + struct iso_read_image_features *features) +{ + int ret; + IsoImageFilesystem *fs; + IsoFilesystem *fsback; + + if (image == NULL || src == NULL || opts == NULL) { + return ISO_NULL_POINTER; + } + + ret = iso_image_filesystem_new(src, opts, image->messenger, &fs); + if (ret < 0) { + return ret; + } + + /* backup image filesystem and builder */ + fsback = image->fs; + //TODO + + + /* get root from filesystem */ + + + /* remove root node */ + + + /* recursively add image */ + + + /* recover backed fs and builder */ + + + /* set volume attributes */ + + + if (features != NULL) { + //TODO + } + + //TODO + + return -1; +} diff --git a/src/fs_image.h b/src/fs_image.h index 9c7d8ae..cb5a49b 100644 --- a/src/fs_image.h +++ b/src/fs_image.h @@ -12,65 +12,7 @@ #include "libisofs.h" #include "fsource.h" -/** - * Options for image reading. - * There are four kind of options: - * - Related to multisession support. - * In most cases, an image begins at LBA 0 of the data source. However, - * in multisession discs, the later image begins in the last session on - * disc. The block option can be used to specify the start of that last - * session. - * - Related to the tree that will be read. - * As default, when Rock Ridge extensions are present in the image, that - * will be used to get the tree. If RR extensions are not present, libisofs - * will use the Joliet extensions if available. Finally, the plain ISO-9660 - * tree is used if neither RR nor Joliet extensions are available. With - * norock, nojoliet, and preferjoliet options, you can change this - * default behavior. - * - Related to default POSIX attributes. - * When Rock Ridege extensions are not used, libisofs can't figure out what - * are the the permissions, uid or gid for the files. You should supply - * default values for that. - * - Return information for image. - * Both size, hasRR and hasJoliet will be filled by libisofs with suitable values. - * Also, error is set to non-0 if some error happens (error codes are - * private now) - */ -struct iso_read_opts -{ - uint32_t block; /** Block where the image begins, usually 0, can be - * different on a multisession disc. - */ - - unsigned int norock : 1; /*< Do not read Rock Ridge extensions */ - unsigned int nojoliet : 1; /*< Do not read Joliet extensions */ - - /** - * When both Joliet and RR extensions are present, the RR tree is used. - * If you prefer using Joliet, set this to 1. - */ - unsigned int preferjoliet : 1; - - uid_t uid; /**< Default uid when no RR */ - gid_t gid; /**< Default uid when no RR */ - mode_t mode; /**< Default mode when no RR (only permissions) */ - //TODO differ file and dir mode - //option to convert names to lower case? - - struct libiso_msgs *messenger; - - char *input_charset; - -/* modified by the function */ -// unsigned int hasRR:1; /*< It will be set to 1 if RR extensions are present, -// to 0 if not. */ -// unsigned int hasJoliet:1; /*< It will be set to 1 if Joliet extensions are -// present, to 0 if not. */ -// uint32_t size; /**< Will be filled with the size (in 2048 byte block) of -// * the image, as reported in the PVM. */ -//int error; -}; - +struct libiso_msgs; typedef struct Iso_Image_Filesystem IsoImageFilesystem; /** @@ -102,6 +44,7 @@ struct Iso_Image_Filesystem }; int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts, + struct libiso_msgs *messenger, IsoImageFilesystem **fs); #endif /*LIBISO_FS_IMAGE_H_*/ diff --git a/src/libisofs.h b/src/libisofs.h index f3b2ec1..995f96f 100644 --- a/src/libisofs.h +++ b/src/libisofs.h @@ -202,6 +202,72 @@ struct Iso_Data_Source { void *data; }; +/** + * Options for image reading. + * There are four kind of options: + * - Related to multisession support. + * In most cases, an image begins at LBA 0 of the data source. However, + * in multisession discs, the later image begins in the last session on + * disc. The block option can be used to specify the start of that last + * session. + * - Related to the tree that will be read. + * As default, when Rock Ridge extensions are present in the image, that + * will be used to get the tree. If RR extensions are not present, libisofs + * will use the Joliet extensions if available. Finally, the plain ISO-9660 + * tree is used if neither RR nor Joliet extensions are available. With + * norock, nojoliet, and preferjoliet options, you can change this + * default behavior. + * - Related to default POSIX attributes. + * When Rock Ridege extensions are not used, libisofs can't figure out what + * are the the permissions, uid or gid for the files. You should supply + * default values for that. + */ +struct iso_read_opts +{ + /** + * Block where the image begins, usually 0, can be different on a + * multisession disc. + */ + uint32_t block; + + unsigned int norock : 1; /*< Do not read Rock Ridge extensions */ + unsigned int nojoliet : 1; /*< Do not read Joliet extensions */ + + /** + * When both Joliet and RR extensions are present, the RR tree is used. + * If you prefer using Joliet, set this to 1. + */ + unsigned int preferjoliet : 1; + + uid_t uid; /**< Default uid when no RR */ + gid_t gid; /**< Default uid when no RR */ + mode_t mode; /**< Default mode when no RR (only permissions) */ + //TODO differ file and dir mode + //option to convert names to lower case? + + char *input_charset; +}; + +/** + * Return information for image. + * Both size, hasRR and hasJoliet will be filled by libisofs with suitable + * values. + */ +struct iso_read_image_features +{ + /** It will be set to 1 if RR extensions are present, to 0 if not. */ + unsigned int hasRR:1; + + /** It will be set to 1 if Joliet extensions are present, to 0 if not. */ + unsigned int hasJoliet:1; + + /** + * Will be filled with the size (in 2048 byte block) of the image, as + * reported in the PVM. + */ + uint32_t size; +}; + /** * Create a new image, empty. * @@ -223,6 +289,27 @@ int iso_image_new(const char *name, IsoImage **image); int iso_image_create(IsoImage *image, Ecma119WriteOpts *opts, struct burn_source **burn_src); +/** + * Import a previous session or image, for growing or modify. + * + * @param image + * The image context to which old image will be imported. Note that all + * files added to image, and image attributes, will be replaced with the + * contents of the old image. TODO support for merging old image files + * @param src + * Data Source from which old image will be read. + * @param opts + * Options for image import + * @param features + * Will be filled with the features of the old image. You can pass NULL + * if you're not interested on them. + * @return + * 1 on success, < 0 on error + */ +int iso_image_import(IsoImage *image, IsoDataSource *src, + struct iso_read_opts *opts, + struct iso_read_image_features *features); + /** * Increments the reference counting of the given image. */ From 193fbaef8b6309d79fcf826b0cc6463630931afc Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Thu, 3 Jan 2008 19:47:44 +0100 Subject: [PATCH 3/4] Custom create_node() builder function to deal with old image files. --- src/fs_image.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 211 insertions(+), 10 deletions(-) diff --git a/src/fs_image.c b/src/fs_image.c index c5121d5..0744b37 100644 --- a/src/fs_image.c +++ b/src/fs_image.c @@ -20,6 +20,7 @@ #include #include +#include static int ifs_fs_open(IsoImageFilesystem *fs); @@ -1585,6 +1586,163 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts, return ret; } +static +int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image, + IsoFileSource *src, IsoNode **node) +{ + int result; + struct stat info; + IsoNode *new; + char *name; + ImageFileSourceData *data; + + if (builder == NULL || src == NULL || node == NULL || src->data == NULL) { + return ISO_NULL_POINTER; + } + + data = (ImageFileSourceData*)src->data; + + name = iso_file_source_get_name(src); + + /* get info about source */ + result = iso_file_source_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) { + free(name); + return result; + } + /* take a ref to the src, as stream has taken our ref */ + iso_file_source_ref(src); + file = calloc(1, sizeof(IsoFile)); + if (file == NULL) { + free(name); + iso_stream_unref(stream); + return ISO_MEM_ERROR; + } + + /* the msblock is taken from the image */ + file->msblock = data->block; + + /* + * and we set the sort weight based on the block on image, to + * improve performance on image modifying. + */ + file->sort_weight = INT_MAX - data->block; + + 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) { + free(name); + return ISO_MEM_ERROR; + } + new->type = LIBISO_DIR; + } + break; + case S_IFLNK: + { + /* source is a symbolic link */ + char dest[PATH_MAX]; + IsoSymlink *link; + + result = iso_file_source_readlink(src, dest, PATH_MAX); + if (result < 0) { + free(name); + return result; + } + link = malloc(sizeof(IsoSymlink)); + if (link == NULL) { + free(name); + 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) { + free(name); + 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 = 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; + + new->parent = NULL; + new->next = NULL; + + *node = new; + return ISO_SUCCESS; +} + +/** + * Create a new builder, that is exactly a copy of an old builder, but where + * create_node() function has been replaced by image_builder_create_node. + */ +int iso_image_builder_new(IsoNodeBuilder *old, IsoNodeBuilder **builder) +{ + IsoNodeBuilder *b; + + if (builder == NULL) { + return ISO_NULL_POINTER; + } + + b = malloc(sizeof(IsoNodeBuilder)); + if (b == NULL) { + return ISO_MEM_ERROR; + } + + b->refcount = 1; + b->create_file_data = old->create_file_data; + b->create_node_data = old->create_node_data; + b->create_file = old->create_file; + b->create_node = image_builder_create_node; + b->free = old->free; + + *builder = b; + return ISO_SUCCESS; +} + int iso_image_import(IsoImage *image, IsoDataSource *src, struct iso_read_opts *opts, struct iso_read_image_features *features) @@ -1592,6 +1750,9 @@ int iso_image_import(IsoImage *image, IsoDataSource *src, int ret; IsoImageFilesystem *fs; IsoFilesystem *fsback; + IsoNodeBuilder *blback; + IsoDir *oldroot; + IsoFileSource *newroot; if (image == NULL || src == NULL || opts == NULL) { return ISO_NULL_POINTER; @@ -1602,17 +1763,43 @@ int iso_image_import(IsoImage *image, IsoDataSource *src, return ret; } - /* backup image filesystem and builder */ - fsback = image->fs; - //TODO - - /* get root from filesystem */ + ret = fs->fs.get_root((IsoFilesystem*)fs, &newroot); + if (ret < 0) { + return ret; + } + + /* backup image filesystem, builder and root */ + fsback = image->fs; + blback = image->builder; + oldroot = image->root; + + /* create new builder */ + ret = iso_image_builder_new(blback, &image->builder); + if (ret < 0) { + goto import_revert; + } + + image->fs = (IsoFilesystem*)fs; + + /* create new root, and set root attributes from source */ + ret = iso_node_new_root(&image->root); + if (ret < 0) { + goto import_revert; + } + { + struct stat info; + + /* I know this will not fail */ + iso_file_source_lstat(newroot, &info); + image->root->node.mode = info.st_mode; + image->root->node.uid = info.st_uid; + image->root->node.gid = info.st_gid; + image->root->node.atime = info.st_atime; + image->root->node.mtime = info.st_mtime; + image->root->node.ctime = info.st_ctime; + } - - /* remove root node */ - - /* recursively add image */ @@ -1628,5 +1815,19 @@ int iso_image_import(IsoImage *image, IsoDataSource *src, //TODO - return -1; + ret = ISO_SUCCESS; + goto import_cleanup; + + import_revert:; + + image->root = oldroot; + image->fs = fsback; + + import_cleanup:; + + iso_file_source_unref(newroot); + fs->close(fs); + iso_filesystem_unref((IsoFilesystem*)fs); + + return ret; } From 22c73dc3433ff27b6edccdc761a1d84e9407eeb8 Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Thu, 3 Jan 2008 20:04:08 +0100 Subject: [PATCH 4/4] Add image contents recursively and volume attributes. --- Makefile.am | 1 + src/fs_image.c | 43 ++++++++++++++++++++++++++++++++++--------- src/tree.c | 10 ++++++---- src/tree.h | 21 +++++++++++++++++++++ 4 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 src/tree.h diff --git a/Makefile.am b/Makefile.am index 4e82110..219c2ac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,6 +15,7 @@ src_libisofs_la_SOURCES = \ src/error.h \ src/node.h \ src/node.c \ + src/tree.h \ src/tree.c \ src/image.h \ src/image.c \ diff --git a/src/fs_image.c b/src/fs_image.c index 0744b37..c32d474 100644 --- a/src/fs_image.c +++ b/src/fs_image.c @@ -17,6 +17,7 @@ #include "messages.h" #include "rockridge.h" #include "image.h" +#include "tree.h" #include #include @@ -1801,19 +1802,43 @@ int iso_image_import(IsoImage *image, IsoDataSource *src, } /* recursively add image */ + ret = iso_add_dir_src_rec(image, image->root, newroot); + iso_node_builder_unref(image->builder); - /* recover backed fs and builder */ - - - /* set volume attributes */ - - - if (features != NULL) { - //TODO + /* error during recursive image addition? */ + if (ret <= 0) { + goto import_revert; } - //TODO + /* free old root */ + iso_node_unref((IsoNode*)oldroot); + + /* recover backed fs and builder */ + image->fs = fsback; + image->builder = blback; + + { + _ImageFsData *data; + data = fs->fs.data; + + /* set volume attributes */ + iso_image_set_volset_id(image, data->volset_id); + iso_image_set_volume_id(image, data->volume_id); + iso_image_set_publisher_id(image, data->publisher_id); + iso_image_set_data_preparer_id(image, data->data_preparer_id); + iso_image_set_system_id(image, data->system_id); + iso_image_set_application_id(image, data->application_id); + iso_image_set_copyright_file_id(image, data->copyright_file_id); + iso_image_set_abstract_file_id(image, data->abstract_file_id); + iso_image_set_biblio_file_id(image, data->biblio_file_id); + + if (features != NULL) { + features->hasJoliet = data->joliet; + features->hasRR = data->rr_version != 0; + features->size = data->nblocks; + } + } ret = ISO_SUCCESS; goto import_cleanup; diff --git a/src/tree.c b/src/tree.c index b80af75..0bbfb62 100644 --- a/src/tree.c +++ b/src/tree.c @@ -17,6 +17,7 @@ #include "fsource.h" #include "builder.h" #include "messages.h" +#include "tree.h" #include #include @@ -446,11 +447,12 @@ int check_hidden(IsoImage *image, const char *name) } /** + * Recursively add a given directory to the image tree. + * * @return * 1 continue, 0 stop, < 0 error */ -static -int iso_add_dir_aux(IsoImage *image, IsoDir *parent, IsoFileSource *dir) +int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir) { int result; int action; /* 1 add, 2 skip, 3 stop, < 0 error */ @@ -564,7 +566,7 @@ int iso_add_dir_aux(IsoImage *image, IsoDir *parent, IsoFileSource *dir) /* finally, if the node is a directory we need to recurse */ if (new->type == LIBISO_DIR) { - result = iso_add_dir_aux(image, (IsoDir*)new, file); + result = iso_add_dir_src_rec(image, (IsoDir*)new, file); iso_file_source_unref(file); if (result < 0) { /* error */ @@ -631,7 +633,7 @@ int iso_tree_add_dir_rec(IsoImage *image, IsoDir *parent, const char *dir) iso_file_source_unref(file); return ISO_FILE_IS_NOT_DIR; } - result = iso_add_dir_aux(image, parent, file); + result = iso_add_dir_src_rec(image, parent, file); iso_file_source_unref(file); return result; } diff --git a/src/tree.h b/src/tree.h new file mode 100644 index 0000000..9c5347c --- /dev/null +++ b/src/tree.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2007 Vreixo Formoso + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See COPYING file for details. + */ +#ifndef LIBISO_IMAGE_TREE_H_ +#define LIBISO_IMAGE_TREE_H_ + +#include "image.h" + +/** + * Recursively add a given directory to the image tree. + * + * @return + * 1 continue, 0 stop, < 0 error + */ +int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir); + +#endif /*LIBISO_IMAGE_TREE_H_*/