aboutsummaryrefslogtreecommitdiffstats
path: root/src/archive
diff options
context:
space:
mode:
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.h25
-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.h25
-rw-r--r--src/archive_api.c5
-rw-r--r--src/archive_api.h63
-rw-r--r--src/archive_internal.h9
-rw-r--r--src/archive_list.c42
-rw-r--r--src/archive_list.h2
-rw-r--r--src/archive_plugin.c92
-rw-r--r--src/archive_plugin.h109
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