From aad05fd1386442330ecc0a15b86cf8081ea47c83 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 31 Dec 2009 10:02:55 +0100 Subject: [PATCH] archive: use reference counting for archive+input Make the input_stream implementation hold a reference on the archive_file object. Allow the caller to "close" the archive_file object immediately, no matter if the open_stream() method has succeeded or not. --- src/archive/bz2_archive_plugin.c | 9 +++++++++ src/archive/iso9660_archive_plugin.c | 12 +++++++++++- src/archive/zzip_archive_plugin.c | 11 +++++++++++ src/archive_plugin.h | 3 --- src/input/archive_input_plugin.c | 5 +---- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/archive/bz2_archive_plugin.c b/src/archive/bz2_archive_plugin.c index 975fd3f07..e4a5c3664 100644 --- a/src/archive/bz2_archive_plugin.c +++ b/src/archive/bz2_archive_plugin.c @@ -25,6 +25,7 @@ #include "archive/bz2_archive_plugin.h" #include "archive_api.h" #include "input_plugin.h" +#include "refcount.h" #include #include @@ -40,6 +41,8 @@ struct bz2_archive_file { struct archive_file base; + struct refcount ref; + char *name; bool reset; struct input_stream istream; @@ -105,6 +108,7 @@ bz2_open(const char *pathname, GError **error_r) context = g_malloc(sizeof(*context)); archive_file_init(&context->base, &bz2_archive_plugin); + refcount_init(&context->ref); //open archive if (!input_stream_open(&context->istream, pathname, error_r)) { @@ -149,6 +153,9 @@ bz2_close(struct archive_file *file) { struct bz2_archive_file *context = (struct bz2_archive_file *) file; + if (!refcount_dec(&context->ref)) + return; + g_free(context->name); input_stream_close(&context->istream); @@ -180,6 +187,8 @@ bz2_open_stream(struct archive_file *file, struct input_stream *is, bis->eof = false; + refcount_inc(&context->ref); + return true; } diff --git a/src/archive/iso9660_archive_plugin.c b/src/archive/iso9660_archive_plugin.c index 3d5f33896..0d32b9b1b 100644 --- a/src/archive/iso9660_archive_plugin.c +++ b/src/archive/iso9660_archive_plugin.c @@ -25,6 +25,7 @@ #include "archive/iso9660_archive_plugin.h" #include "archive_api.h" #include "input_plugin.h" +#include "refcount.h" #include #include @@ -37,6 +38,8 @@ struct iso9660_archive_file { struct archive_file base; + struct refcount ref; + iso9660_t *iso; GSList *list; GSList *iter; @@ -93,6 +96,7 @@ iso9660_archive_open(const char *pathname, GError **error_r) g_new(struct iso9660_archive_file, 1); archive_file_init(&context->base, &iso9660_archive_plugin); + refcount_init(&context->ref); context->list = NULL; @@ -139,8 +143,11 @@ iso9660_archive_close(struct archive_file *file) { struct iso9660_archive_file *context = (struct iso9660_archive_file *)file; - GSList *tmp; + + if (!refcount_dec(&context->ref)) + return; + if (context->list) { //free list for (tmp = context->list; tmp != NULL; tmp = g_slist_next(tmp)) @@ -192,6 +199,9 @@ iso9660_archive_open_stream(struct archive_file *file, struct input_stream *is, is->size = iis->statbuf->size; iis->max_blocks = CEILING(iis->statbuf->size, ISO_BLOCKSIZE); + + refcount_inc(&context->ref); + return true; } diff --git a/src/archive/zzip_archive_plugin.c b/src/archive/zzip_archive_plugin.c index fb7af74ed..755baff74 100644 --- a/src/archive/zzip_archive_plugin.c +++ b/src/archive/zzip_archive_plugin.c @@ -26,6 +26,7 @@ #include "archive_api.h" #include "archive_api.h" #include "input_plugin.h" +#include "refcount.h" #include #include @@ -34,6 +35,8 @@ struct zzip_archive { struct archive_file base; + struct refcount ref; + ZZIP_DIR *dir; GSList *list; GSList *iter; @@ -56,6 +59,7 @@ zzip_archive_open(const char *pathname, GError **error_r) ZZIP_DIRENT dirent; archive_file_init(&context->base, &zzip_archive_plugin); + refcount_init(&context->ref); // open archive context->list = NULL; @@ -102,6 +106,10 @@ static void zzip_archive_close(struct archive_file *file) { struct zzip_archive *context = (struct zzip_archive *) file; + + if (!refcount_dec(&context->ref)) + return; + if (context->list) { //free list for (GSList *tmp = context->list; tmp != NULL; tmp = g_slist_next(tmp)) @@ -151,6 +159,9 @@ zzip_archive_open_stream(struct archive_file *file, struct input_stream *is, zzip_file_stat(zis->file, &z_stat); is->size = z_stat.st_size; + + refcount_inc(&context->ref); + return true; } diff --git a/src/archive_plugin.h b/src/archive_plugin.h index 52629f2e1..b15320503 100644 --- a/src/archive_plugin.h +++ b/src/archive_plugin.h @@ -67,9 +67,6 @@ struct archive_plugin { /** * Opens an input_stream of a file within the archive. * - * If this function succeeds, then the #input_stream "owns" - * the archive file and will automatically close it. - * * @param path the path within the archive * @param error_r location to store the error occuring, or * NULL to ignore errors diff --git a/src/input/archive_input_plugin.c b/src/input/archive_input_plugin.c index 248b8626e..0409057bb 100644 --- a/src/input/archive_input_plugin.c +++ b/src/input/archive_input_plugin.c @@ -67,12 +67,9 @@ input_archive_open(struct input_stream *is, const char *pathname, //setup fileops opened = archive_file_open_stream(file, is, filename, error_r); + archive_file_close(file); g_free(pname); - if (!opened) { - archive_file_close(file); - } - return opened; }