From cc5443c38eddbbd2894436b1e2107f8dda7262b8 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 Feb 2016 13:31:03 +0100 Subject: [PATCH] tag/ApeLoader: use class InputStream instead of FILE* Prepare for APE tag support on userspace NFS/SMB/CIFS mounts. --- Makefile.am | 7 ++++++- src/tag/ApeLoader.cxx | 37 ++++++++++++++++++++++++------------- src/tag/ApeLoader.hxx | 10 ++++++++++ src/tag/ApeTag.cxx | 17 +++++++++++++++++ src/tag/ApeTag.hxx | 10 ++++++++++ 5 files changed, 67 insertions(+), 14 deletions(-) diff --git a/Makefile.am b/Makefile.am index b89f942b7..f94ef3c8c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1882,10 +1882,15 @@ test_read_tags_SOURCES = test/read_tags.cxx \ test_ReadApeTags_LDADD = \ $(TAG_LIBS) \ + $(INPUT_LIBS) \ + $(ARCHIVE_LIBS) \ $(FS_LIBS) \ $(ICU_LDADD) \ + libsystem.a \ libutil.a -test_ReadApeTags_SOURCES = test/ReadApeTags.cxx +test_ReadApeTags_SOURCES = \ + src/Log.cxx src/LogBackend.cxx \ + test/ReadApeTags.cxx if ENABLE_ID3TAG test_dump_rva2_LDADD = \ diff --git a/src/tag/ApeLoader.cxx b/src/tag/ApeLoader.cxx index b1759a730..26d42c48b 100644 --- a/src/tag/ApeLoader.cxx +++ b/src/tag/ApeLoader.cxx @@ -20,12 +20,16 @@ #include "config.h" #include "ApeLoader.hxx" #include "system/ByteOrder.hxx" -#include "fs/FileSystem.hxx" +#include "fs/Path.hxx" +#include "thread/Mutex.hxx" +#include "thread/Cond.hxx" +#include "input/InputStream.hxx" +#include "input/LocalOpen.hxx" #include "util/StringView.hxx" +#include "util/Error.hxx" #include #include -#include #include struct ape_footer { @@ -37,13 +41,18 @@ struct ape_footer { unsigned char reserved[8]; }; -static bool -ape_scan_internal(FILE *fp, ApeTagCallback callback) +bool +tag_ape_scan(InputStream &is, ApeTagCallback callback) { + const ScopeLock protect(is.mutex); + + if (!is.KnownSize() || !is.CheapSeeking()) + return false; + /* determine if file has an apeV2 tag */ struct ape_footer footer; - if (fseek(fp, -(long)sizeof(footer), SEEK_END) || - fread(&footer, 1, sizeof(footer), fp) != sizeof(footer) || + if (!is.Seek(is.GetSize() - sizeof(footer), IgnoreError()) || + !is.ReadFull(&footer, sizeof(footer), IgnoreError()) || memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0 || FromLE32(footer.version) != 2000) return false; @@ -53,7 +62,7 @@ ape_scan_internal(FILE *fp, ApeTagCallback callback) if (remaining <= sizeof(footer) + 10 || /* refuse to load more than one megabyte of tag data */ remaining > 1024 * 1024 || - fseek(fp, -(long)remaining, SEEK_END)) + !is.Seek(is.GetSize() - remaining, IgnoreError())) return false; /* read tag into buffer */ @@ -61,7 +70,7 @@ ape_scan_internal(FILE *fp, ApeTagCallback callback) assert(remaining > 10); char *buffer = new char[remaining]; - if (fread(buffer, 1, remaining, fp) != remaining) { + if (!is.ReadFull(buffer, remaining, IgnoreError())) { delete[] buffer; return false; } @@ -104,11 +113,13 @@ ape_scan_internal(FILE *fp, ApeTagCallback callback) bool tag_ape_scan(Path path_fs, ApeTagCallback callback) { - FILE *fp = FOpen(path_fs, PATH_LITERAL("rb")); - if (fp == nullptr) + Mutex mutex; + Cond cond; + + std::unique_ptr is(OpenLocalInputStream(path_fs, mutex, + cond, IgnoreError())); + if (!is) return false; - bool success = ape_scan_internal(fp, callback); - fclose(fp); - return success; + return tag_ape_scan(*is, callback); } diff --git a/src/tag/ApeLoader.hxx b/src/tag/ApeLoader.hxx index 4587ff063..0e2eadff1 100644 --- a/src/tag/ApeLoader.hxx +++ b/src/tag/ApeLoader.hxx @@ -28,10 +28,20 @@ struct StringView; class Path; +class InputStream; typedef std::function ApeTagCallback; +/** + * Scans the APE tag values from a file. + * + * @return false if the file could not be opened or if no APE tag is + * present + */ +bool +tag_ape_scan(InputStream &is, ApeTagCallback callback); + /** * Scans the APE tag values from a file. * diff --git a/src/tag/ApeTag.cxx b/src/tag/ApeTag.cxx index 81318a771..edf30dd4d 100644 --- a/src/tag/ApeTag.cxx +++ b/src/tag/ApeTag.cxx @@ -105,6 +105,23 @@ tag_ape_import_item(unsigned long flags, return true; } +bool +tag_ape_scan2(InputStream &is, + const struct tag_handler *handler, void *handler_ctx) +{ + bool recognized = false; + + auto callback = [handler, handler_ctx, &recognized] + (unsigned long flags, const char *key, + StringView value) { + recognized |= tag_ape_import_item(flags, key, value, + handler, handler_ctx); + return true; + }; + + return tag_ape_scan(is, callback) && recognized; +} + bool tag_ape_scan2(Path path_fs, const struct tag_handler *handler, void *handler_ctx) diff --git a/src/tag/ApeTag.hxx b/src/tag/ApeTag.hxx index 20d1d7b81..003f9404c 100644 --- a/src/tag/ApeTag.hxx +++ b/src/tag/ApeTag.hxx @@ -23,10 +23,20 @@ #include "TagTable.hxx" class Path; +class InputStream; struct tag_handler; extern const struct tag_table ape_tags[]; +/** + * Scan the APE tags of a stream. + * + * @param path_fs the path of the file in filesystem encoding + */ +bool +tag_ape_scan2(InputStream &is, + const tag_handler *handler, void *handler_ctx); + /** * Scan the APE tags of a file. *