From 1082e628d1841060bbecadbbbe9d770881505dfe Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 1 Feb 2011 19:16:45 +0100 Subject: [PATCH] New API calls iso_tree_clone(), iso_stream_clone. New IsoFileSourceIface version 2 with method clone_src(). New IsoStreamIface version 4 with method clone_stream(). New public function prototype iso_node_xinfo_cloner. New API calls iso_node_xinfo_make_clonable(), iso_node_xinfo_get_cloner(). New public iso_node_xinfo_cloner instance aaip_xinfo_cloner(). New API calls iso_node_get_next_xinfo(), iso_node_remove_all_xinfo(). New API call iso_node_remove_tree(). --- libisofs/filters/external.c | 5 +- libisofs/filters/gzip.c | 5 +- libisofs/filters/zisofs.c | 9 +- libisofs/fs_image.c | 179 ++++++++++++-------------- libisofs/fs_local.c | 51 +++++++- libisofs/libisofs.h | 241 ++++++++++++++++++++++++++++++++---- libisofs/libisofs.ver | 5 + libisofs/md5.c | 34 +++++ libisofs/messages.c | 84 ++++++++++++- libisofs/node.c | 115 ++++++++++++++++- libisofs/node.h | 31 +++++ libisofs/rockridge.c | 19 ++- libisofs/stream.c | 170 +++++++++++++++++++++++-- libisofs/tree.c | 84 ++++++++++++- libisofs/util.h | 14 +++ 15 files changed, 891 insertions(+), 155 deletions(-) diff --git a/libisofs/filters/external.c b/libisofs/filters/external.c index 1b6f72f..85226ee 100644 --- a/libisofs/filters/external.c +++ b/libisofs/filters/external.c @@ -41,7 +41,7 @@ * for classical pipe filtering. */ - +/* IMPORTANT: Any change must be reflected by extf_clone_stream() */ /* * Individual runtime properties exist only as long as the stream is opened. */ @@ -606,6 +606,9 @@ int extf_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag) IsoStream *new_input_stream, *stream; ExternalFilterStreamData *stream_data, *old_stream_data; + if (flag) + return ISO_STREAM_NO_CLONE; /* unknown option required */ + stream_data = calloc(1, sizeof(ExternalFilterStreamData)); if (stream_data == NULL) return ISO_OUT_OF_MEM; diff --git a/libisofs/filters/gzip.c b/libisofs/filters/gzip.c index a610e12..ef2cb54 100644 --- a/libisofs/filters/gzip.c +++ b/libisofs/filters/gzip.c @@ -154,7 +154,7 @@ static int gzip_compression_level = 6; /* * The data payload of an individual Gzip Filter IsoStream */ -/* IMPORTANT: Any change must be reflected by >>> _clone() */ +/* IMPORTANT: Any change must be reflected by gzip_clone_stream() */ typedef struct { IsoStream *orig; @@ -538,6 +538,9 @@ int gzip_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag) IsoStream *new_input_stream, *stream; GzipFilterStreamData *stream_data, *old_stream_data; + if (flag) + return ISO_STREAM_NO_CLONE; /* unknown option required */ + stream_data = calloc(1, sizeof(GzipFilterStreamData)); if (stream_data == NULL) return ISO_OUT_OF_MEM; diff --git a/libisofs/filters/zisofs.c b/libisofs/filters/zisofs.c index a3e2d88..742b71c 100644 --- a/libisofs/filters/zisofs.c +++ b/libisofs/filters/zisofs.c @@ -168,7 +168,7 @@ static int ziso_compression_level = 6; /* * The common data payload of an individual Zisofs Filter IsoStream - * IMPORTANT: Any change must be reflected by ziso_clone_stream. + * IMPORTANT: Any change must be reflected by ziso_clone_stream(). */ typedef struct { @@ -185,7 +185,7 @@ typedef struct /* * The data payload of an individual Zisofs Filter Compressor IsoStream - * IMPORTANT: Any change must be reflected by ziso_clone_stream. + * IMPORTANT: Any change must be reflected by ziso_clone_stream(). */ typedef struct { @@ -201,7 +201,7 @@ typedef struct /* * The data payload of an individual Zisofs Filter Uncompressor IsoStream - * IMPORTANT: Any change must be reflected by ziso_clone_stream. + * IMPORTANT: Any change must be reflected by ziso_clone_stream(). */ typedef struct { @@ -792,6 +792,9 @@ int ziso_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag) ZisofsUncomprStreamData *uncompr, *old_uncompr; ZisofsComprStreamData *compr, *old_compr; + if (flag) + return ISO_STREAM_NO_CLONE; /* unknown option required */ + ret = iso_stream_clone_filter_common(old_stream, &stream, &new_input_stream, 0); if (ret < 0) diff --git a/libisofs/fs_image.c b/libisofs/fs_image.c index 666cca0..dd5984e 100644 --- a/libisofs/fs_image.c +++ b/libisofs/fs_image.c @@ -317,7 +317,7 @@ typedef struct typedef struct image_fs_data ImageFileSourceData; -/* IMPORTANT: Any change must be reflected by iso_ifs_source_clone */ +/* IMPORTANT: Any change must be reflected by ifs_clone_src */ struct image_fs_data { IsoImageFilesystem *fs; /**< reference to the image it belongs to */ @@ -1044,10 +1044,87 @@ int ifs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) return 1; } +static +int ifs_clone_src(IsoFileSource *old_source, + IsoFileSource **new_source, int flag) +{ + IsoFileSource *src = NULL; + ImageFileSourceData *old_data, *new_data = NULL; + char *new_name = NULL; + struct iso_file_section *new_sections = NULL; + void *new_aa_string = NULL; + int i, ret; + + if (flag) + return ISO_STREAM_NO_CLONE; /* unknown option required */ + + old_data = (ImageFileSourceData *) old_source->data; + *new_source = NULL; + src = calloc(1, sizeof(IsoFileSource)); + if (src == NULL) + goto no_mem; + new_name = strdup(old_data->name); + if (new_name == NULL) + goto no_mem; + new_data = calloc(1, sizeof(ImageFileSourceData)); + + if (new_data == NULL) + goto no_mem; + if (old_data->nsections > 0) { + new_sections = calloc(old_data->nsections, + sizeof(struct iso_file_section)); + if (new_sections == NULL) + goto no_mem; + } + ret = aaip_xinfo_cloner(old_data->aa_string, &new_aa_string, 0); + if (ret < 0) + goto no_mem; + + new_data->fs = old_data->fs; + iso_filesystem_ref(new_data->fs); + + new_data->parent = old_data->parent; + iso_file_source_ref(new_data->parent); + + memcpy(&(new_data->info), &(old_data->info), sizeof(struct stat)); + new_data->name = new_name; + new_data->sections = new_sections; + new_data->nsections = old_data->nsections; + for (i = 0; i < new_data->nsections; i++) + memcpy(new_data->sections + i, old_data->sections + i, + sizeof(struct iso_file_section)); + new_data->opened = old_data->opened; +#ifdef Libisofs_with_zliB + new_data->header_size_div4 = old_data->header_size_div4; + new_data->block_size_log2 = old_data->block_size_log2; + new_data->uncompressed_size = old_data->uncompressed_size; +#endif + new_data->data.content = NULL; + new_data->aa_string = (unsigned char *) new_aa_string; + + src->class = old_source->class; + src->refcount = 1; + src->data = new_data; + *new_source = src; + return ISO_SUCCESS; +no_mem:; + if (src != NULL) + free((char *) src); + if (new_data != NULL) + free((char *) new_data); + if (new_name != NULL) + free(new_name); + if (new_sections != NULL) + free((char *) new_sections); + if (new_aa_string != NULL) + aaip_xinfo_func(new_aa_string, 1); + return ISO_OUT_OF_MEM; +} + IsoFileSourceIface ifs_class = { - 1, /* version */ + 2, /* version */ ifs_get_path, ifs_get_name, ifs_lstat, @@ -1061,7 +1138,8 @@ IsoFileSourceIface ifs_class = { ifs_get_filesystem, ifs_free, ifs_lseek, - ifs_get_aa_string + ifs_get_aa_string, + ifs_clone_src }; @@ -1988,101 +2066,6 @@ void ifs_fs_free(IsoFilesystem *fs) free(data); } -int iso_ifs_source_clone(IsoFileSource *old_source, - IsoFileSource **new_source, int flag) -{ - IsoFileSource *src = NULL; - ImageFileSourceData *old_data, *new_data = NULL; - char *new_name = NULL; - struct iso_file_section *new_sections = NULL; - unsigned char *new_aa_string; - size_t aa_size; - int i, new_aa_length = 0; - - old_data = (ImageFileSourceData *) old_source->data; - *new_source = NULL; - src = calloc(1, sizeof(IsoFileSource)); - if (src == NULL) - goto no_mem; - new_data = calloc(1, sizeof(ImageFileSourceData)); - if (new_data == NULL) - goto no_mem; - new_name = strdup(old_data->name); - if (new_name == NULL) { - free((char *) src); - free((char *) new_data); - return ISO_OUT_OF_MEM; - } - if (old_data->nsections > 0) { - new_sections = calloc(old_data->nsections, - sizeof(struct iso_file_section)); - if (new_sections == NULL) - goto no_mem; - } - if (old_data->aa_string != NULL) { - aa_size = aaip_count_bytes(old_data->aa_string, 0); - if (aa_size > 0) { - new_aa_string = calloc(1, aa_size); - if (new_aa_string == NULL) - goto no_mem; - } - } - - new_data->fs = old_data->fs; - iso_filesystem_ref(new_data->fs); - - /* Re-using the directory structure of the original image tree is - supposed to not spoil independence of the cloned IsoFileSource because - that directory structure does not change as long as the loaded - image exists. - The .readdir() method of IsoFileSourceIface will not list the clones - but rather the originals. - It is unclear anyway, how it should work with the root of a cloned - IsoNode tree which would need to be implanted fakely into the - IsoFilesystem. - - Currently there is the technical problem that a new parent would have - to be passed through the IsoStream cloning call, which cannot have - knowledge of a newly created IsoSource parent. - */ - new_data->parent = old_data->parent; - iso_file_source_ref(new_data->parent); - - memcpy(&(new_data->info), &(old_data->info), sizeof(struct stat)); - new_data->name = new_name; - new_data->sections = new_sections; - new_data->nsections = old_data->nsections; - for (i = 0; i < new_data->nsections; i++) - memcpy(new_data->sections + i, old_data->sections + i, - sizeof(struct iso_file_section)); - new_data->opened = old_data->opened; -#ifdef Libisofs_with_zliB - new_data->header_size_div4 = old_data->header_size_div4; - new_data->block_size_log2 = old_data->block_size_log2; - new_data->uncompressed_size = old_data->uncompressed_size; -#endif - new_data->data.content = NULL; - if (new_aa_length > 0) - memcpy(new_aa_string, old_data->aa_string, new_aa_length); - new_data->aa_string = new_aa_string; - - *new_source = src; - return ISO_SUCCESS; -no_mem:; - if (src != NULL) - free((char *) src); - if (new_data != NULL) - free((char *) new_data); - if (new_name != NULL) - free(new_name); - if (new_sections != NULL) - free((char *) new_sections); - if (new_aa_string != NULL) - free((char *) new_aa_string); - return ISO_OUT_OF_MEM; -} - - /** * Read the SUSP system user entries of the "." entry of the root directory, * indentifying when Rock Ridge extensions are being used. diff --git a/libisofs/fs_local.c b/libisofs/fs_local.c index 25f44b2..63834f5 100644 --- a/libisofs/fs_local.c +++ b/libisofs/fs_local.c @@ -39,7 +39,7 @@ int iso_file_source_new_lfs(IsoFileSource *parent, const char *name, */ IsoFilesystem *lfs= NULL; - +/* IMPORTANT: Any change must be reflected by lfs_clone_src() */ typedef struct { /** reference to the parent (if root it points to itself) */ @@ -534,10 +534,54 @@ ex:; return ret; } +static +int lfs_clone_src(IsoFileSource *old_source, + IsoFileSource **new_source, int flag) +{ + IsoFileSource *src = NULL; + char *new_name = NULL; + _LocalFsFileSource *old_data, *new_data = NULL; + + if (flag) + return ISO_STREAM_NO_CLONE; /* unknown option required */ + + old_data = (_LocalFsFileSource *) old_source->data; + *new_source = NULL; + src = calloc(1, sizeof(IsoFileSource)); + if (src == NULL) + goto no_mem; + new_name = strdup(old_data->name); + if (new_name == NULL) + goto no_mem; + + new_data = calloc(1, sizeof(_LocalFsFileSource)); + if (new_data == NULL) + goto no_mem; + new_data->openned = 0; + new_data->info.fd = -1; /* the value does not matter with (openned == 0) */ + new_data->name = new_name; + new_data->parent = old_data->parent; + iso_file_source_ref(new_data->parent); + + src->class = old_source->class; + src->refcount = 1; + src->data = new_data; + *new_source = src; + return ISO_SUCCESS; +no_mem:; + if (src != NULL) + free((char *) src); + if (new_data != NULL) + free((char *) new_data); + if (new_name != NULL) + free(new_name); + return ISO_OUT_OF_MEM; +} + IsoFileSourceIface lfs_class = { - 1, /* version */ + 2, /* version */ lfs_get_path, lfs_get_name, lfs_lstat, @@ -551,7 +595,8 @@ IsoFileSourceIface lfs_class = { lfs_get_filesystem, lfs_free, lfs_lseek, - lfs_get_aa_string + lfs_get_aa_string, + lfs_clone_src }; diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 3581c4d..3f8a45a 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -1,3 +1,7 @@ + +#ifndef LIBISO_LIBISOFS_H_ +#define LIBISO_LIBISOFS_H_ + /* * Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic * Copyright (c) 2009-2011 Thomas Schmitt @@ -24,8 +28,17 @@ * */ -#ifndef LIBISO_LIBISOFS_H_ -#define LIBISO_LIBISOFS_H_ +/* + * Normally this API is operated via public functions and opaque object + * handles. But it also exposes several C structures which may be used to + * provide custom functionality for the objects of the API. The same + * structures are used for internal objects of libisofs, too. + * You are not supposed to manipulate the entrails of such objects if they + * are not your own custom extensions. + * + * See for an example IsoStream = struct iso_stream below. + */ + #include @@ -502,6 +515,8 @@ struct IsoFileSource_Iface * @since 0.6.2 * Version 1 additionally provides function *(get_aa_string)(). * @since 0.6.14 + * Version 2 additionally provides function *(clone_src)(). + * @since 1.0.2 */ int version; @@ -736,6 +751,24 @@ struct IsoFileSource_Iface int (*get_aa_string)(IsoFileSource *src, unsigned char **aa_string, int flag); + /** + * Produce a copy of a source. It must be possible to operate both source + * objects concurrently. + * + * @param old_src + * The existing source object to be copied + * @param new_stream + * Will return a pointer to the copy + * @param flag + * Bitfield for control purposes. Submit 0 for now. + * The function shall return ISO_STREAM_NO_CLONE on unknown flag bits. + * + * @since 1.0.2 + * Present if .version is 2 or higher. + */ + int (*clone_src)(IsoFileSource *old_src, IsoFileSource **new_src, + int flag); + /* * TODO #00004 Add a get_mime_type() function. * This can be useful for GUI apps, to choose the icon of the file @@ -760,6 +793,31 @@ struct iso_file_source #endif /* ! Libisofs_h_as_cpluspluS */ #endif /* ! __cplusplus */ + +/* A class of IsoStream is implemented by a class description + * IsoStreamIface = struct IsoStream_Iface + * and a structure of data storage for each instance of IsoStream. + * This structure shall be known to the functions of the IsoStreamIface. + * To create a custom IsoStream class: + * - Define the structure of the custom instance data. + * - Implement the methods which are described by the definition of + * struct IsoStream_Iface (see below), + * - Create a static instance of IsoStreamIface which lists the methods as + * C function pointers. (Example in libisofs/stream.c : fsrc_stream_class) + * To create an instance of that class: + * - Allocate sizeof(IsoStream) bytes of memory and initialize it as + * struct iso_stream : + * - Point to the custom IsoStreamIface by member .class . + * - Set member .refcount to 1. + * - Let member .data point to the custom instance data. + * + * Regrettably the choice of the structure member name "class" makes it + * impossible to implement this generic interface in C++ language directly. + * If C++ is absolutely necessary then you will have to make own copies + * of the public API structures. Use other names but take care to maintain + * the same memory layout. + */ + /** * Representation of file contents. It is an stream of bytes, functionally * like a pipe. @@ -795,6 +853,7 @@ extern ino_t serial_id; * * @since 0.6.4 */ + struct IsoStream_Iface { /* @@ -851,7 +910,7 @@ struct IsoStream_Iface off_t (*get_size)(IsoStream *stream); /** - * Attempts to read up to count bytes from the given stream into + * Attempt to read up to count bytes from the given stream into * the buffer starting at buf. The implementation has to make sure that * either the full desired count of bytes is delivered or that the * next call to this function will return EOF or error. @@ -867,12 +926,9 @@ struct IsoStream_Iface int (*read)(IsoStream *stream, void *buf, size_t count); /** - * Whether this IsoStream can be read several times, with the same results. - * For example, a regular file is repeatable, you can read it as many - * times as you want. However, a pipe isn't. - * - * This function doesn't take into account if the file has been modified - * between the two reads. + * Tell whether this IsoStream can be read several times, with the same + * results. For example, a regular file is repeatable, you can read it + * as many times as you want. However, a pipe is not. * * @return * 1 if stream is repeatable, 0 if not, @@ -893,13 +949,13 @@ struct IsoStream_Iface void (*free)(IsoStream *stream); /** - * Updates the size of the IsoStream with the current size of the - * underlying source. After calling this, get_size() will return - * the new size. This should never be called after - * iso_image_create_burn_source() was called and the image was not - * completely written. To update the size of all files before written the - * image, you may want to call iso_image_update_sizes() just before - * iso_image_create_burn_source(). + * Update the size of the IsoStream with the current size of the underlying + * source, if the source is prone to size changes. After calling this, + * get_size() shall eventually return the new size. + * This will never be called after iso_image_create_burn_source() was + * called and before the image was completely written. + * (The API call to update the size of all files in the image is + * iso_image_update_sizes()). * * @return * 1 if ok, < 0 on error (has to be a valid libisofs error code) @@ -910,7 +966,7 @@ struct IsoStream_Iface int (*update_size)(IsoStream *stream); /** - * Obtains the eventual input stream of a filter stream. + * Retrieve the eventual input stream of a filter stream. * * @param stream * The eventual filter stream to be inquired. @@ -918,7 +974,7 @@ struct IsoStream_Iface * Bitfield for control purposes. 0 means normal behavior. * @return * The input stream, if one exists. Elsewise NULL. - * No extra reference to the stream is taken by this call. + * No extra reference to the stream shall be taken by this call. * * @since 0.6.18 * Present if .version is 2 or higher. @@ -978,6 +1034,9 @@ struct IsoStream_Iface * Will return a pointer to the copy * @param flag * Bitfield for control purposes. 0 means normal behavior. + * The function shall return ISO_STREAM_NO_CLONE on unknown flag bits. + * @return + * 1 in case of success, or an error code < 0 * * @since 1.0.2 * Present if .version is 4 or higher. @@ -3222,9 +3281,9 @@ void iso_node_unref(IsoNode *node); enum IsoNodeType iso_node_get_type(IsoNode *node); /** - * Function to handle particular extended information. The function - * pointer acts as an identifier for the type of the information. Structs - * with same information type must use the same function. + * Class of functions to handle particular extended information. A function + * instance acts as an identifier for the type of the information. Structs + * with same information type must use a pointer to the same function. * * @param data * Attached data @@ -3279,6 +3338,20 @@ int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data); */ int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc); +/** + * Remove all extended information from the given node. + * + * @param node + * The node where to remove all extended info + * @param flag + * Bitfield for control purposes, unused yet, submit 0 + * @return + * 1 on success, < 0 on error + * + * @since 1.0.2 + */ +int iso_node_remove_all_xinfo(IsoNode *node, int flag); + /** * Get the given extended info (defined by the proc function) from the * given node. @@ -3298,6 +3371,102 @@ int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc); */ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data); + +/** + * Get the next pair of function pointer and data of an iteration of the + * list of extended informations. Like: + * iso_node_xinfo_func proc; + * void *handle = NULL, *data; + * while (iso_node_get_next_xinfo(node, &handle, &proc, &data) == 1) { + * ... make use of proc and data ... + * } + * The iteration allocates no memory. So you may end it without any disposal + * action. + * IMPORTANT: Do not continue iterations after manipulating the extended + * information of a node. Memory corruption hazard ! + * @param node + * The node to inquire + * @param handle + * The opaque iteration handle. Initialize iteration by submitting + * a pointer to a void pointer with value NULL. + * Do not alter its content until iteration has ended. + * @param proc + * The function pointer which serves as key + * @param data + * Will be filled with the extended info corresponding to the given proc + * function + * @return + * 1 on success + * 0 if iteration has ended (proc and data are invalid then) + * < 0 on error + * + * @since 1.0.2 + */ +int iso_node_get_next_xinfo(IsoNode *node, void **handle, + iso_node_xinfo_func *proc, void **data); + + +/** + * Class of functions to clone extended information. A function instance gets + * associated to a particular iso_node_xinfo_func instance by function + * iso_node_xinfo_make_clonable(). This is a precondition to have IsoNode + * objects clonable which carry data for a particular iso_node_xinfo_func. + * + * @param old_data + * Data item to be cloned + * @param new_data + * Shall return the cloned data item + * @param flag + * Unused yet, submit 0 + * The function shall return ISO_XINFO_NO_CLONE on unknown flag bits. + * @return + * > 0 number of allocated bytes + * 0 no size info is available + * < 0 error + * + * @since 1.0.2 + */ +typedef int (*iso_node_xinfo_cloner)(void *old_data, void **new_data,int flag); + +/** + * Associate a iso_node_xinfo_cloner to a particular class of extended + * information in order to make it clonable. + * + * @param proc + * The key and disposal function which identifies the particular + * extended information class. + * @param cloner + * The cloner function which shall be associated with proc. + * @param flag + * Unused yet, submit 0 + * @return + * 1 success, < 0 error + * + * @since 1.0.2 + */ +int iso_node_xinfo_make_clonable(iso_node_xinfo_func proc, + iso_node_xinfo_cloner cloner, int flag); + +/** + * Inquire the registered cloner function for a particular class of + * extended information. + * + * @param proc + * The key and disposal function which identifies the particular + * extended information class. + * @param cloner + * Will return the cloner function which is associated with proc, or NULL. + * @param flag + * Unused yet, submit 0 + * @return + * 1 success, 0 no cloner registered for proc, < 0 error + * + * @since 1.0.2 + */ +int iso_node_xinfo_get_cloner(iso_node_xinfo_func proc, + iso_node_xinfo_cloner *cloner, int flag); + + /** * Set the name of a node. Note that if the node is already added to a dir * this can fail if dir already contains a node with the new name. @@ -4456,17 +4625,24 @@ int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent, * clone_stream(). * Surely clonable node types are: * IsoDir, - * >>> IsoSymlink, - * >>> IsoSpecial, - * IsoFile from a loaded ISO image without filter streams, - * >>> IsoFile referring to local filesystem files without filter streams. + * IsoSymlink, + * IsoSpecial, + * IsoFile from a loaded ISO image, + * IsoFile referring to local filesystem files, + * IsoFile created by iso_tree_add_new_file + * from a stream created by iso_memory_stream_new(), + * IsoFile created by iso_tree_add_new_cut_out_node() * Silently ignored are nodes of type IsoBoot. - * An IsoFile node with filter streams can be cloned if all those filters + * An IsoFile node with IsoStream filters can be cloned if all those filters * are clonable and the node would be clonable without filter. - * Clonable filter streams are created by: + * Clonable IsoStream filters are created by: * iso_file_add_zisofs_filter() * iso_file_add_gzip_filter() * iso_file_add_external_filter() + * An IsoNode with extended information as of iso_node_add_xinfo() can only be + * cloned if each of the iso_node_xinfo_func instances is associated to a + * clone function. See iso_node_xinfo_make_clonable(). + * All internally used classes of extended information are clonable. * * @param node * The node to be cloned. @@ -5334,6 +5510,12 @@ int iso_stream_clone(IsoStream *old_stream, IsoStream **new_stream, int flag); */ int aaip_xinfo_func(void *data, int flag); +/** + * The iso_node_xinfo_cloner function which gets associated to aaip_xinfo_func + * by iso_init() resp. iso_init_with_flag() via iso_node_xinfo_make_clonable(). + * @since 1.0.2 + */ +int aaip_xinfo_cloner(void *old_data, void **new_data, int flag); /** * Get the eventual ACLs which are associated with the node. @@ -6617,6 +6799,11 @@ int iso_md5_match(char first_md5[16], char second_md5[16]); (FAILURE, HIGH, -374) */ #define ISO_STREAM_NO_CLONE 0xE830FE8A +/** Extended information class offers no cloning method + (FAILURE, HIGH, -375) */ +#define ISO_XINFO_NO_CLONE 0xE830FE89 + + /* Internal developer note: Place new error codes directly above this comment. Newly introduced errors must get a message entry in diff --git a/libisofs/libisofs.ver b/libisofs/libisofs.ver index 5d9994c..3392fee 100644 --- a/libisofs/libisofs.ver +++ b/libisofs/libisofs.ver @@ -1,5 +1,6 @@ LIBISOFS6 { global: +aaip_xinfo_cloner; aaip_xinfo_func; el_torito_get_bootable; el_torito_get_boot_media_type; @@ -156,6 +157,7 @@ iso_node_get_hidden; iso_node_get_mode; iso_node_get_mtime; iso_node_get_name; +iso_node_get_next_xinfo; iso_node_get_old_image_lba; iso_node_get_parent; iso_node_get_permissions; @@ -166,6 +168,7 @@ iso_node_get_xinfo; iso_node_lookup_attr; iso_node_ref; iso_node_remove; +iso_node_remove_all_xinfo; iso_node_remove_tree; iso_node_remove_xinfo; iso_node_set_acl_text; @@ -181,6 +184,8 @@ iso_node_set_sort_weight; iso_node_set_uid; iso_node_take; iso_node_unref; +iso_node_xinfo_get_cloner; +iso_node_xinfo_make_clonable; iso_node_zf_by_magic; iso_obtain_msgs; iso_read_image_features_destroy; diff --git a/libisofs/md5.c b/libisofs/md5.c index f100a6b..f2c8906 100644 --- a/libisofs/md5.c +++ b/libisofs/md5.c @@ -424,6 +424,22 @@ int checksum_cx_xinfo_func(void *data, int flag) return 1; } +/* The iso_node_xinfo_cloner function which gets associated to + * checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via + * iso_node_xinfo_make_clonable() + */ +int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag) +{ + *new_data = NULL; + if (flag) + return ISO_XINFO_NO_CLONE; + if (old_data == NULL) + return 0; + /* data is an int disguised as pointer. It does not point to memory. */ + *new_data = old_data; + return 0; +} + /* Function to identify and manage md5 sums of unspecified providence stored * directly in this xinfo. @@ -436,6 +452,24 @@ int checksum_md5_xinfo_func(void *data, int flag) return 1; } +/* The iso_node_xinfo_cloner function which gets associated to + * checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via + * iso_node_xinfo_make_clonable() + */ +int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag) +{ + *new_data = NULL; + if (flag) + return ISO_XINFO_NO_CLONE; + if (old_data == NULL) + return 0; + *new_data = calloc(1, 16); + if (*new_data == NULL) + return ISO_OUT_OF_MEM; + memcpy(*new_data, old_data, 16); + return 16; +} + /* ----------------------------------------------------------------------- */ diff --git a/libisofs/messages.c b/libisofs/messages.c index d86885b..7326246 100644 --- a/libisofs/messages.c +++ b/libisofs/messages.c @@ -37,6 +37,7 @@ #include "messages.h" #include "util.h" +#include "node.h" /* @@ -80,11 +81,69 @@ int abort_threshold = LIBISO_MSGS_SEV_FAILURE; struct libiso_msgs *libiso_msgr = NULL; +/* ------------- List of xinfo clone functions ----------- */ + +struct iso_xinfo_cloner_assoc { + iso_node_xinfo_func proc; + iso_node_xinfo_cloner cloner; + struct iso_xinfo_cloner_assoc *next; +}; + +struct iso_xinfo_cloner_assoc *iso_xinfo_cloner_list = NULL; + +/* API */ +int iso_node_xinfo_make_clonable(iso_node_xinfo_func proc, + iso_node_xinfo_cloner cloner, int flag) +{ + struct iso_xinfo_cloner_assoc *assoc; + + assoc = calloc(1, sizeof(struct iso_xinfo_cloner_assoc)); + if (assoc == NULL) + return ISO_OUT_OF_MEM; + assoc->proc = proc; + assoc->cloner = cloner; + assoc->next = iso_xinfo_cloner_list; + iso_xinfo_cloner_list = assoc; + return ISO_SUCCESS; +} + +/* API */ +int iso_node_xinfo_get_cloner(iso_node_xinfo_func proc, + iso_node_xinfo_cloner *cloner, int flag) +{ + struct iso_xinfo_cloner_assoc *assoc; + + *cloner = NULL; + for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next) { + if (assoc->proc != proc) + continue; + *cloner = assoc->cloner; + return 1; + } + return 0; +} + +static +int iso_node_xinfo_dispose_cloners(int flag) +{ + struct iso_xinfo_cloner_assoc *assoc, *next; + + for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = next) { + next = assoc->next; + free((char *) assoc); + } + return(1); +} + +/* ------------- End of xinfo clone functions list ----------- */ + + /* @param flag bit0= do not set up locale by LC_* environment variables */ int iso_init_with_flag(int flag) { + int ret; #ifdef Libisofs_with_libjtE @@ -120,7 +179,6 @@ LIBJTE_MISCONFIGURATION_ = 0; #endif /* Libisofs_with_libjtE */ - if (! (flag & 1)) { iso_init_locale(0); } @@ -130,10 +188,29 @@ LIBJTE_MISCONFIGURATION_ = 0; } libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER, LIBISO_MSGS_SEV_FATAL, "libisofs: ", 0); + + ret = iso_node_xinfo_make_clonable(aaip_xinfo_func, aaip_xinfo_cloner, 0); + if (ret < 0) + return ret; + ret = iso_node_xinfo_make_clonable(checksum_cx_xinfo_func, + checksum_cx_xinfo_cloner, 0); + if (ret < 0) + return ret; + ret = iso_node_xinfo_make_clonable(checksum_md5_xinfo_func, + checksum_md5_xinfo_cloner, 0); + if (ret < 0) + return ret; + ret = iso_node_xinfo_make_clonable(zisofs_zf_xinfo_func, + zisofs_zf_xinfo_cloner, 0); + if (ret < 0) + return ret; + ret = iso_node_xinfo_make_clonable(iso_px_ino_xinfo_func, + iso_px_ino_xinfo_cloner, 0); + if (ret < 0) + return ret; return 1; } - int iso_init() { return iso_init_with_flag(0); @@ -142,6 +219,7 @@ int iso_init() void iso_finish() { libiso_msgs_destroy(&libiso_msgr, 0); + iso_node_xinfo_dispose_cloners(0); } int iso_set_abort_severity(char *severity) @@ -366,6 +444,8 @@ const char *iso_error_to_msg(int errcode) return "File name cannot be written into ECMA-119 untranslated"; case ISO_STREAM_NO_CLONE: return "Data file input stream object offers no cloning method"; + case ISO_XINFO_NO_CLONE: + return "Extended information class offers no cloning method"; default: return "Unknown error"; } diff --git a/libisofs/node.c b/libisofs/node.c index b953bbb..e0bccb5 100644 --- a/libisofs/node.c +++ b/libisofs/node.c @@ -226,6 +226,77 @@ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data) return 0; } +/* API */ +int iso_node_get_next_xinfo(IsoNode *node, void **handle, + iso_node_xinfo_func *proc, void **data) +{ + IsoExtendedInfo *xinfo; + + if (node == NULL || handle == NULL || proc == NULL || data == NULL) + return ISO_NULL_POINTER; + *proc = NULL; + *data = NULL; + xinfo = (IsoExtendedInfo *) *handle; + if (xinfo == NULL) + xinfo = node->xinfo; + else + xinfo = xinfo->next; + *handle = xinfo; + if (xinfo == NULL) + return 0; + *proc = xinfo->process; + *data = xinfo->data; + return ISO_SUCCESS; +} + +int iso_node_remove_all_xinfo(IsoNode *node, int flag) +{ + IsoExtendedInfo *pos, *next; + + for (pos = node->xinfo; pos != NULL; pos = next) { + next = pos->next; + pos->process(pos->data, 1); + free((char *) pos); + } + node->xinfo = NULL; + return ISO_SUCCESS; +} + +int iso_node_clone_xinfo(IsoNode *from_node, IsoNode *to_node, int flag) +{ + void *handle = NULL, *data, *new_data; + iso_node_xinfo_func proc; + iso_node_xinfo_cloner cloner; + int ret; + + iso_node_remove_all_xinfo(to_node, 0); + while (1) { + ret = iso_node_get_next_xinfo(from_node, &handle, &proc, &data); + if (ret <= 0) + break; + ret = iso_node_xinfo_get_cloner(proc, &cloner, 0); + if (ret == 0) + return ISO_XINFO_NO_CLONE; + if (ret < 0) + return ret; + ret = (*cloner)(data, &new_data, 0); + if (ret < 0) + break; + ret = iso_node_add_xinfo(to_node, proc, new_data); + if (ret < 0) + break; + } + if (ret < 0) { + iso_node_remove_all_xinfo(to_node, 0); + return ret; + } else { + + /* >>> revert order of xinfo list */; + + } + return ISO_SUCCESS; +} + /** * Get the type of an IsoNode. */ @@ -651,6 +722,9 @@ int iso_node_take(IsoNode *node) if (dir == NULL) { return ISO_NODE_NOT_ADDED_TO_DIR; } + + /* >>> Do not take root directory ! (dir == node) ? */; + pos = iso_dir_find_node(dir, node); if (pos == NULL) { /* should never occur */ @@ -694,6 +768,9 @@ int iso_node_remove_tree(IsoNode *node, IsoDirIter *boss_iter) int ret; if (node->type != LIBISO_DIR) { + + /* >>> Do not remove root directory ! (node->parent == node) ? */; + ret = iso_dir_get_children((IsoDir *) node, &iter); if (ret < 0) goto ex; @@ -705,6 +782,11 @@ int iso_node_remove_tree(IsoNode *node, IsoDirIter *boss_iter) if (ret < 0) goto ex; } + if (node->parent == NULL) { + /* node is not grafted into a boss directory */ + iso_node_unref(node); + goto ex; + } } if (boss_iter != NULL) ret = iso_dir_iter_remove(boss_iter); @@ -2183,6 +2265,23 @@ int zisofs_zf_xinfo_func(void *data, int flag) return 1; } +/* The iso_node_xinfo_cloner function which gets associated to + * zisofs_zf_xinfo_func by iso_init() resp. iso_init_with_flag() via + * iso_node_xinfo_make_clonable() + */ +int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag) +{ + *new_data = NULL; + if (flag) + return ISO_XINFO_NO_CLONE; + if (old_data == NULL) + return 0; + *new_data = calloc(1, sizeof(struct zisofs_zf_info)); + if (*new_data == NULL) + return ISO_OUT_OF_MEM; + memcpy(*new_data, old_data, sizeof(struct zisofs_zf_info)); + return (int) sizeof(struct zisofs_zf_info); +} /* Checks whether a file effectively bears a zisofs file header and eventually * marks this by a struct zisofs_zf_info as xinfo of the file node. @@ -2304,6 +2403,21 @@ int iso_px_ino_xinfo_func(void *data, int flag) return 1; } +/* The iso_node_xinfo_cloner function which gets associated to + * iso_px_ino_xinfo_func by iso_init() resp. iso_init_with_flag() via + * iso_node_xinfo_make_clonable() + */ +int iso_px_ino_xinfo_cloner(void *old_data, void **new_data, int flag) +{ + *new_data = NULL; + if (flag) + return ISO_XINFO_NO_CLONE; + *new_data = calloc(1, sizeof(ino_t)); + if (*new_data == NULL) + return ISO_OUT_OF_MEM; + memcpy(*new_data, old_data, sizeof(ino_t)); + return (int) sizeof(ino_t); +} /* * @param flag @@ -2394,7 +2508,6 @@ int iso_node_set_ino_xinfo(IsoNode *node, ino_t ino, int flag) return ret; } - int iso_node_set_ino(IsoNode *node, ino_t ino, int flag) { int ret; diff --git a/libisofs/node.h b/libisofs/node.h index 2cd431f..fe73a5c 100644 --- a/libisofs/node.h +++ b/libisofs/node.h @@ -482,4 +482,35 @@ int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba, int flag); +/** + * Copy the xinfo list from one node to the another. + */ +int iso_node_clone_xinfo(IsoNode *from_node, IsoNode *to_node, int flag); + + +/** + * The iso_node_xinfo_func instance which governs the storing of the inode + * number from Rock Ridge field PX. + */ +int iso_px_ino_xinfo_func(void *data, int flag); + +/* The iso_node_xinfo_cloner function which gets associated to + * iso_px_ino_xinfo_func by iso_init() resp. iso_init_with_flag() via + * iso_node_xinfo_make_clonable() + */ +int iso_px_ino_xinfo_cloner(void *old_data, void **new_data, int flag); + + +/* Function to identify and manage ZF parameters of zisofs compression. + * data is supposed to be a pointer to struct zisofs_zf_info + */ +int zisofs_zf_xinfo_func(void *data, int flag); + +/* The iso_node_xinfo_cloner function which gets associated to + * zisofs_zf_xinfo_func by iso_init() resp. iso_init_with_flag() via + * iso_node_xinfo_make_clonable() + */ +int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag); + + #endif /*LIBISO_NODE_H_*/ diff --git a/libisofs/rockridge.c b/libisofs/rockridge.c index dcdcaae..ff6b74b 100644 --- a/libisofs/rockridge.c +++ b/libisofs/rockridge.c @@ -905,7 +905,7 @@ int add_zf_field(Ecma119Image *t, Ecma119Node *n, struct susp_info *info, return 1; } - +/* API */ int aaip_xinfo_func(void *data, int flag) { if (flag & 1) { @@ -914,6 +914,23 @@ int aaip_xinfo_func(void *data, int flag) return 1; } +/* API */ +int aaip_xinfo_cloner(void *old_data, void **new_data, int flag) +{ + size_t aa_size; + + *new_data = NULL; + if (old_data == NULL) + return 0; + aa_size = aaip_count_bytes((unsigned char *) old_data, 0); + if (aa_size <= 0) + return ISO_AAIP_BAD_AASTRING; + *new_data = calloc(1, aa_size); + if (*new_data == NULL) + return ISO_OUT_OF_MEM; + memcpy(*new_data, old_data, aa_size); + return (int) aa_size; +} /** * Compute SUA length and eventual Continuation Area length of field NM and diff --git a/libisofs/stream.c b/libisofs/stream.c index 5d5a59e..f70d415 100644 --- a/libisofs/stream.c +++ b/libisofs/stream.c @@ -157,20 +157,18 @@ int fsrc_update_size(IsoStream *stream) return ISO_SUCCESS; } +static IsoStream *fsrc_get_input_stream(IsoStream *stream, int flag) { return NULL; } +static int fsrc_cmp_ino(IsoStream *s1, IsoStream *s2) { int ret; - /* <<< provisory */ ret = iso_stream_cmp_ino(s1, s2, 1); - - /* >>> find out whether both streams point to the same image file */; - return ret; } @@ -181,6 +179,13 @@ int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream, IsoStream *stream; int ret; + if (flag) + return ISO_STREAM_NO_CLONE; /* unknown option required */ + + data = (FSrcStreamData*) old_stream->data; + if (data->src->class->version < 2) + return ISO_STREAM_NO_CLONE; /* No clone_src() method available */ + *new_stream = NULL; stream = calloc(1, sizeof(IsoStream)); if (stream == NULL) @@ -191,12 +196,11 @@ int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream, return ISO_OUT_OF_MEM; } *new_stream = stream; - data = (FSrcStreamData*) old_stream->data; stream->class = old_stream->class; stream->refcount = 1; stream->data = new_data; - - ret = iso_ifs_source_clone(data->src, &(new_data->src), 0); + + ret = data->src->class->clone_src(data->src, &(new_data->src), 0); if (ret < 0) { free((char *) stream); free((char *) new_data); @@ -210,7 +214,7 @@ int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream, } IsoStreamIface fsrc_stream_class = { - 4, /* .clone_stream() is defined for this stream */ + 4, /* version */ "fsrc", fsrc_open, fsrc_close, @@ -430,11 +434,76 @@ void cut_out_free(IsoStream *stream) free(data); } +static +int cut_out_update_size(IsoStream *stream) +{ + return ISO_SUCCESS; +} + +static +IsoStream* cut_out_get_input_stream(IsoStream *stream, int flag) +{ + return NULL; +} + +static +int cut_out_cmp_ino(IsoStream *s1, IsoStream *s2) +{ + int ret; + + ret = iso_stream_cmp_ino(s1, s2, 1); + return ret; +} + +static +int cut_out_clone_stream(IsoStream *old_stream, IsoStream **new_stream, + int flag) +{ + struct cut_out_stream *data, *new_data; + IsoStream *stream; + int ret; + + if (flag) + return ISO_STREAM_NO_CLONE; /* unknown option required */ + + data = (struct cut_out_stream *) old_stream->data; + if (data->src->class->version < 2) + return ISO_STREAM_NO_CLONE; /* No clone_src() method available */ + + *new_stream = NULL; + stream = calloc(1, sizeof(IsoStream)); + if (stream == NULL) + return ISO_OUT_OF_MEM; + stream->refcount = 1; + stream->class = old_stream->class; + new_data = calloc(1, sizeof(struct cut_out_stream)); + if (new_data == NULL) { + free((char *) stream); + return ISO_OUT_OF_MEM; + } + ret = data->src->class->clone_src(data->src, &(new_data->src), 0); + if (ret < 0) { + free((char *) stream); + free((char *) new_data); + return ret; + } + + new_data->dev_id = (dev_t) 0; + new_data->ino_id = cut_out_serial_id++; + new_data->offset = data->offset; + new_data->size = data->size; + new_data->pos = 0; + + stream->data = new_data; + *new_stream = stream; + return ISO_SUCCESS; +} + /* * TODO update cut out streams to deal with update_size(). Seems hard. */ IsoStreamIface cut_out_stream_class = { - 0, + 4, /* version */ "cout", cut_out_open, cut_out_close, @@ -442,7 +511,12 @@ IsoStreamIface cut_out_stream_class = { cut_out_read, cut_out_is_repeatable, cut_out_get_id, - cut_out_free + cut_out_free, + cut_out_update_size, + cut_out_get_input_stream, + cut_out_cmp_ino, + cut_out_clone_stream + }; int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size, @@ -604,12 +678,77 @@ void mem_free(IsoStream *stream) { MemStreamData *data; data = (MemStreamData*)stream->data; - free(data->buf); + if (data->buf != NULL) + free(data->buf); free(data); } +static +int mem_update_size(IsoStream *stream) +{ + return ISO_SUCCESS; +} + +static +IsoStream* mem_get_input_stream(IsoStream *stream, int flag) +{ + return NULL; +} + +static +int mem_cmp_ino(IsoStream *s1, IsoStream *s2) +{ + int ret; + + ret = iso_stream_cmp_ino(s1, s2, 1); + return ret; +} + +static +int mem_clone_stream(IsoStream *old_stream, IsoStream **new_stream, + int flag) +{ + MemStreamData *data, *new_data; + IsoStream *stream; + uint8_t *new_buf = NULL; + + if (flag) + return ISO_STREAM_NO_CLONE; /* unknown option required */ + + *new_stream = NULL; + stream = calloc(1, sizeof(IsoStream)); + if (stream == NULL) + return ISO_OUT_OF_MEM; + stream->refcount = 1; + stream->class = old_stream->class; + new_data = calloc(1, sizeof(MemStreamData)); + if (new_data == NULL) { + free((char *) stream); + return ISO_OUT_OF_MEM; + } + data = (MemStreamData *) old_stream->data; + if (data->size > 0) { + new_buf = calloc(1, data->size); + if (new_buf == NULL) { + free((char *) stream); + free((char *) new_data); + return ISO_OUT_OF_MEM; + } + memcpy(new_buf, data->buf, data->size); + } + new_data->buf = new_buf; + new_data->offset = -1; + new_data->ino_id = mem_serial_id++; + new_data->size = data->size; + + stream->data = new_data; + *new_stream = stream; + return ISO_SUCCESS; +} + + IsoStreamIface mem_stream_class = { - 0, + 4, /* version */ "mem ", mem_open, mem_close, @@ -617,7 +756,12 @@ IsoStreamIface mem_stream_class = { mem_read, mem_is_repeatable, mem_get_id, - mem_free + mem_free, + mem_update_size, + mem_get_input_stream, + mem_cmp_ino, + mem_clone_stream + }; /** diff --git a/libisofs/tree.c b/libisofs/tree.c index d0558cf..4035439 100644 --- a/libisofs/tree.c +++ b/libisofs/tree.c @@ -997,6 +997,24 @@ char *iso_tree_get_node_path(IsoNode *node) /* ------------------------- tree cloning ------------------------------ */ +static +int iso_tree_copy_node_attr(IsoNode *old_node, IsoNode *new_node, int flag) +{ + int ret; + + new_node->mode = old_node->mode; + new_node->uid = old_node->uid; + new_node->gid = old_node->gid; + new_node->atime = old_node->atime; + new_node->mtime = old_node->mtime; + new_node->ctime = old_node->ctime; + new_node->hidden = old_node->hidden; + ret = iso_node_clone_xinfo(old_node, new_node, 0); + if (ret < 0) + return ret; + return ISO_SUCCESS; +} + static int iso_tree_clone_dir(IsoDir *old_dir, IsoDir *new_parent, char *new_name, IsoNode **new_node, @@ -1012,7 +1030,10 @@ int iso_tree_clone_dir(IsoDir *old_dir, ret = iso_tree_add_new_dir(new_parent, new_name, &new_dir); if (ret < 0) return ret; - *new_node = (IsoNode *) new_dir; + /* Avoid early grafting of directory to allow cloning of old_dir to a + subordinate of old_dir. + */ + iso_node_take((IsoNode *) new_dir); ret = iso_dir_get_children(old_dir, &iter); if (ret < 0) @@ -1026,6 +1047,13 @@ int iso_tree_clone_dir(IsoDir *old_dir, if (ret < 0) goto ex; } + + /* Now really graft in the new tree */ + ret = iso_dir_add_node(new_parent, (IsoNode *) new_dir, 0); + if (ret < 0) + goto ex; + + *new_node = (IsoNode *) new_dir; ret = ISO_SUCCESS; ex:; if (iter != NULL) @@ -1055,6 +1083,7 @@ int iso_tree_clone_file(IsoFile *old_file, ret = iso_tree_add_new_file(new_parent, new_name, new_stream, &new_file); if (ret < 0) goto ex; + new_stream = NULL; /* now owned by new_file */ new_file->sort_weight = old_file->sort_weight; *new_node = (IsoNode *) new_file; ret = ISO_SUCCESS; @@ -1064,6 +1093,47 @@ ex:; return ret; } +static +int iso_tree_clone_symlink(IsoSymlink *node, + IsoDir *new_parent, char *new_name, IsoNode **new_node, + int flag) +{ + IsoSymlink *new_sym; + int ret; + + *new_node = NULL; + + ret = iso_tree_add_new_symlink(new_parent, new_name, node->dest, &new_sym); + if (ret < 0) + return ret; + new_sym->fs_id = node->fs_id; + new_sym->st_dev = node->st_dev; + new_sym->st_ino = node->st_ino; + *new_node = (IsoNode *) new_sym; + return ISO_SUCCESS; +} + +static +int iso_tree_clone_special(IsoSpecial *node, + IsoDir *new_parent, char *new_name, IsoNode **new_node, + int flag) +{ + IsoSpecial *new_spec; + IsoNode *iso_node; + int ret; + + iso_node = (IsoNode *) node; + ret = iso_tree_add_new_special(new_parent, new_name, iso_node->mode, + node->dev, &new_spec); + if (ret < 0) + return ret; + new_spec->fs_id = node->fs_id; + new_spec->st_dev = node->st_dev; + new_spec->st_ino = node->st_ino; + *new_node = (IsoNode *) new_spec; + return ISO_SUCCESS; +} + /* API */ int iso_tree_clone(IsoNode *node, IsoDir *new_parent, char *new_name, IsoNode **new_node, @@ -1074,7 +1144,6 @@ int iso_tree_clone(IsoNode *node, if (iso_dir_get_node(new_parent, new_name, NULL) == 1) return ISO_NODE_NAME_NOT_UNIQUE; - /* >>> clone particular node types */; if (node->type == LIBISO_DIR) { ret = iso_tree_clone_dir((IsoDir *) node, new_parent, new_name, new_node, 0); @@ -1082,12 +1151,17 @@ int iso_tree_clone(IsoNode *node, ret = iso_tree_clone_file((IsoFile *) node, new_parent, new_name, new_node, 0); } else if (node->type == LIBISO_SYMLINK) { - /* >>> */; + ret = iso_tree_clone_symlink((IsoSymlink *) node, new_parent, new_name, + new_node, 0); } else if (node->type == LIBISO_SPECIAL) { - /* >>> */; + ret = iso_tree_clone_special((IsoSpecial *) node, new_parent, new_name, + new_node, 0); } else if (node->type == LIBISO_BOOT) { - ret = ISO_SUCCESS; /* API says they are silently ignored */ + ret = ISO_SUCCESS; /* API says they are silently ignored */ } + if (ret < 0) + return ret; + ret = iso_tree_copy_node_attr(node, *new_node, 0); return ret; } diff --git a/libisofs/util.h b/libisofs/util.h index 948aa0a..5f13db8 100644 --- a/libisofs/util.h +++ b/libisofs/util.h @@ -512,12 +512,26 @@ int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag); */ int checksum_cx_xinfo_func(void *data, int flag); +/* The iso_node_xinfo_cloner function which gets associated to + * checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via + * iso_node_xinfo_make_clonable() + */ +int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag); + + /* Function to identify and manage md5 sums of unspecified providence stored * directly in this xinfo. This is supposed to override any other recorded * MD5 of the node unless data get copied and checksummed during that copying. */ int checksum_md5_xinfo_func(void *data, int flag); +/* The iso_node_xinfo_cloner function which gets associated to + * checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via + * iso_node_xinfo_make_clonable() + */ +int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag); + + /* ------------------------------------------------------------------------- */