aboutsummaryrefslogtreecommitdiffstats
path: root/src/command/FileCommands.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/command/FileCommands.cxx')
-rw-r--r--src/command/FileCommands.cxx183
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();
}