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.
This commit is contained in:
parent
032c5376ad
commit
aad05fd138
@ -25,6 +25,7 @@
|
|||||||
#include "archive/bz2_archive_plugin.h"
|
#include "archive/bz2_archive_plugin.h"
|
||||||
#include "archive_api.h"
|
#include "archive_api.h"
|
||||||
#include "input_plugin.h"
|
#include "input_plugin.h"
|
||||||
|
#include "refcount.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -40,6 +41,8 @@
|
|||||||
struct bz2_archive_file {
|
struct bz2_archive_file {
|
||||||
struct archive_file base;
|
struct archive_file base;
|
||||||
|
|
||||||
|
struct refcount ref;
|
||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
bool reset;
|
bool reset;
|
||||||
struct input_stream istream;
|
struct input_stream istream;
|
||||||
@ -105,6 +108,7 @@ bz2_open(const char *pathname, GError **error_r)
|
|||||||
|
|
||||||
context = g_malloc(sizeof(*context));
|
context = g_malloc(sizeof(*context));
|
||||||
archive_file_init(&context->base, &bz2_archive_plugin);
|
archive_file_init(&context->base, &bz2_archive_plugin);
|
||||||
|
refcount_init(&context->ref);
|
||||||
|
|
||||||
//open archive
|
//open archive
|
||||||
if (!input_stream_open(&context->istream, pathname, error_r)) {
|
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;
|
struct bz2_archive_file *context = (struct bz2_archive_file *) file;
|
||||||
|
|
||||||
|
if (!refcount_dec(&context->ref))
|
||||||
|
return;
|
||||||
|
|
||||||
g_free(context->name);
|
g_free(context->name);
|
||||||
|
|
||||||
input_stream_close(&context->istream);
|
input_stream_close(&context->istream);
|
||||||
@ -180,6 +187,8 @@ bz2_open_stream(struct archive_file *file, struct input_stream *is,
|
|||||||
|
|
||||||
bis->eof = false;
|
bis->eof = false;
|
||||||
|
|
||||||
|
refcount_inc(&context->ref);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "archive/iso9660_archive_plugin.h"
|
#include "archive/iso9660_archive_plugin.h"
|
||||||
#include "archive_api.h"
|
#include "archive_api.h"
|
||||||
#include "input_plugin.h"
|
#include "input_plugin.h"
|
||||||
|
#include "refcount.h"
|
||||||
|
|
||||||
#include <cdio/cdio.h>
|
#include <cdio/cdio.h>
|
||||||
#include <cdio/iso9660.h>
|
#include <cdio/iso9660.h>
|
||||||
@ -37,6 +38,8 @@
|
|||||||
struct iso9660_archive_file {
|
struct iso9660_archive_file {
|
||||||
struct archive_file base;
|
struct archive_file base;
|
||||||
|
|
||||||
|
struct refcount ref;
|
||||||
|
|
||||||
iso9660_t *iso;
|
iso9660_t *iso;
|
||||||
GSList *list;
|
GSList *list;
|
||||||
GSList *iter;
|
GSList *iter;
|
||||||
@ -93,6 +96,7 @@ iso9660_archive_open(const char *pathname, GError **error_r)
|
|||||||
g_new(struct iso9660_archive_file, 1);
|
g_new(struct iso9660_archive_file, 1);
|
||||||
|
|
||||||
archive_file_init(&context->base, &iso9660_archive_plugin);
|
archive_file_init(&context->base, &iso9660_archive_plugin);
|
||||||
|
refcount_init(&context->ref);
|
||||||
|
|
||||||
context->list = NULL;
|
context->list = NULL;
|
||||||
|
|
||||||
@ -139,8 +143,11 @@ iso9660_archive_close(struct archive_file *file)
|
|||||||
{
|
{
|
||||||
struct iso9660_archive_file *context =
|
struct iso9660_archive_file *context =
|
||||||
(struct iso9660_archive_file *)file;
|
(struct iso9660_archive_file *)file;
|
||||||
|
|
||||||
GSList *tmp;
|
GSList *tmp;
|
||||||
|
|
||||||
|
if (!refcount_dec(&context->ref))
|
||||||
|
return;
|
||||||
|
|
||||||
if (context->list) {
|
if (context->list) {
|
||||||
//free list
|
//free list
|
||||||
for (tmp = context->list; tmp != NULL; tmp = g_slist_next(tmp))
|
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;
|
is->size = iis->statbuf->size;
|
||||||
|
|
||||||
iis->max_blocks = CEILING(iis->statbuf->size, ISO_BLOCKSIZE);
|
iis->max_blocks = CEILING(iis->statbuf->size, ISO_BLOCKSIZE);
|
||||||
|
|
||||||
|
refcount_inc(&context->ref);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "archive_api.h"
|
#include "archive_api.h"
|
||||||
#include "archive_api.h"
|
#include "archive_api.h"
|
||||||
#include "input_plugin.h"
|
#include "input_plugin.h"
|
||||||
|
#include "refcount.h"
|
||||||
|
|
||||||
#include <zzip/zzip.h>
|
#include <zzip/zzip.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
@ -34,6 +35,8 @@
|
|||||||
struct zzip_archive {
|
struct zzip_archive {
|
||||||
struct archive_file base;
|
struct archive_file base;
|
||||||
|
|
||||||
|
struct refcount ref;
|
||||||
|
|
||||||
ZZIP_DIR *dir;
|
ZZIP_DIR *dir;
|
||||||
GSList *list;
|
GSList *list;
|
||||||
GSList *iter;
|
GSList *iter;
|
||||||
@ -56,6 +59,7 @@ zzip_archive_open(const char *pathname, GError **error_r)
|
|||||||
ZZIP_DIRENT dirent;
|
ZZIP_DIRENT dirent;
|
||||||
|
|
||||||
archive_file_init(&context->base, &zzip_archive_plugin);
|
archive_file_init(&context->base, &zzip_archive_plugin);
|
||||||
|
refcount_init(&context->ref);
|
||||||
|
|
||||||
// open archive
|
// open archive
|
||||||
context->list = NULL;
|
context->list = NULL;
|
||||||
@ -102,6 +106,10 @@ static void
|
|||||||
zzip_archive_close(struct archive_file *file)
|
zzip_archive_close(struct archive_file *file)
|
||||||
{
|
{
|
||||||
struct zzip_archive *context = (struct zzip_archive *) file;
|
struct zzip_archive *context = (struct zzip_archive *) file;
|
||||||
|
|
||||||
|
if (!refcount_dec(&context->ref))
|
||||||
|
return;
|
||||||
|
|
||||||
if (context->list) {
|
if (context->list) {
|
||||||
//free list
|
//free list
|
||||||
for (GSList *tmp = context->list; tmp != NULL; tmp = g_slist_next(tmp))
|
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);
|
zzip_file_stat(zis->file, &z_stat);
|
||||||
is->size = z_stat.st_size;
|
is->size = z_stat.st_size;
|
||||||
|
|
||||||
|
refcount_inc(&context->ref);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,9 +67,6 @@ struct archive_plugin {
|
|||||||
/**
|
/**
|
||||||
* Opens an input_stream of a file within the archive.
|
* 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 path the path within the archive
|
||||||
* @param error_r location to store the error occuring, or
|
* @param error_r location to store the error occuring, or
|
||||||
* NULL to ignore errors
|
* NULL to ignore errors
|
||||||
|
@ -67,12 +67,9 @@ input_archive_open(struct input_stream *is, const char *pathname,
|
|||||||
|
|
||||||
//setup fileops
|
//setup fileops
|
||||||
opened = archive_file_open_stream(file, is, filename, error_r);
|
opened = archive_file_open_stream(file, is, filename, error_r);
|
||||||
|
archive_file_close(file);
|
||||||
g_free(pname);
|
g_free(pname);
|
||||||
|
|
||||||
if (!opened) {
|
|
||||||
archive_file_close(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
return opened;
|
return opened;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user