diff options
Diffstat (limited to '')
-rw-r--r-- | src/archive/bz2_archive_plugin.c (renamed from src/archive/bz2_plugin.c) | 174 | ||||
-rw-r--r-- | src/archive/bz2_archive_plugin.h (renamed from src/input/lastfm_input_plugin.h) | 6 | ||||
-rw-r--r-- | src/archive/iso9660_archive_plugin.c (renamed from src/archive/iso_plugin.c) | 107 | ||||
-rw-r--r-- | src/archive/iso9660_archive_plugin.h | 25 | ||||
-rw-r--r-- | src/archive/zzip_archive_plugin.c (renamed from src/archive/zip_plugin.c) | 104 | ||||
-rw-r--r-- | src/archive/zzip_archive_plugin.h | 25 | ||||
-rw-r--r-- | src/archive_api.c | 5 | ||||
-rw-r--r-- | src/archive_api.h | 63 | ||||
-rw-r--r-- | src/archive_internal.h | 9 | ||||
-rw-r--r-- | src/archive_list.c | 42 | ||||
-rw-r--r-- | src/archive_list.h | 2 | ||||
-rw-r--r-- | src/archive_plugin.c | 92 | ||||
-rw-r--r-- | src/archive_plugin.h | 109 |
13 files changed, 497 insertions, 266 deletions
diff --git a/src/archive/bz2_plugin.c b/src/archive/bz2_archive_plugin.c index 0ef042e90..b3a9027af 100644 --- a/src/archive/bz2_plugin.c +++ b/src/archive/bz2_archive_plugin.c @@ -21,9 +21,10 @@ * single bz2 archive handling (requires libbz2) */ +#include "config.h" +#include "archive/bz2_archive_plugin.h" #include "archive_api.h" #include "input_plugin.h" -#include "config.h" #include <stdint.h> #include <stddef.h> @@ -32,30 +33,40 @@ #include <bzlib.h> #ifdef HAVE_OLDER_BZIP2 -#define BZ2_bzDecompressInit bzDecompressInit -#define BZ2_bzDecompress bzDecompress +#define BZ2_bzDecompressInit bzDecompressInit +#define BZ2_bzDecompress bzDecompress #endif #define BZ_BUFSIZE 5000 -typedef struct { - char *name; - bool reset; +struct bz2_archive_file { + struct archive_file base; + + char *name; + bool reset; struct input_stream istream; - int last_bz_result; - int last_parent_result; - bz_stream bzstream; - char *buffer; -} bz2_context; + bool eof; + + bz_stream bzstream; + char *buffer; +}; static const struct input_plugin bz2_inputplugin; +static inline GQuark +bz2_quark(void) +{ + return g_quark_from_static_string("bz2"); +} + /* single archive handling allocation helpers */ static bool -bz2_alloc(bz2_context *data) +bz2_alloc(struct bz2_archive_file *data, GError **error_r) { + int ret; + data->bzstream.bzalloc = NULL; data->bzstream.bzfree = NULL; data->bzstream.opaque = NULL; @@ -64,19 +75,21 @@ bz2_alloc(bz2_context *data) data->bzstream.next_in = (void *) data->buffer; data->bzstream.avail_in = 0; - if (BZ2_bzDecompressInit(&data->bzstream, 0, 0) != BZ_OK) { + ret = BZ2_bzDecompressInit(&data->bzstream, 0, 0); + if (ret != BZ_OK) { g_free(data->buffer); g_free(data); + + g_set_error(error_r, bz2_quark(), ret, + "BZ2_bzDecompressInit() has failed"); return false; } - data->last_bz_result = BZ_OK; - data->last_parent_result = 0; return true; } static void -bz2_destroy(bz2_context *data) +bz2_destroy(struct bz2_archive_file *data) { BZ2_bzDecompressEnd(&data->bzstream); g_free(data->buffer); @@ -85,61 +98,56 @@ bz2_destroy(bz2_context *data) /* archive open && listing routine */ static struct archive_file * -bz2_open(char * pathname) +bz2_open(const char *pathname, GError **error_r) { - bz2_context *context; - char *name; + struct bz2_archive_file *context; int len; - context = g_malloc(sizeof(bz2_context)); - if (!context) { - return NULL; - } + context = g_malloc(sizeof(*context)); + archive_file_init(&context->base, &bz2_archive_plugin); + //open archive - if (!input_stream_open(&context->istream, pathname)) { - g_warning("failed to open an bzip2 archive %s\n",pathname); - g_free(context); - return NULL; - } - //capture filename - name = strrchr(pathname, '/'); - if (name == NULL) { - g_warning("failed to get bzip2 name from %s\n",pathname); + if (!input_stream_open(&context->istream, pathname, error_r)) { g_free(context); return NULL; } - context->name = g_strdup(name+1); + + context->name = g_path_get_basename(pathname); + //remove suffix len = strlen(context->name); if (len > 4) { - context->name[len-4] = 0; //remove .bz2 suffix + context->name[len - 4] = 0; //remove .bz2 suffix } - return (struct archive_file *) context; + + return &context->base; } static void bz2_scan_reset(struct archive_file *file) { - bz2_context *context = (bz2_context *) file; + struct bz2_archive_file *context = (struct bz2_archive_file *) file; context->reset = true; } static char * bz2_scan_next(struct archive_file *file) { - bz2_context *context = (bz2_context *) file; + struct bz2_archive_file *context = (struct bz2_archive_file *) file; char *name = NULL; + if (context->reset) { name = context->name; context->reset = false; } + return name; } static void bz2_close(struct archive_file *file) { - bz2_context *context = (bz2_context *) file; + struct bz2_archive_file *context = (struct bz2_archive_file *) file; g_free(context->name); @@ -151,35 +159,36 @@ bz2_close(struct archive_file *file) static bool bz2_open_stream(struct archive_file *file, struct input_stream *is, - G_GNUC_UNUSED const char *path) + G_GNUC_UNUSED const char *path, GError **error_r) { - bz2_context *context = (bz2_context *) file; + struct bz2_archive_file *context = (struct bz2_archive_file *) file; + //setup file ops is->plugin = &bz2_inputplugin; //insert back reference is->data = context; is->seekable = false; - if (!bz2_alloc(context)) { - g_warning("alloc bz2 failed\n"); + if (!bz2_alloc(context, error_r)) return false; - } + + context->eof = false; + return true; } static void bz2_is_close(struct input_stream *is) { - bz2_context *context = (bz2_context *) is->data; + struct bz2_archive_file *context = (struct bz2_archive_file *) is->data; bz2_destroy(context); is->data = NULL; bz2_close((struct archive_file *)context); } -static int -bz2_fillbuffer(bz2_context *context, - size_t numBytes) +static bool +bz2_fillbuffer(struct bz2_archive_file *context, GError **error_r) { size_t count; bz_stream *bzstream; @@ -187,76 +196,65 @@ bz2_fillbuffer(bz2_context *context, bzstream = &context->bzstream; if (bzstream->avail_in > 0) - return 0; + return true; count = input_stream_read(&context->istream, - context->buffer, BZ_BUFSIZE); - - if (count == 0) { - if (bzstream->avail_out == numBytes) - return -1; - if (!input_stream_eof(&context->istream)) - context->last_parent_result = 1; - } else { - bzstream->next_in = context->buffer; - bzstream->avail_in = count; - } + context->buffer, BZ_BUFSIZE, + error_r); + if (count == 0) + return false; - return 0; + bzstream->next_in = context->buffer; + bzstream->avail_in = count; + return true; } static size_t -bz2_is_read(struct input_stream *is, void *ptr, size_t size) +bz2_is_read(struct input_stream *is, void *ptr, size_t length, + GError **error_r) { - bz2_context *context = (bz2_context *) is->data; + struct bz2_archive_file *context = (struct bz2_archive_file *) is->data; bz_stream *bzstream; int bz_result; - size_t numBytes = size; - size_t bytesRead = 0; + size_t nbytes = 0; - if (context->last_bz_result != BZ_OK) - return 0; - if (context->last_parent_result != 0) + if (context->eof) return 0; bzstream = &context->bzstream; bzstream->next_out = ptr; - bzstream->avail_out = numBytes; + bzstream->avail_out = length; - while (bzstream->avail_out != 0) { - if (bz2_fillbuffer(context, numBytes) != 0) - break; + do { + if (!bz2_fillbuffer(context, error_r)) + return 0; bz_result = BZ2_bzDecompress(bzstream); - if (context->last_bz_result != BZ_OK - && bzstream->avail_out == numBytes) { - context->last_bz_result = bz_result; + if (bz_result == BZ_STREAM_END) { + context->eof = true; break; } - if (bz_result == BZ_STREAM_END) { - context->last_bz_result = bz_result; - break; + if (bz_result != BZ_OK) { + g_set_error(error_r, bz2_quark(), bz_result, + "BZ2_bzDecompress() has failed"); + return 0; } - } + } while (bzstream->avail_out == length); - bytesRead = numBytes - bzstream->avail_out; - is->offset += bytesRead; + nbytes = length - bzstream->avail_out; + is->offset += nbytes; - return bytesRead; + return nbytes; } static bool bz2_is_eof(struct input_stream *is) { - bz2_context *context = (bz2_context *) is->data; - - if (context->last_bz_result == BZ_STREAM_END) { - return true; - } + struct bz2_archive_file *context = (struct bz2_archive_file *) is->data; - return false; + return context->eof; } /* exported structures */ @@ -272,7 +270,7 @@ static const struct input_plugin bz2_inputplugin = { .eof = bz2_is_eof, }; -const struct archive_plugin bz2_plugin = { +const struct archive_plugin bz2_archive_plugin = { .name = "bz2", .open = bz2_open, .scan_reset = bz2_scan_reset, diff --git a/src/input/lastfm_input_plugin.h b/src/archive/bz2_archive_plugin.h index d0eaf5a55..42b0c48ed 100644 --- a/src/input/lastfm_input_plugin.h +++ b/src/archive/bz2_archive_plugin.h @@ -17,9 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef LASTFM_INPUT_PLUGIN_H -#define LASTFM_INPUT_PLUGIN_H +#ifndef MPD_ARCHIVE_BZ2_H +#define MPD_ARCHIVE_BZ2_H -extern const struct input_plugin lastfm_input_plugin; +extern const struct archive_plugin bz2_archive_plugin; #endif diff --git a/src/archive/iso_plugin.c b/src/archive/iso9660_archive_plugin.c index 9063af0fc..780268df8 100644 --- a/src/archive/iso_plugin.c +++ b/src/archive/iso9660_archive_plugin.c @@ -21,6 +21,8 @@ * iso archive handling (requires cdio, and iso9660) */ +#include "config.h" +#include "archive/iso9660_archive_plugin.h" #include "archive_api.h" #include "input_plugin.h" @@ -32,21 +34,29 @@ #define CEILING(x, y) ((x+(y-1))/y) -typedef struct { +struct iso9660_archive_file { + struct archive_file base; + iso9660_t *iso; iso9660_stat_t *statbuf; size_t cur_ofs; size_t max_blocks; GSList *list; GSList *iter; -} iso_context; +}; + +static const struct input_plugin iso9660_input_plugin; -static const struct input_plugin iso_inputplugin; +static inline GQuark +iso9660_quark(void) +{ + return g_quark_from_static_string("iso9660"); +} /* archive open && listing routine */ static void -listdir_recur(const char *psz_path, iso_context *context) +listdir_recur(const char *psz_path, struct iso9660_archive_file *context) { iso9660_t *iso = context->iso; CdioList_t *entlist; @@ -80,36 +90,44 @@ listdir_recur(const char *psz_path, iso_context *context) } static struct archive_file * -iso_open(char * pathname) +iso9660_archive_open(const char *pathname, GError **error_r) { - iso_context *context = g_malloc(sizeof(iso_context)); + struct iso9660_archive_file *context = + g_new(struct iso9660_archive_file, 1); + + archive_file_init(&context->base, &iso9660_archive_plugin); context->list = NULL; /* open archive */ context->iso = iso9660_open (pathname); if (context->iso == NULL) { - g_warning("iso %s open failed\n", pathname); + g_set_error(error_r, iso9660_quark(), 0, + "Failed to open ISO9660 file %s", pathname); return NULL; } listdir_recur("/", context); - return (struct archive_file *)context; + return &context->base; } static void -iso_scan_reset(struct archive_file *file) +iso9660_archive_scan_reset(struct archive_file *file) { - iso_context *context = (iso_context *) file; + struct iso9660_archive_file *context = + (struct iso9660_archive_file *)file; + //reset iterator context->iter = context->list; } static char * -iso_scan_next(struct archive_file *file) +iso9660_archive_scan_next(struct archive_file *file) { - iso_context *context = (iso_context *) file; + struct iso9660_archive_file *context = + (struct iso9660_archive_file *)file; + char *data = NULL; if (context->iter != NULL) { ///fetch data and goto next @@ -120,9 +138,11 @@ iso_scan_next(struct archive_file *file) } static void -iso_close(struct archive_file *file) +iso9660_archive_close(struct archive_file *file) { - iso_context *context = (iso_context *) file; + struct iso9660_archive_file *context = + (struct iso9660_archive_file *)file; + GSList *tmp; if (context->list) { //free list @@ -139,12 +159,14 @@ iso_close(struct archive_file *file) /* single archive handling */ static bool -iso_open_stream(struct archive_file *file, struct input_stream *is, - const char *pathname) +iso9660_archive_open_stream(struct archive_file *file, struct input_stream *is, + const char *pathname, GError **error_r) { - iso_context *context = (iso_context *) file; + struct iso9660_archive_file *context = + (struct iso9660_archive_file *)file; + //setup file ops - is->plugin = &iso_inputplugin; + is->plugin = &iso9660_input_plugin; //insert back reference is->data = context; //we are not seekable @@ -153,7 +175,8 @@ iso_open_stream(struct archive_file *file, struct input_stream *is, context->statbuf = iso9660_ifs_stat_translate (context->iso, pathname); if (context->statbuf == NULL) { - g_warning("file %s not found in iso\n", pathname); + g_set_error(error_r, iso9660_quark(), 0, + "not found in the ISO file: %s", pathname); return false; } context->cur_ofs = 0; @@ -162,19 +185,19 @@ iso_open_stream(struct archive_file *file, struct input_stream *is, } static void -iso_is_close(struct input_stream *is) +iso9660_input_close(struct input_stream *is) { - iso_context *context = (iso_context *) is->data; + struct iso9660_archive_file *context = is->data; g_free(context->statbuf); - iso_close((struct archive_file *)context); + iso9660_archive_close((struct archive_file *)context); } static size_t -iso_is_read(struct input_stream *is, void *ptr, size_t size) +iso9660_input_read(struct input_stream *is, void *ptr, size_t size, GError **error_r) { - iso_context *context = (iso_context *) is->data; + struct iso9660_archive_file *context = (struct iso9660_archive_file *) is->data; int toread, readed = 0; int no_blocks, cur_block; size_t left_bytes = context->statbuf->size - context->cur_ofs; @@ -196,9 +219,10 @@ iso_is_read(struct input_stream *is, void *ptr, size_t size) context->statbuf->lsn + cur_block, no_blocks); if (readed != no_blocks * ISO_BLOCKSIZE) { - g_warning("error reading ISO file at lsn %lu\n", - (long unsigned int) cur_block ); - return -1; + g_set_error(error_r, iso9660_quark(), 0, + "error reading ISO file at lsn %lu", + (long unsigned int) cur_block); + return 0; } if (left_bytes < size) { readed = left_bytes; @@ -209,31 +233,32 @@ iso_is_read(struct input_stream *is, void *ptr, size_t size) } static bool -iso_is_eof(struct input_stream *is) +iso9660_input_eof(struct input_stream *is) { - iso_context *context = (iso_context *) is->data; + struct iso9660_archive_file *context = is->data; + return (context->cur_ofs == context->statbuf->size); } /* exported structures */ -static const char *const iso_extensions[] = { +static const char *const iso9660_archive_extensions[] = { "iso", NULL }; -static const struct input_plugin iso_inputplugin = { - .close = iso_is_close, - .read = iso_is_read, - .eof = iso_is_eof, +static const struct input_plugin iso9660_input_plugin = { + .close = iso9660_input_close, + .read = iso9660_input_read, + .eof = iso9660_input_eof, }; -const struct archive_plugin iso_plugin = { +const struct archive_plugin iso9660_archive_plugin = { .name = "iso", - .open = iso_open, - .scan_reset = iso_scan_reset, - .scan_next = iso_scan_next, - .open_stream = iso_open_stream, - .close = iso_close, - .suffixes = iso_extensions + .open = iso9660_archive_open, + .scan_reset = iso9660_archive_scan_reset, + .scan_next = iso9660_archive_scan_next, + .open_stream = iso9660_archive_open_stream, + .close = iso9660_archive_close, + .suffixes = iso9660_archive_extensions }; diff --git a/src/archive/iso9660_archive_plugin.h b/src/archive/iso9660_archive_plugin.h new file mode 100644 index 000000000..21730c537 --- /dev/null +++ b/src/archive/iso9660_archive_plugin.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2003-2009 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ARCHIVE_ISO9660_H +#define MPD_ARCHIVE_ISO9660_H + +extern const struct archive_plugin iso9660_archive_plugin; + +#endif diff --git a/src/archive/zip_plugin.c b/src/archive/zzip_archive_plugin.c index 243d46418..43c880aab 100644 --- a/src/archive/zip_plugin.c +++ b/src/archive/zzip_archive_plugin.c @@ -21,6 +21,8 @@ * zip archive handling (requires zziplib) */ +#include "config.h" +#include "archive/zzip_archive_plugin.h" #include "archive_api.h" #include "archive_api.h" #include "input_plugin.h" @@ -29,29 +31,40 @@ #include <glib.h> #include <string.h> -typedef struct { +struct zzip_archive { + struct archive_file base; + ZZIP_DIR *dir; ZZIP_FILE *file; size_t length; GSList *list; GSList *iter; -} zip_context; +}; + +static const struct input_plugin zzip_input_plugin; -static const struct input_plugin zip_inputplugin; +static inline GQuark +zzip_quark(void) +{ + return g_quark_from_static_string("zzip"); +} /* archive open && listing routine */ static struct archive_file * -zip_open(char * pathname) +zzip_archive_open(const char *pathname, GError **error_r) { - zip_context *context = g_malloc(sizeof(zip_context)); + struct zzip_archive *context = g_malloc(sizeof(*context)); ZZIP_DIRENT dirent; + archive_file_init(&context->base, &zzip_archive_plugin); + // open archive context->list = NULL; context->dir = zzip_dir_open(pathname, NULL); if (context->dir == NULL) { - g_warning("zipfile %s open failed\n", pathname); + g_set_error(error_r, zzip_quark(), 0, + "Failed to open ZIP file %s", pathname); return NULL; } @@ -63,21 +76,21 @@ zip_open(char * pathname) } } - return (struct archive_file *)context; + return &context->base; } static void -zip_scan_reset(struct archive_file *file) +zzip_archive_scan_reset(struct archive_file *file) { - zip_context *context = (zip_context *) file; + struct zzip_archive *context = (struct zzip_archive *) file; //reset iterator context->iter = context->list; } static char * -zip_scan_next(struct archive_file *file) +zzip_archive_scan_next(struct archive_file *file) { - zip_context *context = (zip_context *) file; + struct zzip_archive *context = (struct zzip_archive *) file; char *data = NULL; if (context->iter != NULL) { ///fetch data and goto next @@ -88,9 +101,9 @@ zip_scan_next(struct archive_file *file) } static void -zip_close(struct archive_file *file) +zzip_archive_close(struct archive_file *file) { - zip_context *context = (zip_context *) file; + struct zzip_archive *context = (struct zzip_archive *) file; if (context->list) { //free list for (GSList *tmp = context->list; tmp != NULL; tmp = g_slist_next(tmp)) @@ -106,14 +119,14 @@ zip_close(struct archive_file *file) /* single archive handling */ static bool -zip_open_stream(struct archive_file *file, struct input_stream *is, - const char *pathname) +zzip_archive_open_stream(struct archive_file *file, struct input_stream *is, + const char *pathname, GError **error_r) { - zip_context *context = (zip_context *) file; + struct zzip_archive *context = (struct zzip_archive *) file; ZZIP_STAT z_stat; //setup file ops - is->plugin = &zip_inputplugin; + is->plugin = &zzip_input_plugin; //insert back reference is->data = context; //we are seekable (but its not recommendent to do so) @@ -121,7 +134,8 @@ zip_open_stream(struct archive_file *file, struct input_stream *is, context->file = zzip_file_open(context->dir, pathname, 0); if (!context->file) { - g_warning("file %s not found in the zipfile\n", pathname); + g_set_error(error_r, zzip_quark(), 0, + "not found in the ZIP file: %s", pathname); return false; } zzip_file_stat(context->file, &z_stat); @@ -130,41 +144,45 @@ zip_open_stream(struct archive_file *file, struct input_stream *is, } static void -zip_is_close(struct input_stream *is) +zzip_input_close(struct input_stream *is) { - zip_context *context = (zip_context *) is->data; + struct zzip_archive *context = (struct zzip_archive *) is->data; zzip_file_close (context->file); - zip_close((struct archive_file *)context); + zzip_archive_close((struct archive_file *)context); } static size_t -zip_is_read(struct input_stream *is, void *ptr, size_t size) +zzip_input_read(struct input_stream *is, void *ptr, size_t size, + GError **error_r) { - zip_context *context = (zip_context *) is->data; + struct zzip_archive *context = (struct zzip_archive *) is->data; int ret; ret = zzip_file_read(context->file, ptr, size); if (ret < 0) { - g_warning("error %d reading zipfile\n", ret); + g_set_error(error_r, zzip_quark(), ret, + "zzip_file_read() has failed"); return 0; } return ret; } static bool -zip_is_eof(struct input_stream *is) +zzip_input_eof(struct input_stream *is) { - zip_context *context = (zip_context *) is->data; + struct zzip_archive *context = (struct zzip_archive *) is->data; return ((size_t) zzip_tell(context->file) == context->length); } static bool -zip_is_seek(G_GNUC_UNUSED struct input_stream *is, - G_GNUC_UNUSED off_t offset, G_GNUC_UNUSED int whence) +zzip_input_seek(struct input_stream *is, + goffset offset, int whence, GError **error_r) { - zip_context *context = (zip_context *) is->data; + struct zzip_archive *context = (struct zzip_archive *) is->data; zzip_off_t ofs = zzip_seek(context->file, offset, whence); if (ofs != -1) { + g_set_error(error_r, zzip_quark(), ofs, + "zzip_seek() has failed"); is->offset = ofs; return true; } @@ -173,24 +191,24 @@ zip_is_seek(G_GNUC_UNUSED struct input_stream *is, /* exported structures */ -static const char *const zip_extensions[] = { +static const char *const zzip_archive_extensions[] = { "zip", NULL }; -static const struct input_plugin zip_inputplugin = { - .close = zip_is_close, - .read = zip_is_read, - .eof = zip_is_eof, - .seek = zip_is_seek, +static const struct input_plugin zzip_input_plugin = { + .close = zzip_input_close, + .read = zzip_input_read, + .eof = zzip_input_eof, + .seek = zzip_input_seek, }; -const struct archive_plugin zip_plugin = { - .name = "zip", - .open = zip_open, - .scan_reset = zip_scan_reset, - .scan_next = zip_scan_next, - .open_stream = zip_open_stream, - .close = zip_close, - .suffixes = zip_extensions +const struct archive_plugin zzip_archive_plugin = { + .name = "zzip", + .open = zzip_archive_open, + .scan_reset = zzip_archive_scan_reset, + .scan_next = zzip_archive_scan_next, + .open_stream = zzip_archive_open_stream, + .close = zzip_archive_close, + .suffixes = zzip_archive_extensions }; diff --git a/src/archive/zzip_archive_plugin.h b/src/archive/zzip_archive_plugin.h new file mode 100644 index 000000000..07a8a2eca --- /dev/null +++ b/src/archive/zzip_archive_plugin.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2003-2009 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ARCHIVE_ZZIP_H +#define MPD_ARCHIVE_ZZIP_H + +extern const struct archive_plugin zzip_archive_plugin; + +#endif diff --git a/src/archive_api.c b/src/archive_api.c index 153afa361..574960558 100644 --- a/src/archive_api.c +++ b/src/archive_api.c @@ -17,6 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" /* must be first for large file support */ +#include "archive_api.h" + #include <stdio.h> #include <string.h> @@ -26,8 +29,6 @@ #include <errno.h> #include <glib.h> -#include "archive_api.h" - /** * * archive_lookup is used to determine if part of pathname refers to an regular diff --git a/src/archive_api.h b/src/archive_api.h index 2efcc1e6a..20a4f9277 100644 --- a/src/archive_api.h +++ b/src/archive_api.h @@ -27,72 +27,11 @@ */ #include "archive_internal.h" +#include "archive_plugin.h" #include "input_stream.h" #include <stdbool.h> -struct archive_file; - -struct archive_plugin { - const char *name; - - /** - * optional, set this to NULL if the archive plugin doesn't - * have/need one this must false if there is an error and - * true otherwise - */ - bool (*init)(void); - - /** - * optional, set this to NULL if the archive plugin doesn't - * have/need one - */ - void (*finish)(void); - - /** - * tryes to open archive file and associates handle with archive - * returns pointer to handle used is all operations with this archive - * or NULL when opening fails - */ - struct archive_file *(*open)(char * pathname); - - /** - * reset routine will move current read index in archive to default - * position and then the filenames from archives can be read - * via scan_next routine - */ - void (*scan_reset)(struct archive_file *); - - /** - * the read method will return corresponding files from archive - * (as pathnames) and move read index to next file. When there is no - * next file it return NULL. - */ - char *(*scan_next)(struct archive_file *); - - /** - * 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 - */ - bool (*open_stream)(struct archive_file *, struct input_stream *is, - const char *path); - - /** - * closes archive file. - */ - void (*close)(struct archive_file *); - - /** - * suffixes handled by this plugin. - * last element in these arrays must always be a NULL - */ - const char *const*suffixes; -}; - bool archive_lookup(char *pathname, char **archive, char **inpath, char **suffix); #endif diff --git a/src/archive_internal.h b/src/archive_internal.h index 130d25d65..3d973381e 100644 --- a/src/archive_internal.h +++ b/src/archive_internal.h @@ -21,7 +21,14 @@ #define MPD_ARCHIVE_INTERNAL_H struct archive_file { - int placeholder; + const struct archive_plugin *plugin; }; +static inline void +archive_file_init(struct archive_file *archive_file, + const struct archive_plugin *plugin) +{ + archive_file->plugin = plugin; +} + #endif diff --git a/src/archive_list.c b/src/archive_list.c index 8228fc961..191cb004a 100644 --- a/src/archive_list.c +++ b/src/archive_list.c @@ -17,50 +17,44 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" #include "archive_list.h" -#include "archive_api.h" +#include "archive_plugin.h" #include "utils.h" -#include "config.h" +#include "archive/bz2_archive_plugin.h" +#include "archive/iso9660_archive_plugin.h" +#include "archive/zzip_archive_plugin.h" #include <string.h> #include <glib.h> -extern const struct archive_plugin bz2_plugin; -extern const struct archive_plugin zip_plugin; -extern const struct archive_plugin iso_plugin; - static const struct archive_plugin *const archive_plugins[] = { #ifdef HAVE_BZ2 - &bz2_plugin, + &bz2_archive_plugin, #endif -#ifdef HAVE_ZIP - &zip_plugin, +#ifdef HAVE_ZZIP + &zzip_archive_plugin, #endif -#ifdef HAVE_ISO - &iso_plugin, +#ifdef HAVE_ISO9660 + &iso9660_archive_plugin, #endif NULL }; -enum { - num_archive_plugins = G_N_ELEMENTS(archive_plugins)-1, -}; - /** which plugins have been initialized successfully? */ -static bool archive_plugins_enabled[num_archive_plugins+1]; +static bool archive_plugins_enabled[G_N_ELEMENTS(archive_plugins) - 1]; const struct archive_plugin * archive_plugin_from_suffix(const char *suffix) { - unsigned i; - if (suffix == NULL) return NULL; - for (i=0; i < num_archive_plugins; ++i) { + for (unsigned i = 0; archive_plugins[i] != NULL; ++i) { const struct archive_plugin *plugin = archive_plugins[i]; if (archive_plugins_enabled[i] && - stringFoundInStringArray(plugin->suffixes, suffix)) { + plugin->suffixes != NULL && + string_array_contains(plugin->suffixes, suffix)) { ++i; return plugin; } @@ -71,7 +65,7 @@ archive_plugin_from_suffix(const char *suffix) const struct archive_plugin * archive_plugin_from_name(const char *name) { - for (unsigned i = 0; i < num_archive_plugins; ++i) { + for (unsigned i = 0; archive_plugins[i] != NULL; ++i) { const struct archive_plugin *plugin = archive_plugins[i]; if (archive_plugins_enabled[i] && strcmp(plugin->name, name) == 0) @@ -84,7 +78,7 @@ void archive_plugin_print_all_suffixes(FILE * fp) { const char *const*suffixes; - for (unsigned i = 0; i < num_archive_plugins; ++i) { + for (unsigned i = 0; archive_plugins[i] != NULL; ++i) { const struct archive_plugin *plugin = archive_plugins[i]; if (!archive_plugins_enabled[i]) continue; @@ -101,7 +95,7 @@ void archive_plugin_print_all_suffixes(FILE * fp) void archive_plugin_init_all(void) { - for (unsigned i = 0; i < num_archive_plugins; ++i) { + for (unsigned i = 0; archive_plugins[i] != NULL; ++i) { const struct archive_plugin *plugin = archive_plugins[i]; if (plugin->init == NULL || archive_plugins[i]->init()) archive_plugins_enabled[i] = true; @@ -110,7 +104,7 @@ void archive_plugin_init_all(void) void archive_plugin_deinit_all(void) { - for (unsigned i = 0; i < num_archive_plugins; ++i) { + for (unsigned i = 0; archive_plugins[i] != NULL; ++i) { const struct archive_plugin *plugin = archive_plugins[i]; if (archive_plugins_enabled[i] && plugin->finish != NULL) archive_plugins[i]->finish(); diff --git a/src/archive_list.h b/src/archive_list.h index 55278fbc4..2534b2b18 100644 --- a/src/archive_list.h +++ b/src/archive_list.h @@ -20,8 +20,6 @@ #ifndef MPD_ARCHIVE_LIST_H #define MPD_ARCHIVE_LIST_H -#include "archive_api.h" - #include <stdio.h> struct archive_plugin; diff --git a/src/archive_plugin.c b/src/archive_plugin.c new file mode 100644 index 000000000..86334709b --- /dev/null +++ b/src/archive_plugin.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2003-2009 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "archive_plugin.h" +#include "archive_internal.h" + +#include <assert.h> + +struct archive_file * +archive_file_open(const struct archive_plugin *plugin, const char *path, + GError **error_r) +{ + struct archive_file *file; + + assert(plugin != NULL); + assert(plugin->open != NULL); + assert(path != NULL); + assert(error_r == NULL || *error_r == NULL); + + file = plugin->open(path, error_r); + + if (file != NULL) { + assert(file->plugin != NULL); + assert(file->plugin->close != NULL); + assert(file->plugin->scan_reset != NULL); + assert(file->plugin->scan_next != NULL); + assert(file->plugin->open_stream != NULL); + assert(error_r == NULL || *error_r == NULL); + } else { + assert(error_r == NULL || *error_r != NULL); + } + + return file; +} + +void +archive_file_close(struct archive_file *file) +{ + assert(file != NULL); + assert(file->plugin != NULL); + assert(file->plugin->close != NULL); + + file->plugin->close(file); +} + +void +archive_file_scan_reset(struct archive_file *file) +{ + assert(file != NULL); + assert(file->plugin != NULL); + assert(file->plugin->scan_reset != NULL); + assert(file->plugin->scan_next != NULL); + + file->plugin->scan_reset(file); +} + +char * +archive_file_scan_next(struct archive_file *file) +{ + assert(file != NULL); + assert(file->plugin != NULL); + assert(file->plugin->scan_next != NULL); + + return file->plugin->scan_next(file); +} + +bool +archive_file_open_stream(struct archive_file *file, struct input_stream *is, + const char *path, GError **error_r) +{ + assert(file != NULL); + assert(file->plugin != NULL); + assert(file->plugin->open_stream != NULL); + + return file->plugin->open_stream(file, is, path, error_r); +} diff --git a/src/archive_plugin.h b/src/archive_plugin.h new file mode 100644 index 000000000..52629f2e1 --- /dev/null +++ b/src/archive_plugin.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2003-2009 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ARCHIVE_PLUGIN_H +#define MPD_ARCHIVE_PLUGIN_H + +#include <glib.h> + +#include <stdbool.h> + +struct input_stream; +struct archive_file; + +struct archive_plugin { + const char *name; + + /** + * optional, set this to NULL if the archive plugin doesn't + * have/need one this must false if there is an error and + * true otherwise + */ + bool (*init)(void); + + /** + * optional, set this to NULL if the archive plugin doesn't + * have/need one + */ + void (*finish)(void); + + /** + * tryes to open archive file and associates handle with archive + * returns pointer to handle used is all operations with this archive + * or NULL when opening fails + */ + struct archive_file *(*open)(const char *path_fs, GError **error_r); + + /** + * reset routine will move current read index in archive to default + * position and then the filenames from archives can be read + * via scan_next routine + */ + void (*scan_reset)(struct archive_file *); + + /** + * the read method will return corresponding files from archive + * (as pathnames) and move read index to next file. When there is no + * next file it return NULL. + */ + char *(*scan_next)(struct archive_file *); + + /** + * 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 + */ + bool (*open_stream)(struct archive_file *, struct input_stream *is, + const char *path, GError **error_r); + + /** + * closes archive file. + */ + void (*close)(struct archive_file *); + + /** + * suffixes handled by this plugin. + * last element in these arrays must always be a NULL + */ + const char *const*suffixes; +}; + +struct archive_file * +archive_file_open(const struct archive_plugin *plugin, const char *path, + GError **error_r); + +void +archive_file_close(struct archive_file *file); + +void +archive_file_scan_reset(struct archive_file *file); + +char * +archive_file_scan_next(struct archive_file *file); + +bool +archive_file_open_stream(struct archive_file *file, struct input_stream *is, + const char *path, GError **error_r); + +#endif |