From 68419703d7c81e318ab7f6e19b10bf57b97bb1d9 Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Sun, 7 Sep 2008 16:32:18 +0200 Subject: [PATCH] Added iso_image_update_sizes() API. This requires increasing IsoStreamIface version, as we need to add a new method on it. API/ABI remains compatible with older version. --- .settings/org.eclipse.cdt.core.prefs | 2 +- demo/iso.c | 18 +++++----- libisofs/image.c | 51 +++++++++++++++++++++----- libisofs/libisofs.h | 53 ++++++++++++++++++++++++++-- libisofs/stream.c | 35 ++++++++++++++++-- 5 files changed, 135 insertions(+), 24 deletions(-) diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs index e4c684e..763e6f6 100644 --- a/.settings/org.eclipse.cdt.core.prefs +++ b/.settings/org.eclipse.cdt.core.prefs @@ -1,4 +1,4 @@ -#Tue Aug 19 23:58:44 CEST 2008 +#Sat Sep 06 00:52:28 CEST 2008 eclipse.preferences.version=1 indexer/filesToParseUpFront= indexer/indexAllFiles=true diff --git a/demo/iso.c b/demo/iso.c index f3783b0..6a6bc84 100644 --- a/demo/iso.c +++ b/demo/iso.c @@ -91,7 +91,7 @@ int main(int argc, char **argv) break; } } - + if (argc < 2) { printf ("Please pass directory from which to build ISO\n"); usage(argv); @@ -102,7 +102,7 @@ int main(int argc, char **argv) usage(argv); return 1; } - + fd = fopen(argv[optind+1], "w"); if (!fd) { err(1, "error opening output file"); @@ -114,7 +114,7 @@ int main(int argc, char **argv) return 1; } iso_set_msgs_severities("NEVER", "ALL", ""); - + result = iso_image_new(volid, &image); if (result < 0) { printf ("Error creating image\n"); @@ -125,13 +125,13 @@ int main(int argc, char **argv) iso_tree_set_ignore_special(image, 0); iso_set_abort_severity("SORRY"); /*iso_tree_set_report_callback(image, callback);*/ - + result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[optind]); if (result < 0) { printf ("Error adding directory %d\n", result); return 1; } - + if (boot_img) { /* adds El-Torito boot info. Tunned for isolinux */ ElToritoBootImage *bootimg; @@ -154,22 +154,22 @@ int main(int argc, char **argv) iso_write_opts_set_rockridge(opts, rr); iso_write_opts_set_joliet(opts, j); iso_write_opts_set_iso1999(opts, iso1999); - + result = iso_image_create_burn_source(image, opts, &burn_src); if (result < 0) { printf ("Cant create image, error %d\n", result); return 1; } - + iso_write_opts_free(opts); - + while (burn_src->read_xt(burn_src, buf, 2048) == 2048) { fwrite(buf, 1, 2048, fd); } fclose(fd); burn_src->free_data(burn_src); free(burn_src); - + iso_image_unref(image); iso_finish(); return 0; diff --git a/libisofs/image.c b/libisofs/image.c index 4539ac9..b2fff23 100644 --- a/libisofs/image.c +++ b/libisofs/image.c @@ -1,8 +1,8 @@ /* * Copyright (c) 2007 Vreixo Formoso - * - * This file is part of the libisofs project; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 as + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See COPYING file for details. */ @@ -17,9 +17,9 @@ /** * Create a new image, empty. - * + * * The image will be owned by you and should be unref() when no more needed. - * + * * @param name * Name of the image. This will be used as volset_id and volume_id. * @param image @@ -85,7 +85,7 @@ void iso_image_ref(IsoImage *image) /** * Decrements the reference couting of the given image. - * If it reaches 0, the image is free, together with its tree nodes (whether + * If it reaches 0, the image is free, together with its tree nodes (whether * their refcount reach 0 too, of course). */ void iso_image_unref(IsoImage *image) @@ -125,7 +125,7 @@ void iso_image_unref(IsoImage *image) * Attach user defined data to the image. Use this if your application needs * to store addition info together with the IsoImage. If the image already * has data attached, the old data will be freed. - * + * * @param data * Pointer to application defined data that will be attached to the * image. You can pass NULL to remove any already attached data. @@ -139,7 +139,7 @@ int iso_image_attach_data(IsoImage *image, void *data, void (*give_up)(void*)) if (image == NULL || (data != NULL && free == NULL)) { return ISO_NULL_POINTER; } - + if (image->user_data != NULL) { /* free previously attached data */ if (image->user_data_free) { @@ -148,7 +148,7 @@ int iso_image_attach_data(IsoImage *image, void *data, void (*give_up)(void*)) image->user_data = NULL; image->user_data_free = NULL; } - + if (data != NULL) { image->user_data = data; image->user_data_free = give_up; @@ -275,3 +275,36 @@ int iso_image_get_msg_id(IsoImage *image) { return image->id; } + +static +int dir_update_size(IsoImage *image, IsoDir *dir) +{ + IsoNode *pos; + pos = dir->children; + while (pos) { + int ret = 1; + if (pos->type == LIBISO_FILE) { + ret = iso_stream_update_size(ISO_FILE(pos)->stream); + } else if (pos->type == LIBISO_DIR) { + /* recurse */ + ret = dir_update_size(image, ISO_DIR(pos)); + } + if (ret < 0) { + ret = iso_msg_submit(image->id, ret, 0, NULL); + if (ret < 0) { + return ret; /* cancel due error threshold */ + } + } + pos = pos->next; + } + return ISO_SUCCESS; +} + +int iso_image_update_sizes(IsoImage *image) +{ + if (image == NULL) { + return ISO_NULL_POINTER; + } + + return dir_update_size(image, image->root); +} diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 4a40923..7f19eb2 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -713,7 +713,12 @@ extern ino_t serial_id; */ struct IsoStream_Iface { - /* reserved for future usage, set to 0 */ + /* + * Current version of the interface, set to 1. + * + * -version 1 (since 0.6.8) + * update_size() added. + */ int version; /** @@ -743,7 +748,8 @@ struct IsoStream_Iface /** * Get the size (in bytes) of the stream. This function should always - * return the same size, even if the underlying source size changes. + * return the same size, even if the underlying source size changes, + * unless you call update_size() method. */ off_t (*get_size)(IsoStream *stream); @@ -785,6 +791,21 @@ struct IsoStream_Iface * Use iso_stream_unref() instead. */ 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(). + * + * @return + * 1 if ok, < 0 on error (has to be a valid libisofs error code) + * @since 0.6.8 + */ + int (*update_size)(IsoStream *stream); }; /** @@ -1318,6 +1339,20 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size); int iso_image_create_burn_source(IsoImage *image, IsoWriteOpts *opts, struct burn_source **burn_src); +/** + * Update the sizes of all files added to image. + * + * This may be called just before iso_image_create_burn_source() to force + * libisofs to check the file sizes again (they're already checked when added + * to IsoImage). It is useful if you have changed some files after adding then + * to the image. + * + * @return + * 1 on success, < 0 on error + * @since 0.6.8 + */ +int iso_image_update_sizes(IsoImage *image); + /** * Creates an IsoReadOpts for reading an existent image. You should set the * options desired with the correspondent setters. Note that you may want to @@ -3660,7 +3695,8 @@ int iso_stream_close(IsoStream *stream); /** * Get the size of a given stream. This function should always return the same - * size, even if the underlying source size changes. + * size, even if the underlying source size changes, unless you call + * iso_stream_update_size(). * * @return * IsoStream size in bytes @@ -3699,6 +3735,17 @@ int iso_stream_read(IsoStream *stream, void *buf, size_t count); */ int iso_stream_is_repeatable(IsoStream *stream); +/** + * Updates the size of the IsoStream with the current size of the + * underlying source. + * + * @return + * 1 if ok, < 0 on error (has to be a valid libisofs error code), + * 0 if the IsoStream does not support this function. + * @since 0.6.8 + */ +int iso_stream_update_size(IsoStream *stream); + /** * Get an unique identifier for a given IsoStream. * diff --git a/libisofs/stream.c b/libisofs/stream.c index 2f0a752..3a996e6 100644 --- a/libisofs/stream.c +++ b/libisofs/stream.c @@ -124,8 +124,28 @@ void fsrc_free(IsoStream *stream) free(data); } +static +int fsrc_update_size(IsoStream *stream) +{ + int ret; + struct stat info; + IsoFileSource *src; + + if (stream == NULL) { + return ISO_NULL_POINTER; + } + src = ((FSrcStreamData*)stream->data)->src; + ret = iso_file_source_stat(src, &info); + if (ret < 0) { + return ret; + } + + ((FSrcStreamData*)stream->data)->size = info.st_size; + return ISO_SUCCESS; +} + IsoStreamIface fsrc_stream_class = { - 0, + 1, /* update_size is defined for this stream */ "fsrc", fsrc_open, fsrc_close, @@ -133,7 +153,8 @@ IsoStreamIface fsrc_stream_class = { fsrc_read, fsrc_is_repeatable, fsrc_get_id, - fsrc_free + fsrc_free, + fsrc_update_size }; int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream) @@ -317,6 +338,9 @@ void cut_out_free(IsoStream *stream) free(data); } +/* + * TODO update cut out streams to deal with update_size(). Seems hard. + */ IsoStreamIface cut_out_stream_class = { 0, "cout", @@ -587,6 +611,13 @@ int iso_stream_is_repeatable(IsoStream *stream) return stream->class->is_repeatable(stream); } +inline +int iso_stream_update_size(IsoStream *stream) +{ + IsoStreamIface* class = stream->class; + return (class->version >= 1) ? class->update_size(stream) : 0; +} + inline void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id)