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().
This commit is contained in:
Thomas Schmitt 2011-02-01 19:16:45 +01:00
parent 74c68224c7
commit 1082e628d1
15 changed files with 891 additions and 155 deletions

View File

@ -41,7 +41,7 @@
* for classical pipe filtering. * 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. * 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; IsoStream *new_input_stream, *stream;
ExternalFilterStreamData *stream_data, *old_stream_data; ExternalFilterStreamData *stream_data, *old_stream_data;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
stream_data = calloc(1, sizeof(ExternalFilterStreamData)); stream_data = calloc(1, sizeof(ExternalFilterStreamData));
if (stream_data == NULL) if (stream_data == NULL)
return ISO_OUT_OF_MEM; return ISO_OUT_OF_MEM;

View File

@ -154,7 +154,7 @@ static int gzip_compression_level = 6;
/* /*
* The data payload of an individual Gzip Filter IsoStream * 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 typedef struct
{ {
IsoStream *orig; IsoStream *orig;
@ -538,6 +538,9 @@ int gzip_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag)
IsoStream *new_input_stream, *stream; IsoStream *new_input_stream, *stream;
GzipFilterStreamData *stream_data, *old_stream_data; GzipFilterStreamData *stream_data, *old_stream_data;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
stream_data = calloc(1, sizeof(GzipFilterStreamData)); stream_data = calloc(1, sizeof(GzipFilterStreamData));
if (stream_data == NULL) if (stream_data == NULL)
return ISO_OUT_OF_MEM; return ISO_OUT_OF_MEM;

View File

@ -168,7 +168,7 @@ static int ziso_compression_level = 6;
/* /*
* The common data payload of an individual Zisofs Filter IsoStream * 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 typedef struct
{ {
@ -185,7 +185,7 @@ typedef struct
/* /*
* The data payload of an individual Zisofs Filter Compressor IsoStream * 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 typedef struct
{ {
@ -201,7 +201,7 @@ typedef struct
/* /*
* The data payload of an individual Zisofs Filter Uncompressor IsoStream * 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 typedef struct
{ {
@ -792,6 +792,9 @@ int ziso_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag)
ZisofsUncomprStreamData *uncompr, *old_uncompr; ZisofsUncomprStreamData *uncompr, *old_uncompr;
ZisofsComprStreamData *compr, *old_compr; ZisofsComprStreamData *compr, *old_compr;
if (flag)
return ISO_STREAM_NO_CLONE; /* unknown option required */
ret = iso_stream_clone_filter_common(old_stream, &stream, ret = iso_stream_clone_filter_common(old_stream, &stream,
&new_input_stream, 0); &new_input_stream, 0);
if (ret < 0) if (ret < 0)

View File

