diff options
Diffstat (limited to 'src/archive')
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 |