aboutsummaryrefslogtreecommitdiffstats
path: root/src/archive
diff options
context:
space:
mode:
Diffstat (limited to 'src/archive')
-rw-r--r--src/archive/ArchiveDomain.cxx23
-rw-r--r--src/archive/ArchiveDomain.hxx25
-rw-r--r--src/archive/ArchiveFile.hxx61
-rw-r--r--src/archive/ArchiveList.cxx90
-rw-r--r--src/archive/ArchiveList.hxx47
-rw-r--r--src/archive/ArchiveLookup.cxx103
-rw-r--r--src/archive/ArchiveLookup.hxx45
-rw-r--r--src/archive/ArchivePlugin.cxx40
-rw-r--r--src/archive/ArchivePlugin.hxx61
-rw-r--r--src/archive/ArchiveVisitor.hxx28
-rw-r--r--src/archive/plugins/Bzip2ArchivePlugin.cxx (renamed from src/archive/Bzip2ArchivePlugin.cxx)115
-rw-r--r--src/archive/plugins/Bzip2ArchivePlugin.hxx (renamed from src/archive/Bzip2ArchivePlugin.hxx)6
-rw-r--r--src/archive/plugins/Iso9660ArchivePlugin.cxx (renamed from src/archive/Iso9660ArchivePlugin.cxx)146
-rw-r--r--src/archive/plugins/Iso9660ArchivePlugin.hxx (renamed from src/archive/Iso9660ArchivePlugin.hxx)6
-rw-r--r--src/archive/plugins/ZzipArchivePlugin.cxx (renamed from src/archive/ZzipArchivePlugin.cxx)109
-rw-r--r--src/archive/plugins/ZzipArchivePlugin.hxx (renamed from src/archive/ZzipArchivePlugin.hxx)6
16 files changed, 675 insertions, 236 deletions
diff --git a/src/archive/ArchiveDomain.cxx b/src/archive/ArchiveDomain.cxx
new file mode 100644
index 000000000..4adf4a886
--- /dev/null
+++ b/src/archive/ArchiveDomain.cxx
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2003-2014 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 "ArchiveDomain.hxx"
+#include "util/Domain.hxx"
+
+const Domain archive_domain("archive");
diff --git a/src/archive/ArchiveDomain.hxx b/src/archive/ArchiveDomain.hxx
new file mode 100644
index 000000000..817ae5835
--- /dev/null
+++ b/src/archive/ArchiveDomain.hxx
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2003-2014 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_DOMAIN_HXX
+#define MPD_ARCHIVE_DOMAIN_HXX
+
+extern const class Domain archive_domain;
+
+#endif
diff --git a/src/archive/ArchiveFile.hxx b/src/archive/ArchiveFile.hxx
new file mode 100644
index 000000000..473eef70b
--- /dev/null
+++ b/src/archive/ArchiveFile.hxx
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2003-2014 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_FILE_HXX
+#define MPD_ARCHIVE_FILE_HXX
+
+class Mutex;
+class Cond;
+class Error;
+struct ArchivePlugin;
+class ArchiveVisitor;
+class InputStream;
+
+class ArchiveFile {
+public:
+ const ArchivePlugin &plugin;
+
+ ArchiveFile(const ArchivePlugin &_plugin)
+ :plugin(_plugin) {}
+
+protected:
+ /**
+ * Use Close() instead of delete.
+ */
+ ~ArchiveFile() {}
+
+public:
+ virtual void Close() = 0;
+
+ /**
+ * Visit all entries inside this archive.
+ */
+ virtual void Visit(ArchiveVisitor &visitor) = 0;
+
+ /**
+ * Opens an InputStream of a file within the archive.
+ *
+ * @param path the path within the archive
+ */
+ virtual InputStream *OpenStream(const char *path,
+ Mutex &mutex, Cond &cond,
+ Error &error) = 0;
+};
+
+#endif
diff --git a/src/archive/ArchiveList.cxx b/src/archive/ArchiveList.cxx
new file mode 100644
index 000000000..79c3a16fe
--- /dev/null
+++ b/src/archive/ArchiveList.cxx
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2003-2014 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 "config.h"
+#include "ArchiveList.hxx"
+#include "ArchivePlugin.hxx"
+#include "util/StringUtil.hxx"
+#include "plugins/Bzip2ArchivePlugin.hxx"
+#include "plugins/Iso9660ArchivePlugin.hxx"
+#include "plugins/ZzipArchivePlugin.hxx"
+#include "util/Macros.hxx"
+
+#include <string.h>
+
+const ArchivePlugin *const archive_plugins[] = {
+#ifdef HAVE_BZ2
+ &bz2_archive_plugin,
+#endif
+#ifdef HAVE_ZZIP
+ &zzip_archive_plugin,
+#endif
+#ifdef HAVE_ISO9660
+ &iso9660_archive_plugin,
+#endif
+ nullptr
+};
+
+/** which plugins have been initialized successfully? */
+static bool archive_plugins_enabled[ARRAY_SIZE(archive_plugins) - 1];
+
+#define archive_plugins_for_each_enabled(plugin) \
+ archive_plugins_for_each(plugin) \
+ if (archive_plugins_enabled[archive_plugin_iterator - archive_plugins])
+
+const ArchivePlugin *
+archive_plugin_from_suffix(const char *suffix)
+{
+ if (suffix == nullptr)
+ return nullptr;
+
+ archive_plugins_for_each_enabled(plugin)
+ if (plugin->suffixes != nullptr &&
+ string_array_contains(plugin->suffixes, suffix))
+ return plugin;
+
+ return nullptr;
+}
+
+const ArchivePlugin *
+archive_plugin_from_name(const char *name)
+{
+ archive_plugins_for_each_enabled(plugin)
+ if (strcmp(plugin->name, name) == 0)
+ return plugin;
+
+ return nullptr;
+}
+
+void archive_plugin_init_all(void)
+{
+ for (unsigned i = 0; archive_plugins[i] != nullptr; ++i) {
+ const ArchivePlugin *plugin = archive_plugins[i];
+ if (plugin->init == nullptr || archive_plugins[i]->init())
+ archive_plugins_enabled[i] = true;
+ }
+}
+
+void archive_plugin_deinit_all(void)
+{
+ archive_plugins_for_each_enabled(plugin)
+ if (plugin->finish != nullptr)
+ plugin->finish();
+}
+
diff --git a/src/archive/ArchiveList.hxx b/src/archive/ArchiveList.hxx
new file mode 100644
index 000000000..1f1b0ae96
--- /dev/null
+++ b/src/archive/ArchiveList.hxx
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2003-2014 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_LIST_HXX
+#define MPD_ARCHIVE_LIST_HXX
+
+struct ArchivePlugin;
+
+extern const ArchivePlugin *const archive_plugins[];
+
+#define archive_plugins_for_each(plugin) \
+ for (const ArchivePlugin *plugin, \
+ *const*archive_plugin_iterator = &archive_plugins[0]; \
+ (plugin = *archive_plugin_iterator) != nullptr; \
+ ++archive_plugin_iterator)
+
+/* interface for using plugins */
+
+const ArchivePlugin *
+archive_plugin_from_suffix(const char *suffix);
+
+const ArchivePlugin *
+archive_plugin_from_name(const char *name);
+
+/* this is where we "load" all the "plugins" ;-) */
+void archive_plugin_init_all(void);
+
+/* this is where we "unload" all the "plugins" */
+void archive_plugin_deinit_all(void);
+
+#endif
diff --git a/src/archive/ArchiveLookup.cxx b/src/archive/ArchiveLookup.cxx
new file mode 100644
index 000000000..53730c504
--- /dev/null
+++ b/src/archive/ArchiveLookup.cxx
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2003-2014 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 "config.h" /* must be first for large file support */
+#include "ArchiveLookup.hxx"
+#include "ArchiveDomain.hxx"
+#include "Log.hxx"
+
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+gcc_pure
+static char *
+FindSlash(char *p, size_t i)
+{
+ for (; i > 0; --i)
+ if (p[i] == '/')
+ return p + i;
+
+ return nullptr;
+}
+
+gcc_pure
+static const char *
+FindSuffix(const char *p, const char *i)
+{
+ for (; i > p; --i) {
+ if (*i == '.')
+ return i + 1;
+ }
+
+ return nullptr;
+}
+
+bool
+archive_lookup(char *pathname, const char **archive,
+ const char **inpath, const char **suffix)
+{
+ size_t idx = strlen(pathname);
+
+ char *slash = nullptr;
+
+ while (true) {
+ //try to stat if its real directory
+ struct stat st_info;
+ if (stat(pathname, &st_info) == -1) {
+ if (errno != ENOTDIR) {
+ FormatErrno(archive_domain,
+ "Failed to stat %s", pathname);
+ return false;
+ }
+ } else {
+ //is something found ins original path (is not an archive)
+ if (slash == nullptr)
+ return false;
+
+ //its a file ?
+ if (S_ISREG(st_info.st_mode)) {
+ //so the upper should be file
+ *archive = pathname;
+ *inpath = slash + 1;
+
+ //try to get suffix
+ *suffix = FindSuffix(pathname, slash - 1);
+ return true;
+ } else {
+ FormatError(archive_domain,
+ "Not a regular file: %s",
+ pathname);
+ return false;
+ }
+ }
+
+ //find one dir up
+ if (slash != nullptr)
+ *slash = '/';
+
+ slash = FindSlash(pathname, idx - 1);
+ if (slash == nullptr)
+ return false;
+
+ *slash = 0;
+ idx = slash - pathname;
+ }
+}
+
diff --git a/src/archive/ArchiveLookup.hxx b/src/archive/ArchiveLookup.hxx
new file mode 100644
index 000000000..0c08951a9
--- /dev/null
+++ b/src/archive/ArchiveLookup.hxx
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2003-2014 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_LOOKUP_HXX
+#define MPD_ARCHIVE_LOOKUP_HXX
+
+/**
+ *
+ * archive_lookup is used to determine if part of pathname refers to an regular
+ * file (archive). If so then its also used to split pathname into archive file
+ * and path used to locate file in archive. It also returns suffix of the file.
+ * How it works:
+ * We do stat of the parent of input pathname as long as we find an regular file
+ * Normally this should never happen. When routine returns true pathname modified
+ * and split into archive, inpath and suffix. Otherwise nothing happens
+ *
+ * For example:
+ *
+ * /music/path/Talco.zip/Talco - Combat Circus/12 - A la pachenka.mp3
+ * is split into archive: /music/path/Talco.zip
+ * inarchive pathname: Talco - Combat Circus/12 - A la pachenka.mp3
+ * and suffix: zip
+ */
+bool
+archive_lookup(char *pathname, const char **archive,
+ const char **inpath, const char **suffix);
+
+#endif
+
diff --git a/src/archive/ArchivePlugin.cxx b/src/archive/ArchivePlugin.cxx
new file mode 100644
index 000000000..67f469e08
--- /dev/null
+++ b/src/archive/ArchivePlugin.cxx
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2003-2014 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 "config.h"
+#include "ArchivePlugin.hxx"
+#include "ArchiveFile.hxx"
+#include "fs/Path.hxx"
+#include "util/Error.hxx"
+
+#include <assert.h>
+
+ArchiveFile *
+archive_file_open(const ArchivePlugin *plugin, Path path,
+ Error &error)
+{
+ assert(plugin != nullptr);
+ assert(plugin->open != nullptr);
+ assert(!path.IsNull());
+
+ ArchiveFile *file = plugin->open(path, error);
+ assert((file == nullptr) == error.IsDefined());
+
+ return file;
+}
diff --git a/src/archive/ArchivePlugin.hxx b/src/archive/ArchivePlugin.hxx
new file mode 100644
index 000000000..eb24bbdf9
--- /dev/null
+++ b/src/archive/ArchivePlugin.hxx
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2003-2014 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_HXX
+#define MPD_ARCHIVE_PLUGIN_HXX
+
+class ArchiveFile;
+class Path;
+class Error;
+
+struct ArchivePlugin {
+ const char *name;
+
+ /**
+ * optional, set this to nullptr 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 nullptr 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 nullptr when opening fails
+ */
+ ArchiveFile *(*open)(Path path_fs, Error &error);
+
+ /**
+ * suffixes handled by this plugin.
+ * last element in these arrays must always be a nullptr
+ */
+ const char *const*suffixes;
+};
+
+ArchiveFile *
+archive_file_open(const ArchivePlugin *plugin, Path path,
+ Error &error);
+
+#endif
diff --git a/src/archive/ArchiveVisitor.hxx b/src/archive/ArchiveVisitor.hxx
new file mode 100644
index 000000000..6759695ca
--- /dev/null
+++ b/src/archive/ArchiveVisitor.hxx
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2003-2014 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_VISITOR_HXX
+#define MPD_ARCHIVE_VISITOR_HXX
+
+class ArchiveVisitor {
+public:
+ virtual void VisitArchiveEntry(const char *path_utf8) = 0;
+};
+
+#endif
diff --git a/src/archive/Bzip2ArchivePlugin.cxx b/src/archive/plugins/Bzip2ArchivePlugin.cxx
index d1e6b51af..14a68fdb5 100644
--- a/src/archive/Bzip2ArchivePlugin.cxx
+++ b/src/archive/plugins/Bzip2ArchivePlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,21 +23,20 @@
#include "config.h"
#include "Bzip2ArchivePlugin.hxx"
-#include "ArchivePlugin.hxx"
-#include "ArchiveFile.hxx"
-#include "ArchiveVisitor.hxx"
-#include "InputStream.hxx"
-#include "InputPlugin.hxx"
+#include "../ArchivePlugin.hxx"
+#include "../ArchiveFile.hxx"
+#include "../ArchiveVisitor.hxx"
+#include "input/InputStream.hxx"
+#include "input/InputPlugin.hxx"
#include "util/RefCount.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "fs/Traits.hxx"
+#include "fs/Path.hxx"
#include <bzlib.h>
-#include <stdint.h>
#include <stddef.h>
-#include <string.h>
#ifdef HAVE_OLDER_BZIP2
#define BZ2_bzDecompressInit bzDecompressInit
@@ -51,9 +50,9 @@ public:
std::string name;
InputStream *const istream;
- Bzip2ArchiveFile(const char *path, InputStream *_is)
+ Bzip2ArchiveFile(Path path, InputStream *_is)
:ArchiveFile(bz2_archive_plugin),
- name(PathTraits::GetBaseUTF8(path)),
+ name(PathTraitsFS::GetBase(path.c_str())),
istream(_is) {
// remove .bz2 suffix
const size_t len = name.length();
@@ -62,7 +61,7 @@ public:
}
~Bzip2ArchiveFile() {
- istream->Close();
+ delete istream;
}
void Ref() {
@@ -89,9 +88,7 @@ public:
Error &error) override;
};
-struct Bzip2InputStream {
- InputStream base;
-
+struct Bzip2InputStream final : public InputStream {
Bzip2ArchiveFile *archive;
bool eof;
@@ -105,10 +102,11 @@ struct Bzip2InputStream {
~Bzip2InputStream();
bool Open(Error &error);
- void Close();
-};
-extern const InputPlugin bz2_inputplugin;
+ /* virtual methods from InputStream */
+ bool IsEOF() override;
+ size_t Read(void *ptr, size_t size, Error &error) override;
+};
static constexpr Domain bz2_domain("bz2");
@@ -131,24 +129,19 @@ Bzip2InputStream::Open(Error &error)
return false;
}
- base.ready = true;
+ SetReady();
return true;
}
-inline void
-Bzip2InputStream::Close()
-{
- BZ2_bzDecompressEnd(&bzstream);
-}
-
/* archive open && listing routine */
static ArchiveFile *
-bz2_open(const char *pathname, Error &error)
+bz2_open(Path pathname, Error &error)
{
static Mutex mutex;
static Cond cond;
- InputStream *is = InputStream::Open(pathname, mutex, cond, error);
+ InputStream *is = InputStream::OpenReady(pathname.c_str(), mutex, cond,
+ error);
if (is == nullptr)
return nullptr;
@@ -157,9 +150,10 @@ bz2_open(const char *pathname, Error &error)
/* single archive handling */
-Bzip2InputStream::Bzip2InputStream(Bzip2ArchiveFile &_context, const char *uri,
- Mutex &mutex, Cond &cond)
- :base(bz2_inputplugin, uri, mutex, cond),
+Bzip2InputStream::Bzip2InputStream(Bzip2ArchiveFile &_context,
+ const char *_uri,
+ Mutex &_mutex, Cond &_cond)
+ :InputStream(_uri, _mutex, _cond),
archive(&_context), eof(false)
{
archive->Ref();
@@ -167,6 +161,7 @@ Bzip2InputStream::Bzip2InputStream(Bzip2ArchiveFile &_context, const char *uri,
Bzip2InputStream::~Bzip2InputStream()
{
+ BZ2_bzDecompressEnd(&bzstream);
archive->Unref();
}
@@ -181,16 +176,7 @@ Bzip2ArchiveFile::OpenStream(const char *path,
return nullptr;
}
- return &bis->base;
-}
-
-static void
-bz2_is_close(InputStream *is)
-{
- Bzip2InputStream *bis = (Bzip2InputStream *)is;
-
- bis->Close();
- delete bis;
+ return bis;
}
static bool
@@ -214,30 +200,26 @@ bz2_fillbuffer(Bzip2InputStream *bis, Error &error)
return true;
}
-static size_t
-bz2_is_read(InputStream *is, void *ptr, size_t length,
- Error &error)
+size_t
+Bzip2InputStream::Read(void *ptr, size_t length, Error &error)
{
- Bzip2InputStream *bis = (Bzip2InputStream *)is;
- bz_stream *bzstream;
int bz_result;
size_t nbytes = 0;
- if (bis->eof)
+ if (eof)
return 0;
- bzstream = &bis->bzstream;
- bzstream->next_out = (char *)ptr;
- bzstream->avail_out = length;
+ bzstream.next_out = (char *)ptr;
+ bzstream.avail_out = length;
do {
- if (!bz2_fillbuffer(bis, error))
+ if (!bz2_fillbuffer(this, error))
return 0;
- bz_result = BZ2_bzDecompress(bzstream);
+ bz_result = BZ2_bzDecompress(&bzstream);
if (bz_result == BZ_STREAM_END) {
- bis->eof = true;
+ eof = true;
break;
}
@@ -246,20 +228,18 @@ bz2_is_read(InputStream *is, void *ptr, size_t length,
"BZ2_bzDecompress() has failed");
return 0;
}
- } while (bzstream->avail_out == length);
+ } while (bzstream.avail_out == length);
- nbytes = length - bzstream->avail_out;
- is->offset += nbytes;
+ nbytes = length - bzstream.avail_out;
+ offset += nbytes;
return nbytes;
}
-static bool
-bz2_is_eof(InputStream *is)
+bool
+Bzip2InputStream::IsEOF()
{
- Bzip2InputStream *bis = (Bzip2InputStream *)is;
-
- return bis->eof;
+ return eof;
}
/* exported structures */
@@ -269,22 +249,7 @@ static const char *const bz2_extensions[] = {
nullptr
};
-const InputPlugin bz2_inputplugin = {
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- bz2_is_close,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- bz2_is_read,
- bz2_is_eof,
- nullptr,
-};
-
-const struct archive_plugin bz2_archive_plugin = {
+const ArchivePlugin bz2_archive_plugin = {
"bz2",
nullptr,
nullptr,
diff --git a/src/archive/Bzip2ArchivePlugin.hxx b/src/archive/plugins/Bzip2ArchivePlugin.hxx
index a7933a7a7..1a0a578d1 100644
--- a/src/archive/Bzip2ArchivePlugin.hxx
+++ b/src/archive/plugins/Bzip2ArchivePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,8 @@
#ifndef MPD_ARCHIVE_BZ2_HXX
#define MPD_ARCHIVE_BZ2_HXX
-extern const struct archive_plugin bz2_archive_plugin;
+struct ArchivePlugin;
+
+extern const ArchivePlugin bz2_archive_plugin;
#endif
diff --git a/src/archive/Iso9660ArchivePlugin.cxx b/src/archive/plugins/Iso9660ArchivePlugin.cxx
index ad21d4a3d..ba415d3c5 100644
--- a/src/archive/Iso9660ArchivePlugin.cxx
+++ b/src/archive/plugins/Iso9660ArchivePlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,16 +23,16 @@
#include "config.h"
#include "Iso9660ArchivePlugin.hxx"
-#include "ArchivePlugin.hxx"
-#include "ArchiveFile.hxx"
-#include "ArchiveVisitor.hxx"
-#include "InputStream.hxx"
-#include "InputPlugin.hxx"
+#include "../ArchivePlugin.hxx"
+#include "../ArchiveFile.hxx"
+#include "../ArchiveVisitor.hxx"
+#include "input/InputStream.hxx"
+#include "input/InputPlugin.hxx"
+#include "fs/Path.hxx"
#include "util/RefCount.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
-#include <cdio/cdio.h>
#include <cdio/iso9660.h>
#include <stdlib.h>
@@ -41,11 +41,11 @@
#define CEILING(x, y) ((x+(y-1))/y)
class Iso9660ArchiveFile final : public ArchiveFile {
-public:
RefCount ref;
iso9660_t *iso;
+public:
Iso9660ArchiveFile(iso9660_t *_iso)
:ArchiveFile(iso9660_archive_plugin), iso(_iso) {}
@@ -53,11 +53,19 @@ public:
iso9660_close(iso);
}
+ void Ref() {
+ ref.Increment();
+ }
+
void Unref() {
if (ref.Decrement())
delete this;
}
+ long SeekRead(void *ptr, lsn_t start, long int i_size) const {
+ return iso9660_iso_seek_read(iso, ptr, start, i_size);
+ }
+
void Visit(const char *path, ArchiveVisitor &visitor);
virtual void Close() override {
@@ -71,8 +79,6 @@ public:
Error &error) override;
};
-extern const InputPlugin iso9660_input_plugin;
-
static constexpr Domain iso9660_domain("iso9660");
/* archive open && listing routine */
@@ -110,13 +116,14 @@ Iso9660ArchiveFile::Visit(const char *psz_path, ArchiveVisitor &visitor)
}
static ArchiveFile *
-iso9660_archive_open(const char *pathname, Error &error)
+iso9660_archive_open(Path pathname, Error &error)
{
/* open archive */
- auto iso = iso9660_open(pathname);
+ auto iso = iso9660_open(pathname.c_str());
if (iso == nullptr) {
error.Format(iso9660_domain,
- "Failed to open ISO9660 file %s", pathname);
+ "Failed to open ISO9660 file %s",
+ pathname.c_str());
return nullptr;
}
@@ -131,31 +138,31 @@ Iso9660ArchiveFile::Visit(ArchiveVisitor &visitor)
/* single archive handling */
-struct Iso9660InputStream {
- InputStream base;
-
- Iso9660ArchiveFile *archive;
+class Iso9660InputStream final : public InputStream {
+ Iso9660ArchiveFile &archive;
iso9660_stat_t *statbuf;
- size_t max_blocks;
- Iso9660InputStream(Iso9660ArchiveFile &_archive, const char *uri,
- Mutex &mutex, Cond &cond,
+public:
+ Iso9660InputStream(Iso9660ArchiveFile &_archive, const char *_uri,
+ Mutex &_mutex, Cond &_cond,
iso9660_stat_t *_statbuf)
- :base(iso9660_input_plugin, uri, mutex, cond),
- archive(&_archive), statbuf(_statbuf),
- max_blocks(CEILING(statbuf->size, ISO_BLOCKSIZE)) {
+ :InputStream(_uri, _mutex, _cond),
+ archive(_archive), statbuf(_statbuf) {
+ size = statbuf->size;
+ SetReady();
- base.ready = true;
- base.size = statbuf->size;
-
- archive->ref.Increment();
+ archive.Ref();
}
~Iso9660InputStream() {
free(statbuf);
- archive->Unref();
+ archive.Unref();
}
+
+ /* virtual methods from InputStream */
+ bool IsEOF() override;
+ size_t Read(void *ptr, size_t size, Error &error) override;
};
InputStream *
@@ -170,63 +177,49 @@ Iso9660ArchiveFile::OpenStream(const char *pathname,
return nullptr;
}
- Iso9660InputStream *iis =
- new Iso9660InputStream(*this, pathname, mutex, cond,
- statbuf);
- return &iis->base;
-}
-
-static void
-iso9660_input_close(InputStream *is)
-{
- Iso9660InputStream *iis = (Iso9660InputStream *)is;
-
- delete iis;
+ return new Iso9660InputStream(*this, pathname, mutex, cond,
+ statbuf);
}
-
-static size_t
-iso9660_input_read(InputStream *is, void *ptr, size_t size,
- Error &error)
+size_t
+Iso9660InputStream::Read(void *ptr, size_t read_size, Error &error)
{
- Iso9660InputStream *iis = (Iso9660InputStream *)is;
int readed = 0;
int no_blocks, cur_block;
- size_t left_bytes = iis->statbuf->size - is->offset;
-
- size = (size * ISO_BLOCKSIZE) / ISO_BLOCKSIZE;
+ size_t left_bytes = statbuf->size - offset;
- if (left_bytes < size) {
- no_blocks = CEILING(left_bytes,ISO_BLOCKSIZE);
+ if (left_bytes < read_size) {
+ no_blocks = CEILING(left_bytes, ISO_BLOCKSIZE);
} else {
- no_blocks = size / ISO_BLOCKSIZE;
+ no_blocks = read_size / ISO_BLOCKSIZE;
}
- if (no_blocks > 0) {
- cur_block = is->offset / ISO_BLOCKSIZE;
+ if (no_blocks == 0)
+ return 0;
- readed = iso9660_iso_seek_read (iis->archive->iso, ptr,
- iis->statbuf->lsn + cur_block, no_blocks);
+ cur_block = offset / ISO_BLOCKSIZE;
- if (readed != no_blocks * ISO_BLOCKSIZE) {
- error.Format(iso9660_domain,
- "error reading ISO file at lsn %lu",
- (unsigned long)cur_block);
- return 0;
- }
- if (left_bytes < size) {
- readed = left_bytes;
- }
+ readed = archive.SeekRead(ptr, statbuf->lsn + cur_block,
+ no_blocks);
- is->offset += readed;
+ if (readed != no_blocks * ISO_BLOCKSIZE) {
+ error.Format(iso9660_domain,
+ "error reading ISO file at lsn %lu",
+ (unsigned long)cur_block);
+ return 0;
+ }
+ if (left_bytes < read_size) {
+ readed = left_bytes;
}
+
+ offset += readed;
return readed;
}
-static bool
-iso9660_input_eof(InputStream *is)
+bool
+Iso9660InputStream::IsEOF()
{
- return is->offset == is->size;
+ return offset == size;
}
/* exported structures */
@@ -236,22 +229,7 @@ static const char *const iso9660_archive_extensions[] = {
nullptr
};
-const InputPlugin iso9660_input_plugin = {
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- iso9660_input_close,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- iso9660_input_read,
- iso9660_input_eof,
- nullptr,
-};
-
-const struct archive_plugin iso9660_archive_plugin = {
+const ArchivePlugin iso9660_archive_plugin = {
"iso",
nullptr,
nullptr,
diff --git a/src/archive/Iso9660ArchivePlugin.hxx b/src/archive/plugins/Iso9660ArchivePlugin.hxx
index 6fbab6159..9335e83b3 100644
--- a/src/archive/Iso9660ArchivePlugin.hxx
+++ b/src/archive/plugins/Iso9660ArchivePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,8 @@
#ifndef MPD_ARCHIVE_ISO9660_HXX
#define MPD_ARCHIVE_ISO9660_HXX
-extern const struct archive_plugin iso9660_archive_plugin;
+struct ArchivePlugin;
+
+extern const ArchivePlugin iso9660_archive_plugin;
#endif
diff --git a/src/archive/ZzipArchivePlugin.cxx b/src/archive/plugins/ZzipArchivePlugin.cxx
index 973fe91dc..396055c71 100644
--- a/src/archive/ZzipArchivePlugin.cxx
+++ b/src/archive/plugins/ZzipArchivePlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -23,19 +23,18 @@
#include "config.h"
#include "ZzipArchivePlugin.hxx"
-#include "ArchivePlugin.hxx"
-#include "ArchiveFile.hxx"
-#include "ArchiveVisitor.hxx"
-#include "InputStream.hxx"
-#include "InputPlugin.hxx"
+#include "../ArchivePlugin.hxx"
+#include "../ArchiveFile.hxx"
+#include "../ArchiveVisitor.hxx"
+#include "input/InputStream.hxx"
+#include "input/InputPlugin.hxx"
+#include "fs/Path.hxx"
#include "util/RefCount.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <zzip/zzip.h>
-#include <string.h>
-
class ZzipArchiveFile final : public ArchiveFile {
public:
RefCount ref;
@@ -65,19 +64,17 @@ public:
Error &error) override;
};
-extern const InputPlugin zzip_input_plugin;
-
static constexpr Domain zzip_domain("zzip");
/* archive open && listing routine */
static ArchiveFile *
-zzip_archive_open(const char *pathname, Error &error)
+zzip_archive_open(Path pathname, Error &error)
{
- ZZIP_DIR *dir = zzip_dir_open(pathname, nullptr);
+ ZZIP_DIR *dir = zzip_dir_open(pathname.c_str(), nullptr);
if (dir == nullptr) {
error.Format(zzip_domain, "Failed to open ZIP file %s",
- pathname);
+ pathname.c_str());
return nullptr;
}
@@ -98,25 +95,24 @@ ZzipArchiveFile::Visit(ArchiveVisitor &visitor)
/* single archive handling */
-struct ZzipInputStream {
- InputStream base;
-
+struct ZzipInputStream final : public InputStream {
ZzipArchiveFile *archive;
ZZIP_FILE *file;
- ZzipInputStream(ZzipArchiveFile &_archive, const char *uri,
- Mutex &mutex, Cond &cond,
+ ZzipInputStream(ZzipArchiveFile &_archive, const char *_uri,
+ Mutex &_mutex, Cond &_cond,
ZZIP_FILE *_file)
- :base(zzip_input_plugin, uri, mutex, cond),
+ :InputStream(_uri, _mutex, _cond),
archive(&_archive), file(_file) {
- base.ready = true;
//we are seekable (but its not recommendent to do so)
- base.seekable = true;
+ seekable = true;
ZZIP_STAT z_stat;
zzip_file_stat(file, &z_stat);
- base.size = z_stat.st_size;
+ size = z_stat.st_size;
+
+ SetReady();
archive->ref.Increment();
}
@@ -125,6 +121,11 @@ struct ZzipInputStream {
zzip_file_close(file);
archive->Unref();
}
+
+ /* virtual methods from InputStream */
+ bool IsEOF() override;
+ size_t Read(void *ptr, size_t size, Error &error) override;
+ bool Seek(offset_type offset, Error &error) override;
};
InputStream *
@@ -139,56 +140,37 @@ ZzipArchiveFile::OpenStream(const char *pathname,
return nullptr;
}
- ZzipInputStream *zis =
- new ZzipInputStream(*this, pathname,
- mutex, cond,
- _file);
- return &zis->base;
+ return new ZzipInputStream(*this, pathname,
+ mutex, cond,
+ _file);
}
-static void
-zzip_input_close(InputStream *is)
+size_t
+ZzipInputStream::Read(void *ptr, size_t read_size, Error &error)
{
- ZzipInputStream *zis = (ZzipInputStream *)is;
-
- delete zis;
-}
-
-static size_t
-zzip_input_read(InputStream *is, void *ptr, size_t size,
- Error &error)
-{
- ZzipInputStream *zis = (ZzipInputStream *)is;
- int ret;
-
- ret = zzip_file_read(zis->file, ptr, size);
+ int ret = zzip_file_read(file, ptr, read_size);
if (ret < 0) {
error.Set(zzip_domain, "zzip_file_read() has failed");
return 0;
}
- is->offset = zzip_tell(zis->file);
-
+ offset = zzip_tell(file);
return ret;
}
-static bool
-zzip_input_eof(InputStream *is)
+bool
+ZzipInputStream::IsEOF()
{
- ZzipInputStream *zis = (ZzipInputStream *)is;
-
- return (InputPlugin::offset_type)zzip_tell(zis->file) == is->size;
+ return (InputPlugin::offset_type)zzip_tell(file) == size;
}
-static bool
-zzip_input_seek(InputStream *is, InputPlugin::offset_type offset,
- int whence, Error &error)
+bool
+ZzipInputStream::Seek(offset_type new_offset, Error &error)
{
- ZzipInputStream *zis = (ZzipInputStream *)is;
- zzip_off_t ofs = zzip_seek(zis->file, offset, whence);
+ zzip_off_t ofs = zzip_seek(file, new_offset, SEEK_SET);
if (ofs != -1) {
error.Set(zzip_domain, "zzip_seek() has failed");
- is->offset = ofs;
+ offset = ofs;
return true;
}
return false;
@@ -201,22 +183,7 @@ static const char *const zzip_archive_extensions[] = {
nullptr
};
-const InputPlugin zzip_input_plugin = {
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- zzip_input_close,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- zzip_input_read,
- zzip_input_eof,
- zzip_input_seek,
-};
-
-const struct archive_plugin zzip_archive_plugin = {
+const ArchivePlugin zzip_archive_plugin = {
"zzip",
nullptr,
nullptr,
diff --git a/src/archive/ZzipArchivePlugin.hxx b/src/archive/plugins/ZzipArchivePlugin.hxx
index 4ba16849b..cc92b7c52 100644
--- a/src/archive/ZzipArchivePlugin.hxx
+++ b/src/archive/plugins/ZzipArchivePlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,8 @@
#ifndef MPD_ARCHIVE_ZZIP_HXX
#define MPD_ARCHIVE_ZZIP_HXX
-extern const struct archive_plugin zzip_archive_plugin;
+struct ArchivePlugin;
+
+extern const ArchivePlugin zzip_archive_plugin;
#endif