diff options
Diffstat (limited to 'src/command/FileCommands.cxx')
-rw-r--r-- | src/command/FileCommands.cxx | 183 |
1 files changed, 87 insertions, 96 deletions
diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx index 1b6a11cf5..486c00d89 100644 --- a/src/command/FileCommands.cxx +++ b/src/command/FileCommands.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,10 +21,12 @@ #include "config.h" #include "FileCommands.hxx" +#include "Request.hxx" #include "CommandError.hxx" #include "protocol/Ack.hxx" -#include "protocol/Result.hxx" #include "client/Client.hxx" +#include "client/Response.hxx" +#include "util/ConstBuffer.hxx" #include "util/CharUtil.hxx" #include "util/UriUtil.hxx" #include "util/Error.hxx" @@ -35,10 +37,10 @@ #include "TagFile.hxx" #include "storage/StorageInterface.hxx" #include "fs/AllocatedPath.hxx" -#include "fs/FileSystem.hxx" +#include "fs/FileInfo.hxx" #include "fs/DirectoryReader.hxx" +#include "LocateUri.hxx" #include "TimePrint.hxx" -#include "ls.hxx" #include <assert.h> #include <sys/stat.h> @@ -46,7 +48,7 @@ gcc_pure static bool -SkipNameFS(const char *name_fs) +SkipNameFS(PathTraitsFS::const_pointer name_fs) { return name_fs[0] == '.' && (name_fs[1] == 0 || @@ -55,9 +57,9 @@ SkipNameFS(const char *name_fs) gcc_pure static bool -skip_path(const char *name_fs) +skip_path(Path name_fs) { - return strchr(name_fs, '\n') != nullptr; + return name_fs.HasNewline(); } #if defined(WIN32) && GCC_CHECK_VERSION(4,6) @@ -68,28 +70,19 @@ skip_path(const char *name_fs) #endif CommandResult -handle_listfiles_local(Client &client, const char *path_utf8) +handle_listfiles_local(Response &r, + const char *path_utf8, Path path_fs) { - const auto path_fs = AllocatedPath::FromUTF8(path_utf8); - if (path_fs.IsNull()) { - command_error(client, ACK_ERROR_NO_EXIST, - "unsupported file name"); - return CommandResult::ERROR; - } - - Error error; - if (!client.AllowFile(path_fs, error)) - return print_error(client, error); - DirectoryReader reader(path_fs); if (reader.HasFailed()) { + Error error; error.FormatErrno("Failed to open '%s'", path_utf8); - return print_error(client, error); + return print_error(r, error); } while (reader.ReadEntry()) { const Path name_fs = reader.GetEntry(); - if (SkipNameFS(name_fs.c_str()) || skip_path(name_fs.c_str())) + if (SkipNameFS(name_fs.c_str()) || skip_path(name_fs)) continue; std::string name_utf8 = name_fs.ToUTF8(); @@ -98,20 +91,21 @@ handle_listfiles_local(Client &client, const char *path_utf8) const AllocatedPath full_fs = AllocatedPath::Build(path_fs, name_fs); - struct stat st; - if (!StatFile(full_fs, st, false)) + FileInfo fi; + if (!GetFileInfo(full_fs, fi, false)) continue; - if (S_ISREG(st.st_mode)) { - client_printf(client, "file: %s\n" - "size: %" PRIu64 "\n", - name_utf8.c_str(), - uint64_t(st.st_size)); - } else if (S_ISDIR(st.st_mode)) - client_printf(client, "directory: %s\n", - name_utf8.c_str()); + if (fi.IsRegular()) + r.Format("file: %s\n" + "size: %" PRIu64 "\n", + name_utf8.c_str(), + fi.GetSize()); + else if (fi.IsDirectory()) + r.Format("directory: %s\n", name_utf8.c_str()); + else + continue; - time_print(client, "Last-Modified", st.st_mtime); + time_print(r, "Last-Modified", fi.GetModificationTime()); } return CommandResult::OK; @@ -154,10 +148,10 @@ IsValidValue(const char *p) static void print_pair(const char *key, const char *value, void *ctx) { - Client &client = *(Client *)ctx; + auto &r = *(Response *)ctx; if (IsValidName(key) && IsValidValue(value)) - client_printf(client, "%s: %s\n", key, value); + r.Format("%s: %s\n", key, value); } static constexpr tag_handler print_comment_handler = { @@ -167,93 +161,90 @@ static constexpr tag_handler print_comment_handler = { }; static CommandResult -read_stream_comments(Client &client, const char *uri) +read_stream_comments(Response &r, const char *uri) { - if (!uri_supported_scheme(uri)) { - command_error(client, ACK_ERROR_NO_EXIST, - "unsupported URI scheme"); + if (!tag_stream_scan(uri, print_comment_handler, &r)) { + r.Error(ACK_ERROR_NO_EXIST, "Failed to load file"); return CommandResult::ERROR; } - if (!tag_stream_scan(uri, print_comment_handler, &client)) { - command_error(client, ACK_ERROR_NO_EXIST, - "Failed to load file"); + return CommandResult::OK; + +} + +static CommandResult +read_file_comments(Response &r, const Path path_fs) +{ + if (!tag_file_scan(path_fs, print_comment_handler, &r)) { + r.Error(ACK_ERROR_NO_EXIST, "Failed to load file"); return CommandResult::ERROR; } + tag_ape_scan2(path_fs, &print_comment_handler, &r); + tag_id3_scan(path_fs, &print_comment_handler, &r); + return CommandResult::OK; } static CommandResult -read_file_comments(Client &client, const Path path_fs) +read_db_comments(Client &client, Response &r, const char *uri) { - if (!tag_file_scan(path_fs, print_comment_handler, &client)) { - command_error(client, ACK_ERROR_NO_EXIST, - "Failed to load file"); +#ifdef ENABLE_DATABASE + const Storage *storage = client.GetStorage(); + if (storage == nullptr) { +#else + (void)client; + (void)uri; +#endif + r.Error(ACK_ERROR_NO_EXIST, "No database"); return CommandResult::ERROR; +#ifdef ENABLE_DATABASE } - tag_ape_scan2(path_fs, &print_comment_handler, &client); - tag_id3_scan(path_fs, &print_comment_handler, &client); + { + AllocatedPath path_fs = storage->MapFS(uri); + if (!path_fs.IsNull()) + return read_file_comments(r, path_fs); + } - return CommandResult::OK; + { + const std::string uri2 = storage->MapUTF8(uri); + if (uri_has_scheme(uri2.c_str())) + return read_stream_comments(r, uri2.c_str()); + } + r.Error(ACK_ERROR_NO_EXIST, "No such file"); + return CommandResult::ERROR; +#endif } CommandResult -handle_read_comments(Client &client, gcc_unused unsigned argc, char *argv[]) +handle_read_comments(Client &client, Request args, Response &r) { - assert(argc == 2); + assert(args.size == 1); - const char *const uri = argv[1]; + const char *const uri = args.front(); - if (memcmp(uri, "file:///", 8) == 0) { - /* read comments from arbitrary local file */ - const char *path_utf8 = uri + 7; - AllocatedPath path_fs = AllocatedPath::FromUTF8(path_utf8); - if (path_fs.IsNull()) { - command_error(client, ACK_ERROR_NO_EXIST, - "unsupported file name"); - return CommandResult::ERROR; - } - - Error error; - if (!client.AllowFile(path_fs, error)) - return print_error(client, error); - - return read_file_comments(client, path_fs); - } else if (uri_has_scheme(uri)) { - return read_stream_comments(client, uri); - } else if (!PathTraitsUTF8::IsAbsolute(uri)) { -#ifdef ENABLE_DATABASE - const Storage *storage = client.GetStorage(); - if (storage == nullptr) { -#endif - command_error(client, ACK_ERROR_NO_EXIST, - "No database"); - return CommandResult::ERROR; + Error error; + const auto located_uri = LocateUri(uri, &client, #ifdef ENABLE_DATABASE - } - - { - AllocatedPath path_fs = storage->MapFS(uri); - if (!path_fs.IsNull()) - return read_file_comments(client, path_fs); - } - - { - const std::string uri2 = storage->MapUTF8(uri); - if (uri_has_scheme(uri2.c_str())) - return read_stream_comments(client, - uri2.c_str()); - } - - command_error(client, ACK_ERROR_NO_EXIST, "No such file"); - return CommandResult::ERROR; + nullptr, #endif - } else { - command_error(client, ACK_ERROR_NO_EXIST, "No such file"); - return CommandResult::ERROR; + error); + switch (located_uri.type) { + case LocatedUri::Type::UNKNOWN: + return print_error(r, error); + + case LocatedUri::Type::ABSOLUTE: + return read_stream_comments(r, located_uri.canonical_uri); + + case LocatedUri::Type::RELATIVE: + return read_db_comments(client, r, located_uri.canonical_uri); + + case LocatedUri::Type::PATH: + return read_file_comments(r, located_uri.path); } + + gcc_unreachable(); } |