@ -317,7 +317,7 @@ typedef struct
typedef struct image_fs_data ImageFileSourceData; 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 struct image_fs_data
{ {
IsoImageFilesystem *fs; /**< reference to the image it belongs to */ 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; 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 = { IsoFileSourceIface ifs_class = {
1, /* version */ 2, /* version */
ifs_get_path, ifs_get_path,
ifs_get_name, ifs_get_name,
ifs_lstat, ifs_lstat,
@ -1061,7 +1138,8 @@ IsoFileSourceIface ifs_class = {
ifs_get_filesystem, ifs_get_filesystem,
ifs_free, ifs_free,
ifs_lseek, 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); 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, * Read the SUSP system user entries of the "." entry of the root directory,
* indentifying when Rock Ridge extensions are being used. * indentifying when Rock Ridge extensions are being used.

View File

@ -39,7 +39,7 @@ int iso_file_source_new_lfs(IsoFileSource *parent, const char *name,
*/ */
IsoFilesystem *lfs= NULL; IsoFilesystem *lfs= NULL;
/* IMPORTANT: Any change must be reflected by lfs_clone_src() */
typedef struct typedef struct
{ {
/** reference to the parent (if root it points to itself) */ /** reference to the parent (if root it points to itself) */
@ -534,10 +534,54 @@ ex:;
return ret; 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 = { IsoFileSourceIface lfs_class = {
1, /* version */ 2, /* version */
lfs_get_path, lfs_get_path,
lfs_get_name, lfs_get_name,
lfs_lstat, lfs_lstat,
@ -551,7 +595,8 @@ IsoFileSourceIface lfs_class = {
lfs_get_filesystem, lfs_get_filesystem,
lfs_free, lfs_free,
lfs_lseek, lfs_lseek,
lfs_get_aa_string lfs_get_aa_string,
lfs_clone_src
}; };

View File

@ -1,3 +1,7 @@
#ifndef LIBISO_LIBISOFS_H_
#define LIBISO_LIBISOFS_H_
/* /*
* Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic * Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic
* Copyright (c) 2009-2011 Thomas Schmitt * 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 <sys/stat.h> #include <sys/stat.h>
@ -502,6 +515,8 @@ struct IsoFileSource_Iface
* @since 0.6.2 * @since 0.6.2
* Version 1 additionally provides function *(get_aa_string)(). * Version 1 additionally provides function *(get_aa_string)().
* @since 0.6.14 * @since 0.6.14
* Version 2 additionally provides function *(clone_src)().
* @since 1.0.2
*/ */
int version; int version;
@ -736,6 +751,24 @@ struct IsoFileSource_Iface
int (*get_aa_string)(IsoFileSource *src, int (*get_aa_string)(IsoFileSource *src,
unsigned char **aa_string, int flag); 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. * TODO #00004 Add a get_mime_type() function.
* This can be useful for GUI apps, to choose the icon of the file * 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 /* ! Libisofs_h_as_cpluspluS */
#endif /* ! __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 * Representation of file contents. It is an stream of bytes, functionally
* like a pipe. * like a pipe.
@ -795,6 +853,7 @@ extern ino_t serial_id;
* *
* @since 0.6.4 * @since 0.6.4
*/ */
struct IsoStream_Iface struct IsoStream_Iface
{ {
/* /*
@ -851,7 +910,7 @@ struct IsoStream_Iface
off_t (*get_size)(IsoStream *stream); 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 * the buffer starting at buf. The implementation has to make sure that
* either the full desired count of bytes is delivered or that the * either the full desired count of bytes is delivered or that the
* next call to this function will return EOF or error. * 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); int (*read)(IsoStream *stream, void *buf, size_t count);
/** /**
* Whether this IsoStream can be read several times, with the same results. * Tell whether this IsoStream can be read several times, with the same
* For example, a regular file is repeatable, you can read it as many * results. For example, a regular file is repeatable, you can read it
* times as you want. However, a pipe isn't. * as many times as you want. However, a pipe is not.
*
* This function doesn't take into account if the file has been modified
* between the two reads.
* *
* @return * @return
* 1 if stream is repeatable, 0 if not, * 1 if stream is repeatable, 0 if not,
@ -893,13 +949,13 @@ struct IsoStream_Iface
void (*free)(IsoStream *stream); void (*free)(IsoStream *stream);
/** /**
* Updates the size of the IsoStream with the current size of the * Update the size of the IsoStream with the current size of the underlying
* underlying source. After calling this, get_size() will return * source, if the source is prone to size changes. After calling this,
* the new size. This should never be called after * get_size() shall eventually return the new size.
* iso_image_create_burn_source() was called and the image was not * This will never be called after iso_image_create_burn_source() was
* completely written. To update the size of all files before written the * called and before the image was completely written.
* image, you may want to call iso_image_update_sizes() just before * (The API call to update the size of all files in the image is
* iso_image_create_burn_source(). * iso_image_update_sizes()).
* *
* @return * @return
* 1 if ok, < 0 on error (has to be a valid libisofs error code) * 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); 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 * @param stream
* The eventual filter stream to be inquired. * The eventual filter stream to be inquired.
@ -918,7 +974,7 @@ struct IsoStream_Iface
* Bitfield for control purposes. 0 means normal behavior. * Bitfield for control purposes. 0 means normal behavior.
* @return * @return
* The input stream, if one exists. Elsewise NULL. * 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 * @since 0.6.18
* Present if .version is 2 or higher. * Present if .version is 2 or higher.
@ -978,6 +1034,9 @@ struct IsoStream_Iface
* Will return a pointer to the copy * Will return a pointer to the copy
* @param flag * @param flag
* Bitfield for control purposes. 0 means normal behavior. * 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 * @since 1.0.2
* Present if .version is 4 or higher. * 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); enum IsoNodeType iso_node_get_type(IsoNode *node);
/** /**
* Function to handle particular extended information. The function * Class of functions to handle particular extended information. A function
* pointer acts as an identifier for the type of the information. Structs * instance acts as an identifier for the type of the information. Structs
* with same information type must use the same function. * with same information type must use a pointer to the same function.
* *
* @param data * @param data
* Attached 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); 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 * Get the given extended info (defined by the proc function) from the
* given node. * 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); 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 * 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. * 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(). * clone_stream().
* Surely clonable node types are: * Surely clonable node types are:
* IsoDir, * IsoDir,
* >>> IsoSymlink, * IsoSymlink,
* >>> IsoSpecial, * IsoSpecial,
* IsoFile from a loaded ISO image without filter streams, * IsoFile from a loaded ISO image,
* >>> IsoFile referring to local filesystem files without filter streams. * 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. * 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. * 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_zisofs_filter()
* iso_file_add_gzip_filter() * iso_file_add_gzip_filter()
* iso_file_add_external_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 * @param node
* The node to be cloned. * 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); 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. * 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) */ (FAILURE, HIGH, -374) */
#define ISO_STREAM_NO_CLONE 0xE830FE8A #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: /* Internal developer note:
Place new error codes directly above this comment. Place new error codes directly above this comment.
Newly introduced errors must get a message entry in Newly introduced errors must get a message entry in

View File

@ -1,5 +1,6 @@
LIBISOFS6 { LIBISOFS6 {
global: global:
aaip_xinfo_cloner;
aaip_xinfo_func; aaip_xinfo_func;
el_torito_get_bootable; el_torito_get_bootable;
el_torito_get_boot_media_type; el_torito_get_boot_media_type;
@ -156,6 +157,7 @@ iso_node_get_hidden;
iso_node_get_mode; iso_node_get_mode;
iso_node_get_mtime; iso_node_get_mtime;
iso_node_get_name; iso_node_get_name;
iso_node_get_next_xinfo;
iso_node_get_old_image_lba; iso_node_get_old_image_lba;
iso_node_get_parent; iso_node_get_parent;
iso_node_get_permissions; iso_node_get_permissions;
@ -166,6 +168,7 @@ iso_node_get_xinfo;
iso_node_lookup_attr; iso_node_lookup_attr;
iso_node_ref; iso_node_ref;
iso_node_remove; iso_node_remove;
iso_node_remove_all_xinfo;
iso_node_remove_tree; iso_node_remove_tree;
iso_node_remove_xinfo; iso_node_remove_xinfo;
iso_node_set_acl_text; iso_node_set_acl_text;
@ -181,6 +184,8 @@ iso_node_set_sort_weight;
iso_node_set_uid; iso_node_set_uid;
iso_node_take; iso_node_take;
iso_node_unref; iso_node_unref;
iso_node_xinfo_get_cloner;
iso_node_xinfo_make_clonable;
iso_node_zf_by_magic; iso_node_zf_by_magic;
iso_obtain_msgs; iso_obtain_msgs;
iso_read_image_features_destroy; iso_read_image_features_destroy;

View File

@ -424,6 +424,22 @@ int checksum_cx_xinfo_func(void *data, int flag)
return 1; 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 /* Function to identify and manage md5 sums of unspecified providence stored
* directly in this xinfo. * directly in this xinfo.
@ -436,6 +452,24 @@ int checksum_md5_xinfo_func(void *data, int flag)
return 1; 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;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */

View File

@ -37,6 +37,7 @@
#include "messages.h" #include "messages.h"
#include "util.h" #include "util.h"
#include "node.h"
/* /*
@ -80,11 +81,69 @@ int abort_threshold = LIBISO_MSGS_SEV_FAILURE;
struct libiso_msgs *libiso_msgr = NULL; 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 @param flag bit0= do not set up locale by LC_* environment variables
*/ */
int iso_init_with_flag(int flag) int iso_init_with_flag(int flag)
{ {
int ret;
#ifdef Libisofs_with_libjtE #ifdef Libisofs_with_libjtE
@ -120,7 +179,6 @@ LIBJTE_MISCONFIGURATION_ = 0;
#endif /* Libisofs_with_libjtE */ #endif /* Libisofs_with_libjtE */
if (! (flag & 1)) { if (! (flag & 1)) {
iso_init_locale(0); iso_init_locale(0);
} }
@ -130,10 +188,29 @@ LIBJTE_MISCONFIGURATION_ = 0;
} }
libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER, libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER,
LIBISO_MSGS_SEV_FATAL, "libisofs: ", 0); 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; return 1;
} }
int iso_init() int iso_init()
{ {
return iso_init_with_flag(0); return iso_init_with_flag(0);
@ -142,6 +219,7 @@ int iso_init()
void iso_finish() void iso_finish()
{ {
libiso_msgs_destroy(&libiso_msgr, 0); libiso_msgs_destroy(&libiso_msgr, 0);
iso_node_xinfo_dispose_cloners(0);
} }
int iso_set_abort_severity(char *severity) 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"; return "File name cannot be written into ECMA-119 untranslated";
case ISO_STREAM_NO_CLONE: case ISO_STREAM_NO_CLONE:
return "Data file input stream object offers no cloning method"; return "Data file input stream object offers no cloning method";
case ISO_XINFO_NO_CLONE:
return "Extended information class offers no cloning method";
default: default:
return "Unknown error"; return "Unknown error";
} }

View File

@ -226,6 +226,77 @@ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
return 0; 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. * Get the type of an IsoNode.
*/ */
@ -651,6 +722,9 @@ int iso_node_take(IsoNode *node)
if (dir == NULL) { if (dir == NULL) {
return ISO_NODE_NOT_ADDED_TO_DIR; return ISO_NODE_NOT_ADDED_TO_DIR;
} }
/* >>> Do not take root directory ! (dir == node) ? */;
pos = iso_dir_find_node(dir, node); pos = iso_dir_find_node(dir, node);
if (pos == NULL) { if (pos == NULL) {
/* should never occur */ /* should never occur */
@ -694,6 +768,9 @@ int iso_node_remove_tree(IsoNode *node, IsoDirIter *boss_iter)
int ret; int ret;
if (node->type != LIBISO_DIR) { if (node->type != LIBISO_DIR) {
/* >>> Do not remove root directory ! (node->parent == node) ? */;
ret = iso_dir_get_children((IsoDir *) node, &iter); ret = iso_dir_get_children((IsoDir *) node, &iter);
if (ret < 0) if (ret < 0)
goto ex; goto ex;
@ -705,6 +782,11 @@ int iso_node_remove_tree(IsoNode *node, IsoDirIter *boss_iter)
if (ret < 0) if (ret < 0)
goto ex; goto ex;
} }
if (node->parent == NULL) {
/* node is not grafted into a boss directory */
iso_node_unref(node);
goto ex;
}
} }
if (boss_iter != NULL) if (boss_iter != NULL)
ret = iso_dir_iter_remove(boss_iter); ret = iso_dir_iter_remove(boss_iter);
@ -2183,6 +2265,23 @@ int zisofs_zf_xinfo_func(void *data, int flag)
return 1; 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 /* 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. * 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; 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 * @param flag
@ -2394,7 +2508,6 @@ int iso_node_set_ino_xinfo(IsoNode *node, ino_t ino, int flag)
return ret; return ret;
} }
int iso_node_set_ino(IsoNode *node, ino_t ino, int flag) int iso_node_set_ino(IsoNode *node, ino_t ino, int flag)
{ {
int ret; int ret;

View File

@ -482,4 +482,35 @@ int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba,
int flag); 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_*/ #endif /*LIBISO_NODE_H_*/

View File

@ -905,7 +905,7 @@ int add_zf_field(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
return 1; return 1;
} }
/* API */
int aaip_xinfo_func(void *data, int flag) int aaip_xinfo_func(void *data, int flag)
{ {
if (flag & 1) { if (flag & 1) {
@ -914,6 +914,23 @@ int aaip_xinfo_func(void *data, int flag)
return 1; 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 * Compute SUA length and eventual Continuation Area length of field NM and

View File

@ -157,20 +157,18 @@ int fsrc_update_size(IsoStream *stream)
return ISO_SUCCESS; return ISO_SUCCESS;
} }
static
IsoStream *fsrc_get_input_stream(IsoStream *stream, int flag) IsoStream *fsrc_get_input_stream(IsoStream *stream, int flag)
{ {
return NULL; return NULL;
} }
static
int fsrc_cmp_ino(IsoStream *s1, IsoStream *s2) int fsrc_cmp_ino(IsoStream *s1, IsoStream *s2)
{ {
int ret; int ret;
/* <<< provisory */
ret = iso_stream_cmp_ino(s1, s2, 1); ret = iso_stream_cmp_ino(s1, s2, 1);
/* >>> find out whether both streams point to the same image file */;
return ret; return ret;
} }
@ -181,6 +179,13 @@ int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
IsoStream *stream; IsoStream *stream;
int ret; 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; *new_stream = NULL;
stream = calloc(1, sizeof(IsoStream)); stream = calloc(1, sizeof(IsoStream));
if (stream == NULL) if (stream == NULL)
@ -191,12 +196,11 @@ int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
return ISO_OUT_OF_MEM; return ISO_OUT_OF_MEM;
} }
*new_stream = stream; *new_stream = stream;
data = (FSrcStreamData*) old_stream->data;
stream->class = old_stream->class; stream->class = old_stream->class;
stream->refcount = 1; stream->refcount = 1;
stream->data = new_data; 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) { if (ret < 0) {
free((char *) stream); free((char *) stream);
free((char *) new_data); free((char *) new_data);
@ -210,7 +214,7 @@ int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
} }
IsoStreamIface fsrc_stream_class = { IsoStreamIface fsrc_stream_class = {
4, /* .clone_stream() is defined for this stream */ 4, /* version */
"fsrc", "fsrc",
fsrc_open, fsrc_open,
fsrc_close, fsrc_close,
@ -430,11 +434,76 @@ void cut_out_free(IsoStream *stream)
free(data); 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. * TODO update cut out streams to deal with update_size(). Seems hard.
*/ */
IsoStreamIface cut_out_stream_class = { IsoStreamIface cut_out_stream_class = {
0, 4, /* version */
"cout", "cout",
cut_out_open, cut_out_open,
cut_out_close, cut_out_close,
@ -442,7 +511,12 @@ IsoStreamIface cut_out_stream_class = {
cut_out_read, cut_out_read,
cut_out_is_repeatable, cut_out_is_repeatable,
cut_out_get_id, 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, 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; MemStreamData *data;
data = (MemStreamData*)stream->data; data = (MemStreamData*)stream->data;
free(data->buf); if (data->buf != NULL)
free(data->buf);
free(data); 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 = { IsoStreamIface mem_stream_class = {
0, 4, /* version */
"mem ", "mem ",
mem_open, mem_open,
mem_close, mem_close,
@ -617,7 +756,12 @@ IsoStreamIface mem_stream_class = {
mem_read, mem_read,
mem_is_repeatable, mem_is_repeatable,
mem_get_id, mem_get_id,
mem_free mem_free,
mem_update_size,
mem_get_input_stream,
mem_cmp_ino,
mem_clone_stream
}; };
/** /**

View File

@ -997,6 +997,24 @@ char *iso_tree_get_node_path(IsoNode *node)
/* ------------------------- tree cloning ------------------------------ */ /* ------------------------- 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 static
int iso_tree_clone_dir(IsoDir *old_dir, int iso_tree_clone_dir(IsoDir *old_dir,
IsoDir *new_parent, char *new_name, IsoNode **new_node, 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); ret = iso_tree_add_new_dir(new_parent, new_name, &new_dir);
if (ret < 0) if (ret < 0)
return ret; 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); ret = iso_dir_get_children(old_dir, &iter);
if (ret < 0) if (ret < 0)
@ -1026,6 +1047,13 @@ int iso_tree_clone_dir(IsoDir *old_dir,
if (ret < 0) if (ret < 0)
goto ex; 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; ret = ISO_SUCCESS;
ex:; ex:;
if (iter != NULL) 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); ret = iso_tree_add_new_file(new_parent, new_name, new_stream, &new_file);
if (ret < 0) if (ret < 0)
goto ex; goto ex;
new_stream = NULL; /* now owned by new_file */
new_file->sort_weight = old_file->sort_weight; new_file->sort_weight = old_file->sort_weight;
*new_node = (IsoNode *) new_file; *new_node = (IsoNode *) new_file;
ret = ISO_SUCCESS; ret = ISO_SUCCESS;
@ -1064,6 +1093,47 @@ ex:;
return ret; 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 */ /* API */
int iso_tree_clone(IsoNode *node, int iso_tree_clone(IsoNode *node,
IsoDir *new_parent, char *new_name, IsoNode **new_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) if (iso_dir_get_node(new_parent, new_name, NULL) == 1)
return ISO_NODE_NAME_NOT_UNIQUE; return ISO_NODE_NAME_NOT_UNIQUE;
/* >>> clone particular node types */;
if (node->type == LIBISO_DIR) { if (node->type == LIBISO_DIR) {
ret = iso_tree_clone_dir((IsoDir *) node, new_parent, new_name, ret = iso_tree_clone_dir((IsoDir *) node, new_parent, new_name,
new_node, 0); new_node, 0);
@ -1082,12 +1151,17 @@ int iso_tree_clone(IsoNode *node,
ret = iso_tree_clone_file((IsoFile *) node, new_parent, new_name, ret = iso_tree_clone_file((IsoFile *) node, new_parent, new_name,
new_node, 0); new_node, 0);
} else if (node->type == LIBISO_SYMLINK) { } 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) { } 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) { } 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; return ret;
} }

View File

@ -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); 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 /* Function to identify and manage md5 sums of unspecified providence stored
* directly in this xinfo. This is supposed to override any other recorded * 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. * MD5 of the node unless data get copied and checksummed during that copying.
*/ */
int checksum_md5_xinfo_func(void *data, int flag); 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);
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */