storage: migrate from class Error to C++ exceptions
This commit is contained in:
parent
cab87e9398
commit
c598686bd9
14
src/Main.cxx
14
src/Main.cxx
@ -161,19 +161,16 @@ glue_mapper_init(Error &error)
|
|||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
InitStorage(Error &error)
|
InitStorage()
|
||||||
{
|
{
|
||||||
Storage *storage = CreateConfiguredStorage(io_thread_get(), error);
|
Storage *storage = CreateConfiguredStorage(io_thread_get());
|
||||||
if (storage == nullptr)
|
if (storage == nullptr)
|
||||||
return !error.IsDefined();
|
return;
|
||||||
|
|
||||||
assert(!error.IsDefined());
|
|
||||||
|
|
||||||
CompositeStorage *composite = new CompositeStorage();
|
CompositeStorage *composite = new CompositeStorage();
|
||||||
instance->storage = composite;
|
instance->storage = composite;
|
||||||
composite->Mount("", storage);
|
composite->Mount("", storage);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,8 +193,7 @@ glue_db_init_and_load(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (instance->database->GetPlugin().flags & DatabasePlugin::FLAG_REQUIRE_STORAGE) {
|
if (instance->database->GetPlugin().flags & DatabasePlugin::FLAG_REQUIRE_STORAGE) {
|
||||||
if (!InitStorage(error))
|
InitStorage();
|
||||||
FatalError(error);
|
|
||||||
|
|
||||||
if (instance->storage == nullptr) {
|
if (instance->storage == nullptr) {
|
||||||
delete instance->database;
|
delete instance->database;
|
||||||
|
@ -68,9 +68,7 @@ Song::UpdateFile(Storage &storage)
|
|||||||
|
|
||||||
StorageFileInfo info;
|
StorageFileInfo info;
|
||||||
try {
|
try {
|
||||||
if (!storage.GetInfo(relative_uri.c_str(), true, info,
|
info = storage.GetInfo(relative_uri.c_str(), true);
|
||||||
IgnoreError()))
|
|
||||||
return false;
|
|
||||||
} catch (const std::runtime_error &) {
|
} catch (const std::runtime_error &) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -58,9 +58,8 @@ skip_path(const char *name_utf8)
|
|||||||
#pragma GCC diagnostic ignored "-Wformat-extra-args"
|
#pragma GCC diagnostic ignored "-Wformat-extra-args"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
handle_listfiles_storage(Response &r, StorageDirectoryReader &reader,
|
handle_listfiles_storage(Response &r, StorageDirectoryReader &reader)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
const char *name_utf8;
|
const char *name_utf8;
|
||||||
while ((name_utf8 = reader.Read()) != nullptr) {
|
while ((name_utf8 = reader.Read()) != nullptr) {
|
||||||
@ -68,8 +67,11 @@ handle_listfiles_storage(Response &r, StorageDirectoryReader &reader,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
StorageFileInfo info;
|
StorageFileInfo info;
|
||||||
if (!reader.GetInfo(false, info, error))
|
try {
|
||||||
|
info = reader.GetInfo(false);
|
||||||
|
} catch (const std::runtime_error &) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (info.type) {
|
switch (info.type) {
|
||||||
case StorageFileInfo::Type::OTHER:
|
case StorageFileInfo::Type::OTHER:
|
||||||
@ -91,53 +93,30 @@ handle_listfiles_storage(Response &r, StorageDirectoryReader &reader,
|
|||||||
if (info.mtime != 0)
|
if (info.mtime != 0)
|
||||||
time_print(r, "Last-Modified", info.mtime);
|
time_print(r, "Last-Modified", info.mtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
|
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool
|
|
||||||
handle_listfiles_storage(Response &r, Storage &storage, const char *uri,
|
|
||||||
Error &error)
|
|
||||||
{
|
|
||||||
std::unique_ptr<StorageDirectoryReader> reader(storage.OpenDirectory(uri, error));
|
|
||||||
if (reader == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return handle_listfiles_storage(r, *reader, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
handle_listfiles_storage(Response &r, Storage &storage, const char *uri)
|
handle_listfiles_storage(Response &r, Storage &storage, const char *uri)
|
||||||
{
|
{
|
||||||
Error error;
|
std::unique_ptr<StorageDirectoryReader> reader(storage.OpenDirectory(uri));
|
||||||
if (!handle_listfiles_storage(r, storage, uri, error))
|
handle_listfiles_storage(r, *reader);
|
||||||
return print_error(r, error);
|
|
||||||
|
|
||||||
return CommandResult::OK;
|
return CommandResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
handle_listfiles_storage(Response &r, const char *uri)
|
handle_listfiles_storage(Response &r, const char *uri)
|
||||||
{
|
{
|
||||||
Error error;
|
std::unique_ptr<Storage> storage(CreateStorageURI(io_thread_get(), uri));
|
||||||
std::unique_ptr<Storage> storage(CreateStorageURI(io_thread_get(), uri,
|
|
||||||
error));
|
|
||||||
if (storage == nullptr) {
|
if (storage == nullptr) {
|
||||||
if (error.IsDefined())
|
|
||||||
return print_error(r, error);
|
|
||||||
|
|
||||||
r.Error(ACK_ERROR_ARG, "Unrecognized storage URI");
|
r.Error(ACK_ERROR_ARG, "Unrecognized storage URI");
|
||||||
return CommandResult::ERROR;
|
return CommandResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handle_listfiles_storage(r, *storage, "", error))
|
return handle_listfiles_storage(r, *storage, "");
|
||||||
return print_error(r, error);
|
|
||||||
|
|
||||||
return CommandResult::OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -217,13 +196,8 @@ handle_mount(Client &client, Request args, Response &r)
|
|||||||
return CommandResult::ERROR;
|
return CommandResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error error;
|
Storage *storage = CreateStorageURI(io_thread_get(), remote_uri);
|
||||||
Storage *storage = CreateStorageURI(io_thread_get(), remote_uri,
|
|
||||||
error);
|
|
||||||
if (storage == nullptr) {
|
if (storage == nullptr) {
|
||||||
if (error.IsDefined())
|
|
||||||
return print_error(r, error);
|
|
||||||
|
|
||||||
r.Error(ACK_ERROR_ARG, "Unrecognized storage URI");
|
r.Error(ACK_ERROR_ARG, "Unrecognized storage URI");
|
||||||
return CommandResult::ERROR;
|
return CommandResult::ERROR;
|
||||||
}
|
}
|
||||||
@ -237,6 +211,7 @@ handle_mount(Client &client, Request args, Response &r)
|
|||||||
SimpleDatabase &db = *(SimpleDatabase *)_db;
|
SimpleDatabase &db = *(SimpleDatabase *)_db;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Error error;
|
||||||
if (!db.Mount(local_uri, remote_uri, error)) {
|
if (!db.Mount(local_uri, remote_uri, error)) {
|
||||||
composite.Unmount(local_uri);
|
composite.Unmount(local_uri);
|
||||||
return print_error(r, error);
|
return print_error(r, error);
|
||||||
|
@ -35,11 +35,8 @@
|
|||||||
bool
|
bool
|
||||||
GetInfo(Storage &storage, const char *uri_utf8, StorageFileInfo &info)
|
GetInfo(Storage &storage, const char *uri_utf8, StorageFileInfo &info)
|
||||||
try {
|
try {
|
||||||
Error error;
|
info = storage.GetInfo(uri_utf8, true);
|
||||||
bool success = storage.GetInfo(uri_utf8, true, info, error);
|
return true;
|
||||||
if (!success)
|
|
||||||
LogError(error);
|
|
||||||
return success;
|
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
LogError(e);
|
LogError(e);
|
||||||
return false;
|
return false;
|
||||||
@ -48,11 +45,8 @@ try {
|
|||||||
bool
|
bool
|
||||||
GetInfo(StorageDirectoryReader &reader, StorageFileInfo &info)
|
GetInfo(StorageDirectoryReader &reader, StorageFileInfo &info)
|
||||||
try {
|
try {
|
||||||
Error error;
|
info = reader.GetInfo(true);
|
||||||
bool success = reader.GetInfo(true, info, error);
|
return true;
|
||||||
if (!success)
|
|
||||||
LogError(error);
|
|
||||||
return success;
|
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
LogError(e);
|
LogError(e);
|
||||||
return false;
|
return false;
|
||||||
@ -64,8 +58,7 @@ DirectoryExists(Storage &storage, const Directory &directory)
|
|||||||
StorageFileInfo info;
|
StorageFileInfo info;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!storage.GetInfo(directory.GetPath(), true, info, IgnoreError()))
|
info = storage.GetInfo(directory.GetPath(), true);
|
||||||
return false;
|
|
||||||
} catch (const std::runtime_error &) {
|
} catch (const std::runtime_error &) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -76,24 +69,22 @@ DirectoryExists(Storage &storage, const Directory &directory)
|
|||||||
: info.IsDirectory();
|
: info.IsDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static StorageFileInfo
|
||||||
GetDirectoryChildInfo(Storage &storage, const Directory &directory,
|
GetDirectoryChildInfo(Storage &storage, const Directory &directory,
|
||||||
const char *name_utf8, StorageFileInfo &info, Error &error)
|
const char *name_utf8)
|
||||||
{
|
{
|
||||||
const auto uri_utf8 = PathTraitsUTF8::Build(directory.GetPath(),
|
const auto uri_utf8 = PathTraitsUTF8::Build(directory.GetPath(),
|
||||||
name_utf8);
|
name_utf8);
|
||||||
return storage.GetInfo(uri_utf8.c_str(), true, info, error);
|
return storage.GetInfo(uri_utf8.c_str(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
directory_child_is_regular(Storage &storage, const Directory &directory,
|
directory_child_is_regular(Storage &storage, const Directory &directory,
|
||||||
const char *name_utf8)
|
const char *name_utf8)
|
||||||
try {
|
try {
|
||||||
StorageFileInfo info;
|
return GetDirectoryChildInfo(storage, directory, name_utf8)
|
||||||
return GetDirectoryChildInfo(storage, directory, name_utf8, info,
|
.IsRegular();
|
||||||
IgnoreError()) &&
|
} catch (const std::runtime_error &) {
|
||||||
info.IsRegular();
|
|
||||||
} catch (const std::runtime_error &) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,12 +338,7 @@ UpdateWalk::UpdateDirectory(Directory &directory,
|
|||||||
std::unique_ptr<StorageDirectoryReader> reader;
|
std::unique_ptr<StorageDirectoryReader> reader;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Error error;
|
reader.reset(storage.OpenDirectory(directory.GetPath()));
|
||||||
reader.reset(storage.OpenDirectory(directory.GetPath(), error));
|
|
||||||
if (!reader) {
|
|
||||||
LogError(error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
LogError(e);
|
LogError(e);
|
||||||
return false;
|
return false;
|
||||||
|
@ -21,16 +21,13 @@
|
|||||||
#include "CompositeStorage.hxx"
|
#include "CompositeStorage.hxx"
|
||||||
#include "FileInfo.hxx"
|
#include "FileInfo.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "util/Domain.hxx"
|
|
||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static constexpr Domain composite_domain("composite");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combines the directory entries of another #StorageDirectoryReader
|
* Combines the directory entries of another #StorageDirectoryReader
|
||||||
* instance and the virtual directory entries.
|
* instance and the virtual directory entries.
|
||||||
@ -57,7 +54,7 @@ public:
|
|||||||
|
|
||||||
/* virtual methods from class StorageDirectoryReader */
|
/* virtual methods from class StorageDirectoryReader */
|
||||||
const char *Read() override;
|
const char *Read() override;
|
||||||
bool GetInfo(bool follow, StorageFileInfo &info, Error &error) override;
|
StorageFileInfo GetInfo(bool follow) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
@ -81,20 +78,20 @@ CompositeDirectoryReader::Read()
|
|||||||
return current->c_str();
|
return current->c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
StorageFileInfo
|
||||||
CompositeDirectoryReader::GetInfo(bool follow, StorageFileInfo &info,
|
CompositeDirectoryReader::GetInfo(bool follow)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
if (other != nullptr)
|
if (other != nullptr)
|
||||||
return other->GetInfo(follow, info, error);
|
return other->GetInfo(follow);
|
||||||
|
|
||||||
assert(current != names.end());
|
assert(current != names.end());
|
||||||
|
|
||||||
|
StorageFileInfo info;
|
||||||
info.type = StorageFileInfo::Type::DIRECTORY;
|
info.type = StorageFileInfo::Type::DIRECTORY;
|
||||||
info.mtime = 0;
|
info.mtime = 0;
|
||||||
info.device = 0;
|
info.device = 0;
|
||||||
info.inode = 0;
|
info.inode = 0;
|
||||||
return true;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string
|
static std::string
|
||||||
@ -266,35 +263,40 @@ CompositeStorage::FindStorage(const char *uri) const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
StorageFileInfo
|
||||||
CompositeStorage::GetInfo(const char *uri, bool follow, StorageFileInfo &info,
|
CompositeStorage::GetInfo(const char *uri, bool follow)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
const ScopeLock protect(mutex);
|
const ScopeLock protect(mutex);
|
||||||
|
|
||||||
|
std::exception_ptr error;
|
||||||
|
|
||||||
auto f = FindStorage(uri);
|
auto f = FindStorage(uri);
|
||||||
if (f.directory->storage != nullptr &&
|
if (f.directory->storage != nullptr) {
|
||||||
f.directory->storage->GetInfo(f.uri, follow, info, error))
|
try {
|
||||||
return true;
|
return f.directory->storage->GetInfo(f.uri, follow);
|
||||||
|
} catch (...) {
|
||||||
|
error = std::current_exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const Directory *directory = f.directory->Find(f.uri);
|
const Directory *directory = f.directory->Find(f.uri);
|
||||||
if (directory != nullptr) {
|
if (directory != nullptr) {
|
||||||
error.Clear();
|
StorageFileInfo info;
|
||||||
info.type = StorageFileInfo::Type::DIRECTORY;
|
info.type = StorageFileInfo::Type::DIRECTORY;
|
||||||
info.mtime = 0;
|
info.mtime = 0;
|
||||||
info.device = 0;
|
info.device = 0;
|
||||||
info.inode = 0;
|
info.inode = 0;
|
||||||
return true;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error.IsDefined())
|
if (error)
|
||||||
error.Set(composite_domain, "No such directory");
|
std::rethrow_exception(error);
|
||||||
return false;
|
else
|
||||||
|
throw std::runtime_error("No such file or directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageDirectoryReader *
|
StorageDirectoryReader *
|
||||||
CompositeStorage::OpenDirectory(const char *uri,
|
CompositeStorage::OpenDirectory(const char *uri)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
const ScopeLock protect(mutex);
|
const ScopeLock protect(mutex);
|
||||||
|
|
||||||
@ -303,16 +305,19 @@ CompositeStorage::OpenDirectory(const char *uri,
|
|||||||
if (directory == nullptr || directory->children.empty()) {
|
if (directory == nullptr || directory->children.empty()) {
|
||||||
/* no virtual directories here */
|
/* no virtual directories here */
|
||||||
|
|
||||||
if (f.directory->storage == nullptr) {
|
if (f.directory->storage == nullptr)
|
||||||
error.Set(composite_domain, "No such directory");
|
throw std::runtime_error("No such directory");
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return f.directory->storage->OpenDirectory(f.uri, error);
|
return f.directory->storage->OpenDirectory(f.uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageDirectoryReader *other = nullptr;
|
||||||
|
|
||||||
|
try {
|
||||||
|
other = f.directory->storage->OpenDirectory(f.uri);
|
||||||
|
} catch (const std::runtime_error &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageDirectoryReader *other =
|
|
||||||
f.directory->storage->OpenDirectory(f.uri, IgnoreError());
|
|
||||||
return new CompositeDirectoryReader(other, directory->children);
|
return new CompositeDirectoryReader(other, directory->children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,8 +28,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
class Error;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A #Storage implementation that combines multiple other #Storage
|
* A #Storage implementation that combines multiple other #Storage
|
||||||
* instances in one virtual tree. It is used to "mount" new #Storage
|
* instances in one virtual tree. It is used to "mount" new #Storage
|
||||||
@ -121,11 +119,9 @@ public:
|
|||||||
bool Unmount(const char *uri);
|
bool Unmount(const char *uri);
|
||||||
|
|
||||||
/* virtual methods from class Storage */
|
/* virtual methods from class Storage */
|
||||||
bool GetInfo(const char *uri, bool follow, StorageFileInfo &info,
|
StorageFileInfo GetInfo(const char *uri, bool follow) override;
|
||||||
Error &error) override;
|
|
||||||
|
|
||||||
StorageDirectoryReader *OpenDirectory(const char *uri,
|
StorageDirectoryReader *OpenDirectory(const char *uri) override;
|
||||||
Error &error) override;
|
|
||||||
|
|
||||||
std::string MapUTF8(const char *uri) const override;
|
std::string MapUTF8(const char *uri) const override;
|
||||||
|
|
||||||
|
@ -27,34 +27,39 @@
|
|||||||
#include "fs/CheckFile.hxx"
|
#include "fs/CheckFile.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
|
#include "util/RuntimeError.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
static Storage *
|
static Storage *
|
||||||
CreateConfiguredStorageUri(EventLoop &event_loop, const char *uri,
|
CreateConfiguredStorageUri(EventLoop &event_loop, const char *uri)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
Storage *storage = CreateStorageURI(event_loop, uri, error);
|
Storage *storage = CreateStorageURI(event_loop, uri);
|
||||||
if (storage == nullptr && !error.IsDefined())
|
if (storage == nullptr)
|
||||||
error.Format(config_domain,
|
throw FormatRuntimeError("Unrecognized storage URI: %s", uri);
|
||||||
"Unrecognized storage URI: %s", uri);
|
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AllocatedPath
|
static AllocatedPath
|
||||||
GetConfiguredMusicDirectory(Error &error)
|
GetConfiguredMusicDirectory()
|
||||||
{
|
{
|
||||||
|
Error error;
|
||||||
AllocatedPath path = config_get_path(ConfigOption::MUSIC_DIR, error);
|
AllocatedPath path = config_get_path(ConfigOption::MUSIC_DIR, error);
|
||||||
if (path.IsNull() && !error.IsDefined())
|
if (path.IsNull()) {
|
||||||
|
if (error.IsDefined())
|
||||||
|
throw std::runtime_error(error.GetMessage());
|
||||||
|
|
||||||
path = GetUserMusicDir();
|
path = GetUserMusicDir();
|
||||||
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Storage *
|
static Storage *
|
||||||
CreateConfiguredStorageLocal(Error &error)
|
CreateConfiguredStorageLocal()
|
||||||
{
|
{
|
||||||
AllocatedPath path = GetConfiguredMusicDirectory(error);
|
AllocatedPath path = GetConfiguredMusicDirectory();
|
||||||
if (path.IsNull())
|
if (path.IsNull())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -64,15 +69,13 @@ CreateConfiguredStorageLocal(Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Storage *
|
Storage *
|
||||||
CreateConfiguredStorage(EventLoop &event_loop, Error &error)
|
CreateConfiguredStorage(EventLoop &event_loop)
|
||||||
{
|
{
|
||||||
assert(!error.IsDefined());
|
|
||||||
|
|
||||||
auto uri = config_get_string(ConfigOption::MUSIC_DIR);
|
auto uri = config_get_string(ConfigOption::MUSIC_DIR);
|
||||||
if (uri != nullptr && uri_has_scheme(uri))
|
if (uri != nullptr && uri_has_scheme(uri))
|
||||||
return CreateConfiguredStorageUri(event_loop, uri, error);
|
return CreateConfiguredStorageUri(event_loop, uri);
|
||||||
|
|
||||||
return CreateConfiguredStorageLocal(error);
|
return CreateConfiguredStorageLocal();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -23,17 +23,17 @@
|
|||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
class Error;
|
|
||||||
class Storage;
|
class Storage;
|
||||||
class EventLoop;
|
class EventLoop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read storage configuration settings and create a #Storage instance
|
* Read storage configuration settings and create a #Storage instance
|
||||||
* from it. Returns nullptr on error or if no storage is configured
|
* from it. Returns nullptr if no storage is configured.
|
||||||
* (no #Error set in that case).
|
*
|
||||||
|
* Throws #std::runtime_error on error.
|
||||||
*/
|
*/
|
||||||
Storage *
|
Storage *
|
||||||
CreateConfiguredStorage(EventLoop &event_loop, Error &error);
|
CreateConfiguredStorage(EventLoop &event_loop);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if there is configuration for a #Storage instance.
|
* Returns true if there is configuration for a #Storage instance.
|
||||||
|
@ -36,14 +36,11 @@ MemoryStorageDirectoryReader::Read()
|
|||||||
return entries.front().name.c_str();
|
return entries.front().name.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
StorageFileInfo
|
||||||
MemoryStorageDirectoryReader::GetInfo(gcc_unused bool follow,
|
MemoryStorageDirectoryReader::GetInfo(gcc_unused bool follow)
|
||||||
StorageFileInfo &info,
|
|
||||||
gcc_unused Error &error)
|
|
||||||
{
|
{
|
||||||
assert(!first);
|
assert(!first);
|
||||||
assert(!entries.empty());
|
assert(!entries.empty());
|
||||||
|
|
||||||
info = entries.front().info;
|
return entries.front().info;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,7 @@ public:
|
|||||||
|
|
||||||
/* virtual methods from class StorageDirectoryReader */
|
/* virtual methods from class StorageDirectoryReader */
|
||||||
const char *Read() override;
|
const char *Read() override;
|
||||||
bool GetInfo(bool follow, StorageFileInfo &info,
|
StorageFileInfo GetInfo(bool follow) override;
|
||||||
Error &error) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include "plugins/LocalStorage.hxx"
|
#include "plugins/LocalStorage.hxx"
|
||||||
#include "plugins/SmbclientStorage.hxx"
|
#include "plugins/SmbclientStorage.hxx"
|
||||||
#include "plugins/NfsStorage.hxx"
|
#include "plugins/NfsStorage.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -52,18 +51,16 @@ GetStoragePluginByName(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Storage *
|
Storage *
|
||||||
CreateStorageURI(EventLoop &event_loop, const char *uri, Error &error)
|
CreateStorageURI(EventLoop &event_loop, const char *uri)
|
||||||
{
|
{
|
||||||
assert(!error.IsDefined());
|
|
||||||
|
|
||||||
for (auto i = storage_plugins; *i != nullptr; ++i) {
|
for (auto i = storage_plugins; *i != nullptr; ++i) {
|
||||||
const StoragePlugin &plugin = **i;
|
const StoragePlugin &plugin = **i;
|
||||||
|
|
||||||
if (plugin.create_uri == nullptr)
|
if (plugin.create_uri == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Storage *storage = plugin.create_uri(event_loop, uri, error);
|
Storage *storage = plugin.create_uri(event_loop, uri);
|
||||||
if (storage != nullptr || error.IsDefined())
|
if (storage != nullptr)
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
struct StoragePlugin;
|
struct StoragePlugin;
|
||||||
class Storage;
|
class Storage;
|
||||||
class Error;
|
|
||||||
class EventLoop;
|
class EventLoop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,6 +39,6 @@ GetStoragePluginByName(const char *name);
|
|||||||
|
|
||||||
gcc_nonnull_all gcc_malloc
|
gcc_nonnull_all gcc_malloc
|
||||||
Storage *
|
Storage *
|
||||||
CreateStorageURI(EventLoop &event_loop, const char *uri, Error &error);
|
CreateStorageURI(EventLoop &event_loop, const char *uri);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
struct StorageFileInfo;
|
struct StorageFileInfo;
|
||||||
class AllocatedPath;
|
class AllocatedPath;
|
||||||
class Error;
|
|
||||||
|
|
||||||
class StorageDirectoryReader {
|
class StorageDirectoryReader {
|
||||||
public:
|
public:
|
||||||
@ -36,8 +35,12 @@ public:
|
|||||||
virtual ~StorageDirectoryReader() {}
|
virtual ~StorageDirectoryReader() {}
|
||||||
|
|
||||||
virtual const char *Read() = 0;
|
virtual const char *Read() = 0;
|
||||||
virtual bool GetInfo(bool follow, StorageFileInfo &info,
|
|
||||||
Error &error) = 0;
|
/**
|
||||||
|
* Throws #std::runtime_error on error.
|
||||||
|
*/
|
||||||
|
gcc_pure
|
||||||
|
virtual StorageFileInfo GetInfo(bool follow) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Storage {
|
class Storage {
|
||||||
@ -46,12 +49,16 @@ public:
|
|||||||
Storage(const Storage &) = delete;
|
Storage(const Storage &) = delete;
|
||||||
virtual ~Storage() {}
|
virtual ~Storage() {}
|
||||||
|
|
||||||
virtual bool GetInfo(const char *uri_utf8, bool follow,
|
/**
|
||||||
StorageFileInfo &info,
|
* Throws #std::runtime_error on error.
|
||||||
Error &error) = 0;
|
*/
|
||||||
|
gcc_pure
|
||||||
|
virtual StorageFileInfo GetInfo(const char *uri_utf8, bool follow) = 0;
|
||||||
|
|
||||||
virtual StorageDirectoryReader *OpenDirectory(const char *uri_utf8,
|
/**
|
||||||
Error &error) = 0;
|
* Throws #std::runtime_error on error.
|
||||||
|
*/
|
||||||
|
virtual StorageDirectoryReader *OpenDirectory(const char *uri_utf8) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map the given relative URI to an absolute URI.
|
* Map the given relative URI to an absolute URI.
|
||||||
|
@ -22,15 +22,16 @@
|
|||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
class Error;
|
|
||||||
class Storage;
|
class Storage;
|
||||||
class EventLoop;
|
class EventLoop;
|
||||||
|
|
||||||
struct StoragePlugin {
|
struct StoragePlugin {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
Storage *(*create_uri)(EventLoop &event_loop, const char *uri,
|
/**
|
||||||
Error &error);
|
* Throws #std::runtime_error on error.
|
||||||
|
*/
|
||||||
|
Storage *(*create_uri)(EventLoop &event_loop, const char *uri);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include "fs/FileInfo.hxx"
|
#include "fs/FileInfo.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "fs/DirectoryReader.hxx"
|
#include "fs/DirectoryReader.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -43,8 +42,7 @@ public:
|
|||||||
|
|
||||||
/* virtual methods from class StorageDirectoryReader */
|
/* virtual methods from class StorageDirectoryReader */
|
||||||
const char *Read() override;
|
const char *Read() override;
|
||||||
bool GetInfo(bool follow, StorageFileInfo &info,
|
StorageFileInfo GetInfo(bool follow) override;
|
||||||
Error &error) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LocalStorage final : public Storage {
|
class LocalStorage final : public Storage {
|
||||||
@ -59,11 +57,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* virtual methods from class Storage */
|
/* virtual methods from class Storage */
|
||||||
bool GetInfo(const char *uri_utf8, bool follow, StorageFileInfo &info,
|
StorageFileInfo GetInfo(const char *uri_utf8, bool follow) override;
|
||||||
Error &error) override;
|
|
||||||
|
|
||||||
StorageDirectoryReader *OpenDirectory(const char *uri_utf8,
|
StorageDirectoryReader *OpenDirectory(const char *uri_utf8) override;
|
||||||
Error &error) override;
|
|
||||||
|
|
||||||
std::string MapUTF8(const char *uri_utf8) const override;
|
std::string MapUTF8(const char *uri_utf8) const override;
|
||||||
|
|
||||||
@ -72,15 +68,15 @@ public:
|
|||||||
const char *MapToRelativeUTF8(const char *uri_utf8) const override;
|
const char *MapToRelativeUTF8(const char *uri_utf8) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AllocatedPath MapFS(const char *uri_utf8, Error &error) const;
|
AllocatedPath MapFSOrThrow(const char *uri_utf8) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
gcc_pure
|
||||||
Stat(Path path, bool follow, StorageFileInfo &info, Error &error)
|
static StorageFileInfo
|
||||||
|
Stat(Path path, bool follow)
|
||||||
{
|
{
|
||||||
FileInfo src;
|
const FileInfo src(path, follow);
|
||||||
if (!GetFileInfo(path, src, follow, error))
|
StorageFileInfo info;
|
||||||
return false;
|
|
||||||
|
|
||||||
if (src.IsRegular())
|
if (src.IsRegular())
|
||||||
info.type = StorageFileInfo::Type::REGULAR;
|
info.type = StorageFileInfo::Type::REGULAR;
|
||||||
@ -97,7 +93,7 @@ Stat(Path path, bool follow, StorageFileInfo &info, Error &error)
|
|||||||
info.device = src.GetDevice();
|
info.device = src.GetDevice();
|
||||||
info.inode = src.GetInode();
|
info.inode = src.GetInode();
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
@ -112,24 +108,25 @@ LocalStorage::MapUTF8(const char *uri_utf8) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
AllocatedPath
|
AllocatedPath
|
||||||
LocalStorage::MapFS(const char *uri_utf8, Error &error) const
|
LocalStorage::MapFSOrThrow(const char *uri_utf8) const
|
||||||
{
|
{
|
||||||
assert(uri_utf8 != nullptr);
|
assert(uri_utf8 != nullptr);
|
||||||
|
|
||||||
if (StringIsEmpty(uri_utf8))
|
if (StringIsEmpty(uri_utf8))
|
||||||
return base_fs;
|
return base_fs;
|
||||||
|
|
||||||
AllocatedPath path_fs = AllocatedPath::FromUTF8(uri_utf8, error);
|
return AllocatedPath::Build(base_fs,
|
||||||
if (!path_fs.IsNull())
|
AllocatedPath::FromUTF8Throw(uri_utf8));
|
||||||
path_fs = AllocatedPath::Build(base_fs, path_fs);
|
|
||||||
|
|
||||||
return path_fs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AllocatedPath
|
AllocatedPath
|
||||||
LocalStorage::MapFS(const char *uri_utf8) const
|
LocalStorage::MapFS(const char *uri_utf8) const
|
||||||
{
|
{
|
||||||
return MapFS(uri_utf8, IgnoreError());
|
try {
|
||||||
|
return MapFSOrThrow(uri_utf8);
|
||||||
|
} catch (const std::runtime_error &) {
|
||||||
|
return AllocatedPath::Null();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
@ -138,25 +135,16 @@ LocalStorage::MapToRelativeUTF8(const char *uri_utf8) const
|
|||||||
return PathTraitsUTF8::Relative(base_utf8.c_str(), uri_utf8);
|
return PathTraitsUTF8::Relative(base_utf8.c_str(), uri_utf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
StorageFileInfo
|
||||||
LocalStorage::GetInfo(const char *uri_utf8, bool follow, StorageFileInfo &info,
|
LocalStorage::GetInfo(const char *uri_utf8, bool follow)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
AllocatedPath path_fs = MapFS(uri_utf8, error);
|
return Stat(MapFSOrThrow(uri_utf8), follow);
|
||||||
if (path_fs.IsNull())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return Stat(path_fs, follow, info, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageDirectoryReader *
|
StorageDirectoryReader *
|
||||||
LocalStorage::OpenDirectory(const char *uri_utf8, Error &error)
|
LocalStorage::OpenDirectory(const char *uri_utf8)
|
||||||
{
|
{
|
||||||
AllocatedPath path_fs = MapFS(uri_utf8, error);
|
return new LocalDirectoryReader(MapFSOrThrow(uri_utf8));
|
||||||
if (path_fs.IsNull())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return new LocalDirectoryReader(std::move(path_fs));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
@ -186,12 +174,10 @@ LocalDirectoryReader::Read()
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
StorageFileInfo
|
||||||
LocalDirectoryReader::GetInfo(bool follow, StorageFileInfo &info, Error &error)
|
LocalDirectoryReader::GetInfo(bool follow)
|
||||||
{
|
{
|
||||||
const AllocatedPath path_fs =
|
return Stat(AllocatedPath::Build(base_fs, reader.GetEntry()), follow);
|
||||||
AllocatedPath::Build(base_fs, reader.GetEntry());
|
|
||||||
return Stat(path_fs, follow, info, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage *
|
Storage *
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
#include "event/Call.hxx"
|
#include "event/Call.hxx"
|
||||||
#include "event/DeferredMonitor.hxx"
|
#include "event/DeferredMonitor.hxx"
|
||||||
#include "event/TimeoutMonitor.hxx"
|
#include "event/TimeoutMonitor.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -84,11 +83,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* virtual methods from class Storage */
|
/* virtual methods from class Storage */
|
||||||
bool GetInfo(const char *uri_utf8, bool follow, StorageFileInfo &info,
|
StorageFileInfo GetInfo(const char *uri_utf8, bool follow) override;
|
||||||
Error &error) override;
|
|
||||||
|
|
||||||
StorageDirectoryReader *OpenDirectory(const char *uri_utf8,
|
StorageDirectoryReader *OpenDirectory(const char *uri_utf8) override;
|
||||||
Error &error) override;
|
|
||||||
|
|
||||||
std::string MapUTF8(const char *uri_utf8) const override;
|
std::string MapUTF8(const char *uri_utf8) const override;
|
||||||
|
|
||||||
@ -214,7 +211,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static std::string
|
static std::string
|
||||||
UriToNfsPath(const char *_uri_utf8, Error &error)
|
UriToNfsPath(const char *_uri_utf8)
|
||||||
{
|
{
|
||||||
assert(_uri_utf8 != nullptr);
|
assert(_uri_utf8 != nullptr);
|
||||||
|
|
||||||
@ -222,7 +219,7 @@ UriToNfsPath(const char *_uri_utf8, Error &error)
|
|||||||
std::string uri_utf8("/");
|
std::string uri_utf8("/");
|
||||||
uri_utf8.append(_uri_utf8);
|
uri_utf8.append(_uri_utf8);
|
||||||
|
|
||||||
return AllocatedPath::FromUTF8(uri_utf8.c_str(), error).Steal();
|
return AllocatedPath::FromUTF8Throw(uri_utf8.c_str()).Steal();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
@ -260,12 +257,15 @@ Copy(StorageFileInfo &info, const struct stat &st)
|
|||||||
|
|
||||||
class NfsGetInfoOperation final : public BlockingNfsOperation {
|
class NfsGetInfoOperation final : public BlockingNfsOperation {
|
||||||
const char *const path;
|
const char *const path;
|
||||||
StorageFileInfo &info;
|
StorageFileInfo info;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NfsGetInfoOperation(NfsConnection &_connection, const char *_path,
|
NfsGetInfoOperation(NfsConnection &_connection, const char *_path)
|
||||||
StorageFileInfo &_info)
|
:BlockingNfsOperation(_connection), path(_path) {}
|
||||||
:BlockingNfsOperation(_connection), path(_path), info(_info) {}
|
|
||||||
|
const StorageFileInfo &GetInfo() const {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Start() override {
|
void Start() override {
|
||||||
@ -277,19 +277,16 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
StorageFileInfo
|
||||||
NfsStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow,
|
NfsStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow)
|
||||||
StorageFileInfo &info, Error &error)
|
|
||||||
{
|
{
|
||||||
const std::string path = UriToNfsPath(uri_utf8, error);
|
const std::string path = UriToNfsPath(uri_utf8);
|
||||||
if (path.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
WaitConnected();
|
WaitConnected();
|
||||||
|
|
||||||
NfsGetInfoOperation operation(*connection, path.c_str(), info);
|
NfsGetInfoOperation operation(*connection, path.c_str());
|
||||||
operation.Run();
|
operation.Run();
|
||||||
return true;
|
return operation.GetInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
@ -377,11 +374,9 @@ NfsListDirectoryOperation::CollectEntries(struct nfsdir *dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
StorageDirectoryReader *
|
StorageDirectoryReader *
|
||||||
NfsStorage::OpenDirectory(const char *uri_utf8, Error &error)
|
NfsStorage::OpenDirectory(const char *uri_utf8)
|
||||||
{
|
{
|
||||||
const std::string path = UriToNfsPath(uri_utf8, error);
|
const std::string path = UriToNfsPath(uri_utf8);
|
||||||
if (path.empty())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
WaitConnected();
|
WaitConnected();
|
||||||
|
|
||||||
@ -392,7 +387,7 @@ NfsStorage::OpenDirectory(const char *uri_utf8, Error &error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Storage *
|
static Storage *
|
||||||
CreateNfsStorageURI(EventLoop &event_loop, const char *base, Error &)
|
CreateNfsStorageURI(EventLoop &event_loop, const char *base)
|
||||||
{
|
{
|
||||||
if (memcmp(base, "nfs://", 6) != 0)
|
if (memcmp(base, "nfs://", 6) != 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -26,8 +26,9 @@
|
|||||||
#include "lib/smbclient/Mutex.hxx"
|
#include "lib/smbclient/Mutex.hxx"
|
||||||
#include "fs/Traits.hxx"
|
#include "fs/Traits.hxx"
|
||||||
#include "thread/Mutex.hxx"
|
#include "thread/Mutex.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "system/Error.hxx"
|
||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
|
#include "util/ScopeExit.hxx"
|
||||||
|
|
||||||
#include <libsmbclient.h>
|
#include <libsmbclient.h>
|
||||||
|
|
||||||
@ -45,8 +46,7 @@ public:
|
|||||||
|
|
||||||
/* virtual methods from class StorageDirectoryReader */
|
/* virtual methods from class StorageDirectoryReader */
|
||||||
const char *Read() override;
|
const char *Read() override;
|
||||||
bool GetInfo(bool follow, StorageFileInfo &info,
|
StorageFileInfo GetInfo(bool follow) override;
|
||||||
Error &error) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SmbclientStorage final : public Storage {
|
class SmbclientStorage final : public Storage {
|
||||||
@ -65,11 +65,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* virtual methods from class Storage */
|
/* virtual methods from class Storage */
|
||||||
bool GetInfo(const char *uri_utf8, bool follow, StorageFileInfo &info,
|
StorageFileInfo GetInfo(const char *uri_utf8, bool follow) override;
|
||||||
Error &error) override;
|
|
||||||
|
|
||||||
StorageDirectoryReader *OpenDirectory(const char *uri_utf8,
|
StorageDirectoryReader *OpenDirectory(const char *uri_utf8) override;
|
||||||
Error &error) override;
|
|
||||||
|
|
||||||
std::string MapUTF8(const char *uri_utf8) const override;
|
std::string MapUTF8(const char *uri_utf8) const override;
|
||||||
|
|
||||||
@ -93,18 +91,18 @@ SmbclientStorage::MapToRelativeUTF8(const char *uri_utf8) const
|
|||||||
return PathTraitsUTF8::Relative(base.c_str(), uri_utf8);
|
return PathTraitsUTF8::Relative(base.c_str(), uri_utf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static StorageFileInfo
|
||||||
GetInfo(const char *path, StorageFileInfo &info, Error &error)
|
GetInfo(const char *path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
smbclient_mutex.lock();
|
|
||||||
bool success = smbc_stat(path, &st) == 0;
|
{
|
||||||
smbclient_mutex.unlock();
|
const ScopeLock protect(smbclient_mutex);
|
||||||
if (!success) {
|
if (smbc_stat(path, &st) != 0)
|
||||||
error.SetErrno();
|
throw MakeErrno("Failed to access file");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StorageFileInfo info;
|
||||||
if (S_ISREG(st.st_mode))
|
if (S_ISREG(st.st_mode))
|
||||||
info.type = StorageFileInfo::Type::REGULAR;
|
info.type = StorageFileInfo::Type::REGULAR;
|
||||||
else if (S_ISDIR(st.st_mode))
|
else if (S_ISDIR(st.st_mode))
|
||||||
@ -116,27 +114,28 @@ GetInfo(const char *path, StorageFileInfo &info, Error &error)
|
|||||||
info.mtime = st.st_mtime;
|
info.mtime = st.st_mtime;
|
||||||
info.device = st.st_dev;
|
info.device = st.st_dev;
|
||||||
info.inode = st.st_ino;
|
info.inode = st.st_ino;
|
||||||
return true;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
StorageFileInfo
|
||||||
SmbclientStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow,
|
SmbclientStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow)
|
||||||
StorageFileInfo &info, Error &error)
|
|
||||||
{
|
{
|
||||||
const std::string mapped = MapUTF8(uri_utf8);
|
const std::string mapped = MapUTF8(uri_utf8);
|
||||||
return ::GetInfo(mapped.c_str(), info, error);
|
return ::GetInfo(mapped.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageDirectoryReader *
|
StorageDirectoryReader *
|
||||||
SmbclientStorage::OpenDirectory(const char *uri_utf8, Error &error)
|
SmbclientStorage::OpenDirectory(const char *uri_utf8)
|
||||||
{
|
{
|
||||||
std::string mapped = MapUTF8(uri_utf8);
|
std::string mapped = MapUTF8(uri_utf8);
|
||||||
smbclient_mutex.lock();
|
|
||||||
int handle = smbc_opendir(mapped.c_str());
|
int handle;
|
||||||
smbclient_mutex.unlock();
|
|
||||||
if (handle < 0) {
|
{
|
||||||
error.SetErrno();
|
const ScopeLock protect(smbclient_mutex);
|
||||||
return nullptr;
|
handle = smbc_opendir(mapped.c_str());
|
||||||
|
if (handle < 0)
|
||||||
|
throw MakeErrno("Failed to open directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SmbclientDirectoryReader(std::move(mapped.c_str()), handle);
|
return new SmbclientDirectoryReader(std::move(mapped.c_str()), handle);
|
||||||
@ -173,18 +172,15 @@ SmbclientDirectoryReader::Read()
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
StorageFileInfo
|
||||||
SmbclientDirectoryReader::GetInfo(gcc_unused bool follow,
|
SmbclientDirectoryReader::GetInfo(gcc_unused bool follow)
|
||||||
StorageFileInfo &info,
|
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
const std::string path = PathTraitsUTF8::Build(base.c_str(), name);
|
const std::string path = PathTraitsUTF8::Build(base.c_str(), name);
|
||||||
return ::GetInfo(path.c_str(), info, error);
|
return ::GetInfo(path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Storage *
|
static Storage *
|
||||||
CreateSmbclientStorageURI(gcc_unused EventLoop &event_loop, const char *base,
|
CreateSmbclientStorageURI(gcc_unused EventLoop &event_loop, const char *base)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
if (memcmp(base, "smb://", 6) != 0)
|
if (memcmp(base, "smb://", 6) != 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -193,16 +189,13 @@ CreateSmbclientStorageURI(gcc_unused EventLoop &event_loop, const char *base,
|
|||||||
|
|
||||||
const ScopeLock protect(smbclient_mutex);
|
const ScopeLock protect(smbclient_mutex);
|
||||||
SMBCCTX *ctx = smbc_new_context();
|
SMBCCTX *ctx = smbc_new_context();
|
||||||
if (ctx == nullptr) {
|
if (ctx == nullptr)
|
||||||
error.SetErrno("smbc_new_context() failed");
|
throw MakeErrno("smbc_new_context() failed");
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
SMBCCTX *ctx2 = smbc_init_context(ctx);
|
SMBCCTX *ctx2 = smbc_init_context(ctx);
|
||||||
if (ctx2 == nullptr) {
|
if (ctx2 == nullptr) {
|
||||||
error.SetErrno("smbc_init_context() failed");
|
AtScopeExit(ctx) { smbc_free_context(ctx, 1); };
|
||||||
smbc_free_context(ctx, 1);
|
throw MakeErrno("smbc_new_context() failed");
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SmbclientStorage(base, ctx2);
|
return new SmbclientStorage(base, ctx2);
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "Log.hxx"
|
||||||
#include "ScopeIOThread.hxx"
|
#include "ScopeIOThread.hxx"
|
||||||
#include "storage/Registry.hxx"
|
#include "storage/Registry.hxx"
|
||||||
#include "storage/StorageInterface.hxx"
|
#include "storage/StorageInterface.hxx"
|
||||||
@ -25,6 +26,7 @@
|
|||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -35,12 +37,9 @@
|
|||||||
static Storage *
|
static Storage *
|
||||||
MakeStorage(const char *uri)
|
MakeStorage(const char *uri)
|
||||||
{
|
{
|
||||||
Error error;
|
Storage *storage = CreateStorageURI(io_thread_get(), uri);
|
||||||
Storage *storage = CreateStorageURI(io_thread_get(), uri, error);
|
if (storage == nullptr)
|
||||||
if (storage == nullptr) {
|
throw std::runtime_error("Unrecognized storage URI");
|
||||||
fprintf(stderr, "%s\n", error.GetMessage());
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
@ -48,21 +47,11 @@ MakeStorage(const char *uri)
|
|||||||
static int
|
static int
|
||||||
Ls(Storage &storage, const char *path)
|
Ls(Storage &storage, const char *path)
|
||||||
{
|
{
|
||||||
Error error;
|
auto dir = storage.OpenDirectory(path);
|
||||||
auto dir = storage.OpenDirectory(path, error);
|
|
||||||
if (dir == nullptr) {
|
|
||||||
fprintf(stderr, "%s\n", error.GetMessage());
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *name;
|
const char *name;
|
||||||
while ((name = dir->Read()) != nullptr) {
|
while ((name = dir->Read()) != nullptr) {
|
||||||
StorageFileInfo info;
|
const auto info = dir->GetInfo(false);
|
||||||
if (!dir->GetInfo(false, info, error)) {
|
|
||||||
printf("Error on %s: %s\n", name, error.GetMessage());
|
|
||||||
error.Clear();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *type = "unk";
|
const char *type = "unk";
|
||||||
switch (info.type) {
|
switch (info.type) {
|
||||||
@ -93,7 +82,7 @@ Ls(Storage &storage, const char *path)
|
|||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
try {
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
fprintf(stderr, "Usage: run_storage COMMAND URI ...\n");
|
fprintf(stderr, "Usage: run_storage COMMAND URI ...\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@ -119,4 +108,9 @@ main(int argc, char **argv)
|
|||||||
fprintf(stderr, "Unknown command\n");
|
fprintf(stderr, "Unknown command\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
LogError(e);
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user