diff options
51 files changed, 621 insertions, 394 deletions
diff --git a/Makefile.am b/Makefile.am index 7cc43157a..103975faa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -348,6 +348,7 @@ libfs_a_SOURCES = \ src/fs/Config.cxx src/fs/Config.hxx \ src/fs/Charset.cxx src/fs/Charset.hxx \ src/fs/Path.cxx src/fs/Path.hxx \ + src/fs/AllocatedPath.cxx src/fs/AllocatedPath.hxx \ src/fs/FileSystem.cxx src/fs/FileSystem.hxx \ src/fs/DirectoryReader.hxx diff --git a/src/ClientFile.cxx b/src/ClientFile.cxx index a460310be..f2cb01aff 100644 --- a/src/ClientFile.cxx +++ b/src/ClientFile.cxx @@ -32,8 +32,7 @@ #include <unistd.h> bool -client_allow_file(const Client *client, const Path &path_fs, - Error &error) +client_allow_file(const Client *client, Path path_fs, Error &error) { #ifdef WIN32 (void)client; diff --git a/src/ClientFile.hxx b/src/ClientFile.hxx index 68d79ca08..43af72e93 100644 --- a/src/ClientFile.hxx +++ b/src/ClientFile.hxx @@ -35,7 +35,6 @@ class Error; * @return true if access is allowed */ bool -client_allow_file(const Client *client, const Path &path_fs, - Error &error); +client_allow_file(const Client *client, Path path_fs, Error &error); #endif diff --git a/src/CommandLine.cxx b/src/CommandLine.cxx index b55f2bec4..1f39e47aa 100644 --- a/src/CommandLine.cxx +++ b/src/CommandLine.cxx @@ -31,7 +31,7 @@ #include "InputPlugin.hxx" #include "PlaylistRegistry.hxx" #include "PlaylistPlugin.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/FileSystem.hxx" #include "util/Error.hxx" @@ -136,13 +136,13 @@ static const char *summary = "Music Player Daemon - a daemon for playing music."; gcc_pure -static Path -PathBuildChecked(const Path &a, PathTraits::const_pointer b) +static AllocatedPath +PathBuildChecked(const AllocatedPath &a, PathTraits::const_pointer b) { if (a.IsNull()) - return Path::Null(); + return AllocatedPath::Null(); - return Path::Build(a, b); + return AllocatedPath::Build(a, b); } bool @@ -206,7 +206,7 @@ parse_cmdline(int argc, char **argv, struct options *options, /* default configuration file path */ #ifdef WIN32 - Path path = PathBuildChecked(Path::FromUTF8(g_get_user_config_dir()), + AllocatedPath path = PathBuildChecked(AllocatedPath::FromUTF8(g_get_user_config_dir()), CONFIG_FILE_LOCATION); if (!path.IsNull() && FileExists(path)) return ReadConfigFile(path, error); @@ -215,28 +215,28 @@ parse_cmdline(int argc, char **argv, struct options *options, g_get_system_config_dirs(); for (unsigned i = 0; system_config_dirs[i] != nullptr; ++i) { - path = PathBuildChecked(Path::FromUTF8(system_config_dirs[i]), + path = PathBuildChecked(AllocatedPath::FromUTF8(system_config_dirs[i]), CONFIG_FILE_LOCATION); if (!path.IsNull() && FileExists(path)) return ReadConfigFile(path, error); } #else - Path path = PathBuildChecked(Path::FromUTF8(g_get_user_config_dir()), - USER_CONFIG_FILE_LOCATION_XDG); + AllocatedPath path = PathBuildChecked(AllocatedPath::FromUTF8(g_get_user_config_dir()), + USER_CONFIG_FILE_LOCATION_XDG); if (!path.IsNull() && FileExists(path)) return ReadConfigFile(path, error); - path = PathBuildChecked(Path::FromUTF8(g_get_home_dir()), + path = PathBuildChecked(AllocatedPath::FromUTF8(g_get_home_dir()), USER_CONFIG_FILE_LOCATION1); if (!path.IsNull() && FileExists(path)) return ReadConfigFile(path, error); - path = PathBuildChecked(Path::FromUTF8(g_get_home_dir()), + path = PathBuildChecked(AllocatedPath::FromUTF8(g_get_home_dir()), USER_CONFIG_FILE_LOCATION2); if (!path.IsNull() && FileExists(path)) return ReadConfigFile(path, error); - path = Path::FromUTF8(SYSTEM_CONFIG_FILE_LOCATION); + path = AllocatedPath::FromUTF8(SYSTEM_CONFIG_FILE_LOCATION); if (!path.IsNull() && FileExists(path)) return ReadConfigFile(path, error); #endif diff --git a/src/ConfigData.cxx b/src/ConfigData.cxx index 9655d6400..395d768f6 100644 --- a/src/ConfigData.cxx +++ b/src/ConfigData.cxx @@ -22,7 +22,7 @@ #include "ConfigParser.hxx" #include "ConfigPath.hxx" #include "util/Error.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "system/FatalError.hxx" #include <assert.h> @@ -86,7 +86,7 @@ config_param::GetBlockValue(const char *name, const char *default_value) const return bp->value.c_str(); } -Path +AllocatedPath config_param::GetBlockPath(const char *name, const char *default_value, Error &error) const { @@ -101,12 +101,12 @@ config_param::GetBlockPath(const char *name, const char *default_value, s = bp->value.c_str(); } else { if (default_value == nullptr) - return Path::Null(); + return AllocatedPath::Null(); s = default_value; } - Path path = ParsePath(s, error); + AllocatedPath path = ParsePath(s, error); if (gcc_unlikely(path.IsNull())) error.FormatPrefix("Invalid path in \"%s\" at line %i: ", name, line2); @@ -114,7 +114,7 @@ config_param::GetBlockPath(const char *name, const char *default_value, return path; } -Path +AllocatedPath config_param::GetBlockPath(const char *name, Error &error) const { return GetBlockPath(name, nullptr, error); diff --git a/src/ConfigData.hxx b/src/ConfigData.hxx index 83c9bd477..d85228cc3 100644 --- a/src/ConfigData.hxx +++ b/src/ConfigData.hxx @@ -27,7 +27,7 @@ #include <array> #include <vector> -class Path; +class AllocatedPath; class Error; struct block_param { @@ -109,10 +109,10 @@ struct config_param { * Same as config_dup_path(), but looks up the setting in the * specified block. */ - Path GetBlockPath(const char *name, const char *default_value, - Error &error) const; + AllocatedPath GetBlockPath(const char *name, const char *default_value, + Error &error) const; - Path GetBlockPath(const char *name, Error &error) const; + AllocatedPath GetBlockPath(const char *name, Error &error) const; gcc_pure unsigned GetBlockValue(const char *name, unsigned default_value) const; diff --git a/src/ConfigFile.cxx b/src/ConfigFile.cxx index eacaae5bb..5f614516e 100644 --- a/src/ConfigFile.cxx +++ b/src/ConfigFile.cxx @@ -253,7 +253,7 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, Error &error) } bool -ReadConfigFile(ConfigData &config_data, const Path &path, Error &error) +ReadConfigFile(ConfigData &config_data, Path path, Error &error) { assert(!path.IsNull()); const std::string path_utf8 = path.ToUTF8(); diff --git a/src/ConfigFile.hxx b/src/ConfigFile.hxx index 0dca65567..8c4ddbbd3 100644 --- a/src/ConfigFile.hxx +++ b/src/ConfigFile.hxx @@ -25,6 +25,6 @@ class Path; struct ConfigData; bool -ReadConfigFile(ConfigData &data, const Path &path, Error &error); +ReadConfigFile(ConfigData &data, Path path, Error &error); #endif diff --git a/src/ConfigGlobal.cxx b/src/ConfigGlobal.cxx index e23462e94..99932f621 100644 --- a/src/ConfigGlobal.cxx +++ b/src/ConfigGlobal.cxx @@ -25,6 +25,7 @@ #include "ConfigPath.hxx" #include "ConfigError.hxx" #include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "util/Error.hxx" #include "system/FatalError.hxx" #include "Log.hxx" @@ -45,7 +46,7 @@ void config_global_init(void) } bool -ReadConfigFile(const Path &path, Error &error) +ReadConfigFile(Path path, Error &error) { return ReadConfigFile(config_data, path, error); } @@ -96,20 +97,20 @@ config_get_string(ConfigOption option, const char *default_value) return param->value.c_str(); } -Path +AllocatedPath config_get_path(ConfigOption option, Error &error) { const struct config_param *param = config_get_param(option); if (param == nullptr) - return Path::Null(); + return AllocatedPath::Null(); return config_parse_path(param, error); } -Path +AllocatedPath config_parse_path(const struct config_param *param, Error & error) { - Path path = ParsePath(param->value.c_str(), error); + AllocatedPath path = ParsePath(param->value.c_str(), error); if (gcc_unlikely(path.IsNull())) error.FormatPrefix("Invalid path at line %i: ", param->line); diff --git a/src/ConfigGlobal.hxx b/src/ConfigGlobal.hxx index 2beb2cb5b..978db3145 100644 --- a/src/ConfigGlobal.hxx +++ b/src/ConfigGlobal.hxx @@ -25,6 +25,7 @@ class Error; class Path; +class AllocatedPath; void config_global_init(void); void config_global_finish(void); @@ -36,7 +37,7 @@ void config_global_finish(void); void config_global_check(void); bool -ReadConfigFile(const Path &path, Error &error); +ReadConfigFile(Path path, Error &error); /* don't free the returned value set _last_ to nullptr to get first entry */ @@ -66,18 +67,18 @@ config_get_string(enum ConfigOption option, const char *default_value); /** * Returns an optional configuration variable which contains an * absolute path. If there is a tilde prefix, it is expanded. - * Returns Path::Null() if the value is not present. If the path - * could not be parsed, returns Path::Null() and sets the error. + * Returns AllocatedPath::Null() if the value is not present. If the path + * could not be parsed, returns AllocatedPath::Null() and sets the error. */ -Path +AllocatedPath config_get_path(enum ConfigOption option, Error &error); /** * Parse a configuration parameter as a path. * If there is a tilde prefix, it is expanded. If the path could - * not be parsed, returns Path::Null() and sets the error. + * not be parsed, returns AllocatedPath::Null() and sets the error. */ -Path +AllocatedPath config_parse_path(const struct config_param *param, Error & error_r); gcc_pure diff --git a/src/ConfigPath.cxx b/src/ConfigPath.cxx index ae97275b3..2f3f3ad23 100644 --- a/src/ConfigPath.cxx +++ b/src/ConfigPath.cxx @@ -19,7 +19,7 @@ #include "config.h" #include "ConfigPath.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/Domain.hxx" #include "util/Error.hxx" @@ -36,39 +36,39 @@ /** * Determine a given user's home directory. */ -static Path +static AllocatedPath GetHome(const char *user, Error &error) { passwd *pw = getpwnam(user); if (pw == nullptr) { error.Format(path_domain, "no such user: %s", user); - return Path::Null(); + return AllocatedPath::Null(); } - return Path::FromFS(pw->pw_dir); + return AllocatedPath::FromFS(pw->pw_dir); } /** * Determine the current user's home directory. */ -static Path +static AllocatedPath GetHome(Error &error) { const char *home = g_get_home_dir(); if (home == nullptr) { error.Set(path_domain, "problems getting home for current user"); - return Path::Null(); + return AllocatedPath::Null(); } - return Path::FromUTF8(home, error); + return AllocatedPath::FromUTF8(home, error); } /** * Determine the configured user's home directory. */ -static Path +static AllocatedPath GetConfiguredHome(Error &error) { const char *user = config_get_string(CONF_USER, nullptr); @@ -79,7 +79,7 @@ GetConfiguredHome(Error &error) #endif -Path +AllocatedPath ParsePath(const char *path, Error &error) { assert(path != nullptr); @@ -91,7 +91,7 @@ ParsePath(const char *path, Error &error) if (*path == '\0') return GetConfiguredHome(error); - Path home = Path::Null(); + AllocatedPath home = AllocatedPath::Null(); if (*path == '/') { home = GetConfiguredHome(error); @@ -113,20 +113,20 @@ ParsePath(const char *path, Error &error) } if (home.IsNull()) - return Path::Null(); + return AllocatedPath::Null(); - Path path2 = Path::FromUTF8(path, error); + AllocatedPath path2 = AllocatedPath::FromUTF8(path, error); if (path2.IsNull()) - return Path::Null(); + return AllocatedPath::Null(); - return Path::Build(home, path2); + return AllocatedPath::Build(home, path2); } else if (!PathTraits::IsAbsoluteUTF8(path)) { error.Format(path_domain, "not an absolute path: %s", path); - return Path::Null(); + return AllocatedPath::Null(); } else { #endif - return Path::FromUTF8(path, error); + return AllocatedPath::FromUTF8(path, error); #ifndef WIN32 } #endif diff --git a/src/ConfigPath.hxx b/src/ConfigPath.hxx index 7bc1d732c..99abd85b7 100644 --- a/src/ConfigPath.hxx +++ b/src/ConfigPath.hxx @@ -20,10 +20,10 @@ #ifndef MPD_CONFIG_PATH_HXX #define MPD_CONFIG_PATH_HXX -class Path; +class AllocatedPath; class Error; -Path +AllocatedPath ParsePath(const char *path, Error &error); #endif diff --git a/src/Daemon.cxx b/src/Daemon.cxx index 8e22ed131..4f214517e 100644 --- a/src/Daemon.cxx +++ b/src/Daemon.cxx @@ -20,7 +20,7 @@ #include "config.h" #include "Daemon.hxx" #include "system/FatalError.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "util/Domain.hxx" #include "Log.hxx" @@ -55,7 +55,7 @@ static uid_t user_uid = (uid_t)-1; static gid_t user_gid = (pid_t)-1; /** the absolute path of the pidfile */ -static Path pidfile = Path::Null(); +static AllocatedPath pidfile = AllocatedPath::Null(); /* whether "group" conf. option was given */ static bool had_group = false; @@ -202,7 +202,7 @@ daemonize(bool detach) } void -daemonize_init(const char *user, const char *group, Path &&_pidfile) +daemonize_init(const char *user, const char *group, AllocatedPath &&_pidfile) { if (user) { struct passwd *pwd = getpwnam(user); @@ -235,7 +235,7 @@ daemonize_finish(void) { if (!pidfile.IsNull()) { RemoveFile(pidfile); - pidfile = Path::Null(); + pidfile = AllocatedPath::Null(); } g_free(user_name); diff --git a/src/Daemon.hxx b/src/Daemon.hxx index c662b9bee..ecd090d5b 100644 --- a/src/Daemon.hxx +++ b/src/Daemon.hxx @@ -20,14 +20,14 @@ #ifndef MPD_DAEMON_HXX #define MPD_DAEMON_HXX -class Path; +class AllocatedPath; #ifndef WIN32 void -daemonize_init(const char *user, const char *group, Path &&pidfile); +daemonize_init(const char *user, const char *group, AllocatedPath &&pidfile); #else static inline void -daemonize_init(const char *user, const char *group, Path &&pidfile) +daemonize_init(const char *user, const char *group, AllocatedPath &&pidfile) { (void)user; (void)group; (void)pidfile; } #endif diff --git a/src/DecoderThread.cxx b/src/DecoderThread.cxx index 3a282451a..1f85cd835 100644 --- a/src/DecoderThread.cxx +++ b/src/DecoderThread.cxx @@ -27,7 +27,7 @@ #include "system/FatalError.hxx" #include "Mapper.hxx" #include "fs/Traits.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "DecoderAPI.hxx" #include "tag/Tag.hxx" #include "InputStream.hxx" diff --git a/src/ExcludeList.cxx b/src/ExcludeList.cxx index 16bdbf383..c6b0d1469 100644 --- a/src/ExcludeList.cxx +++ b/src/ExcludeList.cxx @@ -37,7 +37,7 @@ static constexpr Domain exclude_list_domain("exclude_list"); bool -ExcludeList::LoadFile(const Path &path_fs) +ExcludeList::LoadFile(Path path_fs) { FILE *file = FOpen(path_fs, FOpenMode::ReadText); if (file == NULL) { @@ -69,7 +69,7 @@ ExcludeList::LoadFile(const Path &path_fs) } bool -ExcludeList::Check(const Path &name_fs) const +ExcludeList::Check(Path name_fs) const { assert(!name_fs.IsNull()); diff --git a/src/ExcludeList.hxx b/src/ExcludeList.hxx index 03513ef8b..61fdacef8 100644 --- a/src/ExcludeList.hxx +++ b/src/ExcludeList.hxx @@ -67,13 +67,13 @@ public: /** * Loads and parses a .mpdignore file. */ - bool LoadFile(const Path &path_fs); + bool LoadFile(Path path_fs); /** * Checks whether one of the patterns in the .mpdignore file matches * the specified file name. */ - bool Check(const Path &name_fs) const; + bool Check(Path name_fs) const; }; diff --git a/src/InotifyUpdate.cxx b/src/InotifyUpdate.cxx index e1fe53b05..4a93f557b 100644 --- a/src/InotifyUpdate.cxx +++ b/src/InotifyUpdate.cxx @@ -24,7 +24,7 @@ #include "InotifyDomain.hxx" #include "Mapper.hxx" #include "Main.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "util/Error.hxx" #include "Log.hxx" @@ -50,7 +50,7 @@ enum { struct WatchDirectory { WatchDirectory *parent; - Path name; + AllocatedPath name; int descriptor; @@ -129,17 +129,17 @@ remove_watch_directory(WatchDirectory *directory) }); } -static Path +static AllocatedPath watch_directory_get_uri_fs(const WatchDirectory *directory) { if (directory->parent == NULL) - return Path::Null(); + return AllocatedPath::Null(); - Path uri = watch_directory_get_uri_fs(directory->parent); + const auto uri = watch_directory_get_uri_fs(directory->parent); if (uri.IsNull()) return directory->name; - return Path::Build(uri, directory->name); + return AllocatedPath::Build(uri, directory->name); } /* we don't look at "." / ".." nor files with newlines in their name */ @@ -152,7 +152,7 @@ static bool skip_path(const char *path) static void recursive_watch_subdirectories(WatchDirectory *directory, - const Path &path_fs, unsigned depth) + const AllocatedPath &path_fs, unsigned depth) { Error error; DIR *dir; @@ -181,7 +181,8 @@ recursive_watch_subdirectories(WatchDirectory *directory, if (skip_path(ent->d_name)) continue; - const Path child_path_fs = Path::Build(path_fs, ent->d_name); + const auto child_path_fs = + AllocatedPath::Build(path_fs, ent->d_name); ret = StatFile(child_path_fs, st); if (ret < 0) { FormatErrno(inotify_domain, @@ -209,7 +210,7 @@ recursive_watch_subdirectories(WatchDirectory *directory, continue; directory->children.emplace_front(directory, - Path::FromFS(ent->d_name), + AllocatedPath::FromFS(ent->d_name), ret); child = &directory->children.front(); @@ -257,11 +258,11 @@ mpd_inotify_callback(int wd, unsigned mask, (mask & IN_ISDIR) != 0) { /* a sub directory was changed: register those in inotify */ - const Path &root = mapper_get_music_directory_fs(); + const auto &root = mapper_get_music_directory_fs(); - const Path path_fs = uri_fs.IsNull() + const auto path_fs = uri_fs.IsNull() ? root - : Path::Build(root, uri_fs.c_str()); + : AllocatedPath::Build(root, uri_fs.c_str()); recursive_watch_subdirectories(directory, path_fs, watch_directory_depth(directory)); @@ -290,7 +291,7 @@ mpd_inotify_init(unsigned max_depth) { LogDebug(inotify_domain, "initializing inotify"); - const Path &path = mapper_get_music_directory_fs(); + const auto &path = mapper_get_music_directory_fs(); if (path.IsNull()) { LogDebug(inotify_domain, "no music directory configured"); return; diff --git a/src/Listen.cxx b/src/Listen.cxx index d314423c5..1365cae3f 100644 --- a/src/Listen.cxx +++ b/src/Listen.cxx @@ -28,7 +28,7 @@ #include "event/ServerSocket.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "Log.hxx" #include <string.h> @@ -67,7 +67,7 @@ listen_add_config_param(unsigned int port, if (0 == strcmp(param->value.c_str(), "any")) { return listen_socket->AddPort(port, error_r); } else if (param->value[0] == '/' || param->value[0] == '~') { - Path path = config_parse_path(param, error_r); + const auto path = config_parse_path(param, error_r); return !path.IsNull() && listen_socket->AddPath(path.c_str(), error_r); } else { return listen_socket->AddHost(param->value.c_str(), port, diff --git a/src/LogInit.cxx b/src/LogInit.cxx index 433eda51a..e07c3e947 100644 --- a/src/LogInit.cxx +++ b/src/LogInit.cxx @@ -25,7 +25,7 @@ #include "ConfigOption.hxx" #include "system/fd_util.h" #include "system/FatalError.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -61,7 +61,7 @@ static const char *log_charset; static bool stdout_mode = true; static int out_fd; -static Path out_path = Path::Null(); +static AllocatedPath out_path = AllocatedPath::Null(); static void redirect_logs(int fd) { @@ -301,7 +301,7 @@ void log_deinit(void) { close_log_files(); - out_path = Path::Null(); + out_path = AllocatedPath::Null(); } diff --git a/src/Main.cxx b/src/Main.cxx index 14820f0db..45d173e78 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -48,7 +48,7 @@ #include "InputInit.hxx" #include "event/Loop.hxx" #include "IOThread.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/Config.hxx" #include "PlaylistRegistry.hxx" #include "ZeroconfGlue.hxx" @@ -111,7 +111,7 @@ static StateFile *state_file; static bool glue_daemonize_init(const struct options *options, Error &error) { - Path pid_file = config_get_path(CONF_PID_FILE, error); + auto pid_file = config_get_path(CONF_PID_FILE, error); if (pid_file.IsNull() && error.IsDefined()) return false; @@ -128,17 +128,17 @@ glue_daemonize_init(const struct options *options, Error &error) static bool glue_mapper_init(Error &error) { - Path music_dir = config_get_path(CONF_MUSIC_DIR, error); + auto music_dir = config_get_path(CONF_MUSIC_DIR, error); if (music_dir.IsNull() && error.IsDefined()) return false; - Path playlist_dir = config_get_path(CONF_PLAYLIST_DIR, error); + auto playlist_dir = config_get_path(CONF_PLAYLIST_DIR, error); if (playlist_dir.IsNull() && error.IsDefined()) return false; if (music_dir.IsNull()) { - music_dir = Path::FromUTF8(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC), - error); + music_dir = AllocatedPath::FromUTF8(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC), + error); if (music_dir.IsNull()) return false; } @@ -207,9 +207,12 @@ glue_sticker_init(void) { #ifdef ENABLE_SQLITE Error error; - Path sticker_file = config_get_path(CONF_STICKER_FILE, error); - if (sticker_file.IsNull() && error.IsDefined()) - FatalError(error); + auto sticker_file = config_get_path(CONF_STICKER_FILE, error); + if (sticker_file.IsNull()) { + if (error.IsDefined()) + FatalError(error); + return; + } if (!sticker_global_init(std::move(sticker_file), error)) FatalError(error); @@ -219,7 +222,7 @@ glue_sticker_init(void) static bool glue_state_file_init(Error &error) { - Path path_fs = config_get_path(CONF_STATE_FILE, error); + auto path_fs = config_get_path(CONF_STATE_FILE, error); if (path_fs.IsNull()) return !error.IsDefined(); diff --git a/src/Mapper.cxx b/src/Mapper.cxx index 8a6bd2201..e19117feb 100644 --- a/src/Mapper.cxx +++ b/src/Mapper.cxx @@ -25,7 +25,7 @@ #include "Mapper.hxx" #include "Directory.hxx" #include "Song.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/Charset.hxx" #include "fs/FileSystem.hxx" @@ -52,16 +52,16 @@ static size_t music_dir_utf8_length; * The absolute path of the music directory encoded in the filesystem * character set. */ -static Path music_dir_fs = Path::Null(); +static AllocatedPath music_dir_fs = AllocatedPath::Null(); /** * The absolute path of the playlist directory encoded in the * filesystem character set. */ -static Path playlist_dir_fs = Path::Null(); +static AllocatedPath playlist_dir_fs = AllocatedPath::Null(); static void -check_directory(const char *path_utf8, const Path &path_fs) +check_directory(const char *path_utf8, const AllocatedPath &path_fs) { struct stat st; if (!StatFile(path_fs, st)) { @@ -78,7 +78,7 @@ check_directory(const char *path_utf8, const Path &path_fs) } #ifndef WIN32 - const Path x = Path::Build(path_fs, "."); + const auto x = AllocatedPath::Build(path_fs, "."); if (!StatFile(x, st) && errno == EACCES) FormatError(mapper_domain, "No permission to traverse (\"execute\") directory: %s", @@ -92,7 +92,7 @@ check_directory(const char *path_utf8, const Path &path_fs) } static void -mapper_set_music_dir(Path &&path) +mapper_set_music_dir(AllocatedPath &&path) { assert(!path.IsNull()); @@ -106,7 +106,7 @@ mapper_set_music_dir(Path &&path) } static void -mapper_set_playlist_dir(Path &&path) +mapper_set_playlist_dir(AllocatedPath &&path) { assert(!path.IsNull()); @@ -117,7 +117,7 @@ mapper_set_playlist_dir(Path &&path) } void -mapper_init(Path &&_music_dir, Path &&_playlist_dir) +mapper_init(AllocatedPath &&_music_dir, AllocatedPath &&_playlist_dir) { if (!_music_dir.IsNull()) mapper_set_music_dir(std::move(_music_dir)); @@ -136,7 +136,7 @@ mapper_get_music_directory_utf8(void) return music_dir_utf8.c_str(); } -const Path & +const AllocatedPath & mapper_get_music_directory_fs(void) { return music_dir_fs; @@ -153,23 +153,23 @@ map_to_relative_path(const char *path_utf8) : path_utf8; } -Path +AllocatedPath map_uri_fs(const char *uri) { assert(uri != NULL); assert(*uri != '/'); if (music_dir_fs.IsNull()) - return Path::Null(); + return AllocatedPath::Null(); - const Path uri_fs = Path::FromUTF8(uri); + const auto uri_fs = AllocatedPath::FromUTF8(uri); if (uri_fs.IsNull()) - return Path::Null(); + return AllocatedPath::Null(); - return Path::Build(music_dir_fs, uri_fs); + return AllocatedPath::Build(music_dir_fs, uri_fs); } -Path +AllocatedPath map_directory_fs(const Directory *directory) { assert(!music_dir_fs.IsNull()); @@ -180,7 +180,7 @@ map_directory_fs(const Directory *directory) return map_uri_fs(directory->GetPath()); } -Path +AllocatedPath map_directory_child_fs(const Directory *directory, const char *name) { assert(!music_dir_fs.IsNull()); @@ -188,17 +188,17 @@ map_directory_child_fs(const Directory *directory, const char *name) /* check for invalid or unauthorized base names */ if (*name == 0 || strchr(name, '/') != NULL || strcmp(name, ".") == 0 || strcmp(name, "..") == 0) - return Path::Null(); + return AllocatedPath::Null(); - const Path parent_fs = map_directory_fs(directory); + const auto parent_fs = map_directory_fs(directory); if (parent_fs.IsNull()) - return Path::Null(); + return AllocatedPath::Null(); - const Path name_fs = Path::FromUTF8(name); + const auto name_fs = AllocatedPath::FromUTF8(name); if (name_fs.IsNull()) - return Path::Null(); + return AllocatedPath::Null(); - return Path::Build(parent_fs, name_fs); + return AllocatedPath::Build(parent_fs, name_fs); } /** @@ -206,17 +206,17 @@ map_directory_child_fs(const Directory *directory, const char *name) * not have a real parent directory, only the dummy object * #detached_root. */ -static Path +static AllocatedPath map_detached_song_fs(const char *uri_utf8) { - Path uri_fs = Path::FromUTF8(uri_utf8); + auto uri_fs = AllocatedPath::FromUTF8(uri_utf8); if (uri_fs.IsNull()) - return Path::Null(); + return uri_fs; - return Path::Build(music_dir_fs, uri_fs); + return AllocatedPath::Build(music_dir_fs, uri_fs); } -Path +AllocatedPath map_song_fs(const Song *song) { assert(song->IsFile()); @@ -226,7 +226,7 @@ map_song_fs(const Song *song) ? map_detached_song_fs(song->uri) : map_directory_child_fs(song->parent, song->uri); else - return Path::FromUTF8(song->uri); + return AllocatedPath::FromUTF8(song->uri); } std::string @@ -241,24 +241,25 @@ map_fs_to_utf8(const char *path_fs) return PathToUTF8(path_fs); } -const Path & +const AllocatedPath & map_spl_path(void) { return playlist_dir_fs; } -Path +AllocatedPath map_spl_utf8_to_fs(const char *name) { if (playlist_dir_fs.IsNull()) - return Path::Null(); + return AllocatedPath::Null(); std::string filename_utf8 = name; filename_utf8.append(PLAYLIST_FILE_SUFFIX); - const Path filename_fs = Path::FromUTF8(filename_utf8.c_str()); + const auto filename_fs = + AllocatedPath::FromUTF8(filename_utf8.c_str()); if (filename_fs.IsNull()) - return Path::Null(); + return AllocatedPath::Null(); - return Path::Build(playlist_dir_fs, filename_fs); + return AllocatedPath::Build(playlist_dir_fs, filename_fs); } diff --git a/src/Mapper.hxx b/src/Mapper.hxx index 0688d5dd3..c340e6d64 100644 --- a/src/Mapper.hxx +++ b/src/Mapper.hxx @@ -31,11 +31,12 @@ #define PLAYLIST_FILE_SUFFIX ".m3u" class Path; +class AllocatedPath; struct Directory; struct Song; void -mapper_init(Path &&music_dir, Path &&playlist_dir); +mapper_init(AllocatedPath &&music_dir, AllocatedPath &&playlist_dir); void mapper_finish(void); @@ -51,7 +52,7 @@ mapper_get_music_directory_utf8(void); * filesystem character set. */ gcc_const -const Path & +const AllocatedPath & mapper_get_music_directory_fs(void); /** @@ -79,7 +80,7 @@ map_to_relative_path(const char *path_utf8); * and prepending the music directory. */ gcc_pure -Path +AllocatedPath map_uri_fs(const char *uri); /** @@ -89,7 +90,7 @@ map_uri_fs(const char *uri); * @return the path in file system encoding, or nullptr if mapping failed */ gcc_pure -Path +AllocatedPath map_directory_fs(const Directory *directory); /** @@ -101,7 +102,7 @@ map_directory_fs(const Directory *directory); * @return the path in file system encoding, or nullptr if mapping failed */ gcc_pure -Path +AllocatedPath map_directory_child_fs(const Directory *directory, const char *name); /** @@ -112,7 +113,7 @@ map_directory_child_fs(const Directory *directory, const char *name); * @return the path in file system encoding, or nullptr if mapping failed */ gcc_pure -Path +AllocatedPath map_song_fs(const Song *song); /** @@ -131,7 +132,7 @@ map_fs_to_utf8(const char *path_fs); * Returns the playlist directory. */ gcc_const -const Path & +const AllocatedPath & map_spl_path(void); /** @@ -142,7 +143,7 @@ map_spl_path(void); * @return the path in file system encoding, or nullptr if mapping failed */ gcc_pure -Path +AllocatedPath map_spl_utf8_to_fs(const char *name); #endif diff --git a/src/OtherCommands.cxx b/src/OtherCommands.cxx index 507e4df17..7df76a3e1 100644 --- a/src/OtherCommands.cxx +++ b/src/OtherCommands.cxx @@ -35,7 +35,7 @@ #include "Volume.hxx" #include "util/UriUtil.hxx" #include "util/Error.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "Stats.hxx" #include "Permission.hxx" #include "PlaylistFile.hxx" @@ -117,7 +117,7 @@ handle_lsinfo(Client *client, int argc, char *argv[]) if (memcmp(uri, "file:///", 8) == 0) { /* print information about an arbitrary local file */ const char *path_utf8 = uri + 7; - const Path path_fs = Path::FromUTF8(path_utf8); + const auto path_fs = AllocatedPath::FromUTF8(path_utf8); if (path_fs.IsNull()) { command_error(client, ACK_ERROR_NO_EXIST, diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx index aad9cee7a..68e0cfcf1 100644 --- a/src/PlaylistFile.cxx +++ b/src/PlaylistFile.cxx @@ -32,7 +32,7 @@ #include "ConfigDefaults.hxx" #include "Idle.hxx" #include "fs/Limits.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/Charset.hxx" #include "fs/FileSystem.hxx" @@ -85,10 +85,10 @@ spl_valid_name(const char *name_utf8) strchr(name_utf8, '\r') == nullptr; } -static const Path & +static const AllocatedPath & spl_map(Error &error) { - const Path &path_fs = map_spl_path(); + const AllocatedPath &path_fs = map_spl_path(); if (path_fs.IsNull()) error.Set(playlist_domain, PLAYLIST_RESULT_DISABLED, "Stored playlists are disabled"); @@ -107,13 +107,13 @@ spl_check_name(const char *name_utf8, Error &error) return true; } -static Path +static AllocatedPath spl_map_to_fs(const char *name_utf8, Error &error) { if (spl_map(error).IsNull() || !spl_check_name(name_utf8, error)) - return Path::Null(); + return AllocatedPath::Null(); - Path path_fs = map_spl_utf8_to_fs(name_utf8); + auto path_fs = map_spl_utf8_to_fs(name_utf8); if (path_fs.IsNull()) error.Set(playlist_domain, PLAYLIST_RESULT_BAD_NAME, "Bad playlist name"); @@ -141,7 +141,8 @@ playlist_errno(Error &error) static bool LoadPlaylistFileInfo(PlaylistInfo &info, - const Path &parent_path_fs, const Path &name_fs) + const AllocatedPath &parent_path_fs, + const AllocatedPath &name_fs) { const char *name_fs_str = name_fs.c_str(); size_t name_length = strlen(name_fs_str); @@ -153,7 +154,7 @@ LoadPlaylistFileInfo(PlaylistInfo &info, if (!g_str_has_suffix(name_fs_str, PLAYLIST_FILE_SUFFIX)) return false; - Path path_fs = Path::Build(parent_path_fs, name_fs); + const auto path_fs = AllocatedPath::Build(parent_path_fs, name_fs); struct stat st; if (!StatFile(path_fs, st) || !S_ISREG(st.st_mode)) return false; @@ -175,7 +176,7 @@ ListPlaylistFiles(Error &error) { PlaylistVector list; - const Path &parent_path_fs = spl_map(error); + const auto &parent_path_fs = spl_map(error); if (parent_path_fs.IsNull()) return list; @@ -187,7 +188,7 @@ ListPlaylistFiles(Error &error) PlaylistInfo info; while (reader.ReadEntry()) { - const Path entry = reader.GetEntry(); + const auto entry = reader.GetEntry(); if (LoadPlaylistFileInfo(info, parent_path_fs, entry)) list.push_back(std::move(info)); } @@ -204,7 +205,7 @@ SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path, if (spl_map(error).IsNull()) return false; - const Path path_fs = spl_map_to_fs(utf8path, error); + const auto path_fs = spl_map_to_fs(utf8path, error); if (path_fs.IsNull()) return false; @@ -229,7 +230,7 @@ LoadPlaylistFile(const char *utf8path, Error &error) if (spl_map(error).IsNull()) return contents; - const Path path_fs = spl_map_to_fs(utf8path, error); + const auto path_fs = spl_map_to_fs(utf8path, error); if (path_fs.IsNull()) return contents; @@ -310,7 +311,7 @@ spl_clear(const char *utf8path, Error &error) if (spl_map(error).IsNull()) return false; - const Path path_fs = spl_map_to_fs(utf8path, error); + const auto path_fs = spl_map_to_fs(utf8path, error); if (path_fs.IsNull()) return false; @@ -329,7 +330,7 @@ spl_clear(const char *utf8path, Error &error) bool spl_delete(const char *name_utf8, Error &error) { - const Path path_fs = spl_map_to_fs(name_utf8, error); + const auto path_fs = spl_map_to_fs(name_utf8, error); if (path_fs.IsNull()) return false; @@ -369,7 +370,7 @@ spl_append_song(const char *utf8path, Song *song, Error &error) if (spl_map(error).IsNull()) return false; - const Path path_fs = spl_map_to_fs(utf8path, error); + const auto path_fs = spl_map_to_fs(utf8path, error); if (path_fs.IsNull()) return false; @@ -425,7 +426,7 @@ spl_append_uri(const char *url, const char *utf8file, Error &error) } static bool -spl_rename_internal(const Path &from_path_fs, const Path &to_path_fs, +spl_rename_internal(Path from_path_fs, Path to_path_fs, Error &error) { if (!FileExists(from_path_fs)) { @@ -455,11 +456,11 @@ spl_rename(const char *utf8from, const char *utf8to, Error &error) if (spl_map(error).IsNull()) return false; - Path from_path_fs = spl_map_to_fs(utf8from, error); + const auto from_path_fs = spl_map_to_fs(utf8from, error); if (from_path_fs.IsNull()) return false; - Path to_path_fs = spl_map_to_fs(utf8to, error); + const auto to_path_fs = spl_map_to_fs(utf8to, error); if (to_path_fs.IsNull()) return false; diff --git a/src/PlaylistMapper.cxx b/src/PlaylistMapper.cxx index b8ea7eb85..11e10f7ba 100644 --- a/src/PlaylistMapper.cxx +++ b/src/PlaylistMapper.cxx @@ -22,7 +22,7 @@ #include "PlaylistFile.hxx" #include "PlaylistRegistry.hxx" #include "Mapper.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "util/UriUtil.hxx" #include <assert.h> @@ -49,15 +49,16 @@ playlist_open_in_playlist_dir(const char *uri, Mutex &mutex, Cond &cond, { assert(spl_valid_name(uri)); - const Path &playlist_directory_fs = map_spl_path(); + const auto &playlist_directory_fs = map_spl_path(); if (playlist_directory_fs.IsNull()) return nullptr; - const Path uri_fs = Path::FromUTF8(uri); + const auto uri_fs = AllocatedPath::FromUTF8(uri); if (uri_fs.IsNull()) return nullptr; - const Path path_fs = Path::Build(playlist_directory_fs, uri_fs); + const auto path_fs = + AllocatedPath::Build(playlist_directory_fs, uri_fs); assert(!path_fs.IsNull()); return playlist_open_path(path_fs.c_str(), mutex, cond, is_r); @@ -72,7 +73,7 @@ playlist_open_in_music_dir(const char *uri, Mutex &mutex, Cond &cond, { assert(uri_safe_local(uri)); - Path path = map_uri_fs(uri); + const auto path = map_uri_fs(uri); if (path.IsNull()) return nullptr; diff --git a/src/PlaylistSave.cxx b/src/PlaylistSave.cxx index 57a0d1351..60270bc98 100644 --- a/src/PlaylistSave.cxx +++ b/src/PlaylistSave.cxx @@ -25,7 +25,7 @@ #include "Song.hxx" #include "Mapper.hxx" #include "Idle.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/FileSystem.hxx" #include "util/UriUtil.hxx" @@ -40,12 +40,12 @@ void playlist_print_song(FILE *file, const Song *song) { if (playlist_saveAbsolutePaths && song->IsInDatabase()) { - const Path path = map_song_fs(song); + const auto path = map_song_fs(song); if (!path.IsNull()) fprintf(file, "%s\n", path.c_str()); } else { const auto uri_utf8 = song->GetURI(); - const Path uri_fs = Path::FromUTF8(uri_utf8.c_str()); + const auto uri_fs = AllocatedPath::FromUTF8(uri_utf8.c_str()); if (!uri_fs.IsNull()) fprintf(file, "%s\n", uri_fs.c_str()); @@ -55,10 +55,10 @@ playlist_print_song(FILE *file, const Song *song) void playlist_print_uri(FILE *file, const char *uri) { - Path path = playlist_saveAbsolutePaths && !uri_has_scheme(uri) && + auto path = playlist_saveAbsolutePaths && !uri_has_scheme(uri) && !PathTraits::IsAbsoluteUTF8(uri) ? map_uri_fs(uri) - : Path::FromUTF8(uri); + : AllocatedPath::FromUTF8(uri); if (!path.IsNull()) fprintf(file, "%s\n", path.c_str()); @@ -73,7 +73,7 @@ spl_save_queue(const char *name_utf8, const struct queue *queue) if (!spl_valid_name(name_utf8)) return PLAYLIST_RESULT_BAD_NAME; - const Path path_fs = map_spl_utf8_to_fs(name_utf8); + const auto path_fs = map_spl_utf8_to_fs(name_utf8); if (path_fs.IsNull()) return PLAYLIST_RESULT_BAD_NAME; diff --git a/src/PlaylistSong.cxx b/src/PlaylistSong.cxx index fc1fe884c..b7a2e441c 100644 --- a/src/PlaylistSong.cxx +++ b/src/PlaylistSong.cxx @@ -24,7 +24,7 @@ #include "DatabaseGlue.hxx" #include "ls.hxx" #include "tag/Tag.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "util/UriUtil.hxx" #include "util/Error.hxx" @@ -64,7 +64,7 @@ apply_song_metadata(Song *dest, const Song *src) return dest; if (dest->IsInDatabase()) { - const Path &path_fs = map_song_fs(dest); + const auto path_fs = map_song_fs(dest); if (path_fs.IsNull()) return dest; diff --git a/src/QueueCommands.cxx b/src/QueueCommands.cxx index 7d461a4ab..f58263872 100644 --- a/src/QueueCommands.cxx +++ b/src/QueueCommands.cxx @@ -33,7 +33,7 @@ #include "ls.hxx" #include "util/UriUtil.hxx" #include "util/Error.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include <limits> @@ -47,7 +47,7 @@ handle_add(Client *client, gcc_unused int argc, char *argv[]) if (memcmp(uri, "file:///", 8) == 0) { const char *path_utf8 = uri + 7; - const Path path_fs = Path::FromUTF8(path_utf8); + const auto path_fs = AllocatedPath::FromUTF8(path_utf8); if (path_fs.IsNull()) { command_error(client, ACK_ERROR_NO_EXIST, @@ -90,7 +90,7 @@ handle_addid(Client *client, int argc, char *argv[]) if (memcmp(uri, "file:///", 8) == 0) { const char *path_utf8 = uri + 7; - const Path path_fs = Path::FromUTF8(path_utf8); + const auto path_fs = AllocatedPath::FromUTF8(path_utf8); if (path_fs.IsNull()) { command_error(client, ACK_ERROR_NO_EXIST, diff --git a/src/SongUpdate.cxx b/src/SongUpdate.cxx index 1bf70a8c9..362f17e8a 100644 --- a/src/SongUpdate.cxx +++ b/src/SongUpdate.cxx @@ -23,7 +23,7 @@ #include "util/Error.hxx" #include "Directory.hxx" #include "Mapper.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/FileSystem.hxx" #include "InputStream.hxx" @@ -99,7 +99,7 @@ Song::UpdateFile() if (plugin == NULL) return false; - const Path path_fs = map_song_fs(this); + const auto path_fs = map_song_fs(this); if (path_fs.IsNull()) return false; diff --git a/src/StateFile.cxx b/src/StateFile.cxx index ce812076c..7a427a6a9 100644 --- a/src/StateFile.cxx +++ b/src/StateFile.cxx @@ -33,7 +33,7 @@ static constexpr Domain state_file_domain("state_file"); -StateFile::StateFile(Path &&_path, +StateFile::StateFile(AllocatedPath &&_path, Partition &_partition, EventLoop &_loop) :TimeoutMonitor(_loop), path(std::move(_path)), path_utf8(path.ToUTF8()), diff --git a/src/StateFile.hxx b/src/StateFile.hxx index 5052aa1e9..4ec2c4be7 100644 --- a/src/StateFile.hxx +++ b/src/StateFile.hxx @@ -21,7 +21,7 @@ #define MPD_STATE_FILE_HXX #include "event/TimeoutMonitor.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "Compiler.h" #include <string> @@ -29,7 +29,7 @@ struct Partition; class StateFile final : private TimeoutMonitor { - Path path; + AllocatedPath path; std::string path_utf8; Partition &partition; @@ -42,7 +42,7 @@ class StateFile final : private TimeoutMonitor { prev_playlist_version; public: - StateFile(Path &&path, Partition &partition, EventLoop &loop); + StateFile(AllocatedPath &&path, Partition &partition, EventLoop &loop); void Read(); void Write(); diff --git a/src/StickerDatabase.cxx b/src/StickerDatabase.cxx index 84aa4c1e0..3c9bdc2a9 100644 --- a/src/StickerDatabase.cxx +++ b/src/StickerDatabase.cxx @@ -107,13 +107,11 @@ sticker_prepare(const char *sql, Error &error) } bool -sticker_global_init(Path &&path, Error &error) +sticker_global_init(Path path, Error &error) { - int ret; + assert(!path.IsNull()); - if (path.IsNull()) - /* not configured */ - return true; + int ret; /* open/create the sqlite database */ diff --git a/src/StickerDatabase.hxx b/src/StickerDatabase.hxx index 46a9ba52d..d5a81d3b1 100644 --- a/src/StickerDatabase.hxx +++ b/src/StickerDatabase.hxx @@ -58,7 +58,7 @@ struct sticker; * @return true on success, false on error */ bool -sticker_global_init(Path &&path, Error &error); +sticker_global_init(Path path, Error &error); /** * Close the sticker database. diff --git a/src/TextFile.cxx b/src/TextFile.cxx index da0b33816..89df6d1bf 100644 --- a/src/TextFile.cxx +++ b/src/TextFile.cxx @@ -27,7 +27,7 @@ #include <assert.h> #include <string.h> -TextFile::TextFile(const Path &path_fs) +TextFile::TextFile(Path path_fs) :file(FOpen(path_fs, FOpenMode::ReadText)), buffer(g_string_sized_new(step)) {} diff --git a/src/TextFile.hxx b/src/TextFile.hxx index 3d031a1f6..4291f2639 100644 --- a/src/TextFile.hxx +++ b/src/TextFile.hxx @@ -36,7 +36,7 @@ class TextFile { GString *const buffer; public: - TextFile(const Path &path_fs); + TextFile(Path path_fs); TextFile(const TextFile &other) = delete; diff --git a/src/UpdateArchive.cxx b/src/UpdateArchive.cxx index 6ec73c47a..730dfe883 100644 --- a/src/UpdateArchive.cxx +++ b/src/UpdateArchive.cxx @@ -25,7 +25,7 @@ #include "Directory.hxx" #include "Song.hxx" #include "Mapper.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "ArchiveList.hxx" #include "ArchivePlugin.hxx" #include "ArchiveFile.hxx" @@ -101,7 +101,7 @@ update_archive_file2(Directory *parent, const char *name, changed since - don't consider updating it */ return; - const Path path_fs = map_directory_child_fs(parent, name); + const auto path_fs = map_directory_child_fs(parent, name); /* open archive */ Error error; diff --git a/src/UpdateContainer.cxx b/src/UpdateContainer.cxx index 082e34ffe..54328fe14 100644 --- a/src/UpdateContainer.cxx +++ b/src/UpdateContainer.cxx @@ -27,7 +27,7 @@ #include "Song.hxx" #include "DecoderPlugin.hxx" #include "Mapper.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "tag/TagHandler.hxx" #include "tag/TagBuilder.hxx" #include "Log.hxx" @@ -84,7 +84,7 @@ update_container_file(Directory *directory, contdir->device = DEVICE_CONTAINER; db_unlock(); - const Path pathname = map_directory_child_fs(directory, name); + const auto pathname = map_directory_child_fs(directory, name); char *vtrack; unsigned int tnum = 0; @@ -95,7 +95,7 @@ update_container_file(Directory *directory, // shouldn't be necessary but it's there.. song->mtime = st->st_mtime; - const Path child_path_fs = + const auto child_path_fs = map_directory_child_fs(contdir, vtrack); decoder_plugin_scan_file(plugin, child_path_fs.c_str(), diff --git a/src/UpdateIO.cxx b/src/UpdateIO.cxx index ba4fcb7cf..14c25249f 100644 --- a/src/UpdateIO.cxx +++ b/src/UpdateIO.cxx @@ -22,7 +22,7 @@ #include "src/UpdateDomain.hxx" #include "Directory.hxx" #include "Mapper.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "Log.hxx" @@ -32,7 +32,7 @@ int stat_directory(const Directory *directory, struct stat *st) { - const Path path_fs = map_directory_fs(directory); + const auto path_fs = map_directory_fs(directory); if (path_fs.IsNull()) return -1; @@ -51,7 +51,7 @@ int stat_directory_child(const Directory *parent, const char *name, struct stat *st) { - const Path path_fs = map_directory_child_fs(parent, name); + const auto path_fs = map_directory_child_fs(parent, name); if (path_fs.IsNull()) return -1; @@ -69,7 +69,7 @@ stat_directory_child(const Directory *parent, const char *name, bool directory_exists(const Directory *directory) { - const Path path_fs = map_directory_fs(directory); + const auto path_fs = map_directory_fs(directory); if (path_fs.IsNull()) /* invalid path: cannot exist */ return false; @@ -84,7 +84,7 @@ bool directory_child_is_regular(const Directory *directory, const char *name_utf8) { - const Path path_fs = map_directory_child_fs(directory, name_utf8); + const auto path_fs = map_directory_child_fs(directory, name_utf8); if (path_fs.IsNull()) return false; @@ -102,7 +102,7 @@ directory_child_access(const Directory *directory, (void)mode; return true; #else - const Path path = map_directory_child_fs(directory, name); + const auto path = map_directory_child_fs(directory, name); if (path.IsNull()) /* something went wrong, but that isn't a permission problem */ diff --git a/src/UpdateWalk.cxx b/src/UpdateWalk.cxx index 82a0959b1..1df41e4e1 100644 --- a/src/UpdateWalk.cxx +++ b/src/UpdateWalk.cxx @@ -34,7 +34,7 @@ #include "ExcludeList.hxx" #include "ConfigGlobal.hxx" #include "ConfigOption.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" #include "fs/FileSystem.hxx" #include "fs/DirectoryReader.hxx" @@ -102,7 +102,7 @@ remove_excluded_from_directory(Directory *directory, Directory *child, *n; directory_for_each_child_safe(child, n, directory) { - const Path name_fs = Path::FromUTF8(child->GetName()); + const auto name_fs = AllocatedPath::FromUTF8(child->GetName()); if (name_fs.IsNull() || exclude_list.Check(name_fs)) { delete_directory(child); @@ -114,7 +114,7 @@ remove_excluded_from_directory(Directory *directory, directory_for_each_song_safe(song, ns, directory) { assert(song->parent == directory); - const Path name_fs = Path::FromUTF8(song->uri); + const auto name_fs = AllocatedPath::FromUTF8(song->uri); if (name_fs.IsNull() || exclude_list.Check(name_fs)) { delete_song(directory, song); modified = true; @@ -141,7 +141,7 @@ purge_deleted_from_directory(Directory *directory) Song *song, *ns; directory_for_each_song_safe(song, ns, directory) { - const Path path = map_song_fs(song); + const auto path = map_song_fs(song); if (path.IsNull() || !FileExists(path)) { db_lock(); delete_song(directory, song); @@ -264,7 +264,7 @@ update_directory_child(Directory *directory, /* we don't look at "." / ".." nor files with newlines in their name */ gcc_pure -static bool skip_path(const Path &path_fs) +static bool skip_path(Path path_fs) { const char *path = path_fs.c_str(); return (path[0] == '.' && path[1] == 0) || @@ -277,11 +277,11 @@ static bool skip_symlink(const Directory *directory, const char *utf8_name) { #ifndef WIN32 - const Path path_fs = map_directory_child_fs(directory, utf8_name); + const auto path_fs = map_directory_child_fs(directory, utf8_name); if (path_fs.IsNull()) return true; - const Path target = ReadLink(path_fs); + const auto target = ReadLink(path_fs); if (target.IsNull()) /* don't skip if this is not a symlink */ return errno != EINVAL; @@ -345,7 +345,7 @@ update_directory(Directory *directory, const struct stat *st) directory_set_stat(directory, st); - const Path path_fs = map_directory_fs(directory); + const auto path_fs = map_directory_fs(directory); if (path_fs.IsNull()) return false; @@ -360,7 +360,7 @@ update_directory(Directory *directory, const struct stat *st) } ExcludeList exclude_list; - exclude_list.LoadFile(Path::Build(path_fs, ".mpdignore")); + exclude_list.LoadFile(AllocatedPath::Build(path_fs, ".mpdignore")); if (!exclude_list.IsEmpty()) remove_excluded_from_directory(directory, exclude_list); @@ -371,7 +371,7 @@ update_directory(Directory *directory, const struct stat *st) std::string utf8; struct stat st2; - const Path entry = reader.GetEntry(); + const auto entry = reader.GetEntry(); if (skip_path(entry) || exclude_list.Check(entry)) continue; diff --git a/src/db/SimpleDatabasePlugin.cxx b/src/db/SimpleDatabasePlugin.cxx index 03acd1760..567c62b6f 100644 --- a/src/db/SimpleDatabasePlugin.cxx +++ b/src/db/SimpleDatabasePlugin.cxx @@ -76,7 +76,7 @@ SimpleDatabase::Check(Error &error) const /* If the file doesn't exist, we can't check if we can write * it, so we are going to try to get the directory path, and * see if we can write a file in that */ - const Path dirPath = path.GetDirectoryName(); + const auto dirPath = path.GetDirectoryName(); /* Check that the parent part of the path is a directory */ struct stat st; diff --git a/src/db/SimpleDatabasePlugin.hxx b/src/db/SimpleDatabasePlugin.hxx index 6ebaacdf3..bd112f8f3 100644 --- a/src/db/SimpleDatabasePlugin.hxx +++ b/src/db/SimpleDatabasePlugin.hxx @@ -21,7 +21,7 @@ #define MPD_SIMPLE_DATABASE_PLUGIN_HXX #include "DatabasePlugin.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "Compiler.h" #include <cassert> @@ -31,7 +31,7 @@ struct Directory; class SimpleDatabase : public Database { - Path path; + AllocatedPath path; std::string path_utf8; Directory *root; @@ -43,7 +43,7 @@ class SimpleDatabase : public Database { #endif SimpleDatabase() - :path(Path::Null()) {} + :path(AllocatedPath::Null()) {} public: gcc_pure diff --git a/src/decoder/WildmidiDecoderPlugin.cxx b/src/decoder/WildmidiDecoderPlugin.cxx index a1d29a35e..3454d23dc 100644 --- a/src/decoder/WildmidiDecoderPlugin.cxx +++ b/src/decoder/WildmidiDecoderPlugin.cxx @@ -23,7 +23,7 @@ #include "tag/TagHandler.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "system/FatalError.hxx" #include "Log.hxx" @@ -40,9 +40,10 @@ static bool wildmidi_init(const config_param ¶m) { Error error; - const Path path = param.GetBlockPath("config_file", - "/etc/timidity/timidity.cfg", - error); + const AllocatedPath path = + param.GetBlockPath("config_file", + "/etc/timidity/timidity.cfg", + error); if (path.IsNull()) FatalError(error); diff --git a/src/fs/AllocatedPath.cxx b/src/fs/AllocatedPath.cxx new file mode 100644 index 000000000..37b79a685 --- /dev/null +++ b/src/fs/AllocatedPath.cxx @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2003-2013 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 "AllocatedPath.hxx" +#include "Domain.hxx" +#include "Charset.hxx" +#include "util/Error.hxx" +#include "Compiler.h" + +#include <glib.h> + +#include <assert.h> +#include <string.h> + +inline AllocatedPath::AllocatedPath(Donate, pointer _value) + :value(_value) { + g_free(_value); +} + +/* no inlining, please */ +AllocatedPath::~AllocatedPath() {} + +AllocatedPath +AllocatedPath::Build(const_pointer a, const_pointer b) +{ + return AllocatedPath(Donate(), g_build_filename(a, b, nullptr)); +} + +AllocatedPath +AllocatedPath::FromUTF8(const char *path_utf8) +{ + return AllocatedPath(Donate(), ::PathFromUTF8(path_utf8)); +} + +AllocatedPath +AllocatedPath::FromUTF8(const char *path_utf8, Error &error) +{ + AllocatedPath path = FromUTF8(path_utf8); + if (path.IsNull()) + error.Format(path_domain, + "Failed to convert to file system charset: %s", + path_utf8); + + return path; +} + +AllocatedPath +AllocatedPath::GetDirectoryName() const +{ + return AllocatedPath(Donate(), g_path_get_dirname(c_str())); +} + +std::string +AllocatedPath::ToUTF8() const +{ + return ::PathToUTF8(c_str()); +} + +const char * +AllocatedPath::RelativeFS(const char *other_fs) const +{ + const size_t l = length(); + if (memcmp(data(), other_fs, l) != 0) + return nullptr; + + other_fs += l; + if (*other_fs != 0) { + if (!PathTraits::IsSeparatorFS(*other_fs)) + /* mismatch */ + return nullptr; + + /* skip remaining path separators */ + do { + ++other_fs; + } while (PathTraits::IsSeparatorFS(*other_fs)); + } + + return other_fs; +} + +void +AllocatedPath::ChopSeparators() +{ + size_t l = length(); + const char *p = data(); + + while (l >= 2 && PathTraits::IsSeparatorFS(p[l - 1])) { + --l; + +#if GCC_CHECK_VERSION(4,7) && !defined(__clang__) + value.pop_back(); +#else + value.erase(value.end() - 1, value.end()); +#endif + } +} diff --git a/src/fs/AllocatedPath.hxx b/src/fs/AllocatedPath.hxx new file mode 100644 index 000000000..1655a270a --- /dev/null +++ b/src/fs/AllocatedPath.hxx @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2003-2013 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_FS_ALLOCATED_PATH_HXX +#define MPD_FS_ALLOCATED_PATH_HXX + +#include "check.h" +#include "Compiler.h" +#include "Traits.hxx" +#include "Path.hxx" + +#ifdef WIN32 +#include <glib.h> +#endif + +#include <utility> +#include <string> + +#include <assert.h> + +class Error; + +/** + * A path name in the native file system character set. + * + * This class manages the memory chunk where this path string is + * stored. + */ +class AllocatedPath { + typedef std::string string; + + typedef PathTraits::value_type value_type; + typedef PathTraits::pointer pointer; + typedef PathTraits::const_pointer const_pointer; + + string value; + + struct Donate {}; + + /** + * Donate the allocated pointer to a new #AllocatedPath object. + */ + AllocatedPath(Donate, pointer _value); + + AllocatedPath(const_pointer _value):value(_value) {} + +public: + /** + * Copy a #AllocatedPath object. + */ + AllocatedPath(const AllocatedPath &) = default; + + /** + * Move a #AllocatedPath object. + */ + AllocatedPath(AllocatedPath &&other):value(std::move(other.value)) {} + + ~AllocatedPath(); + + /** + * Return a "nulled" instance. Its IsNull() method will + * return true. Such an object must not be used. + * + * @see IsNull() + */ + gcc_const + static AllocatedPath Null() { + return AllocatedPath(""); + } + + gcc_pure + operator Path() const { + return Path::FromFS(c_str()); + } + + /** + * Join two path components with the path separator. + */ + gcc_pure gcc_nonnull_all + static AllocatedPath Build(const_pointer a, const_pointer b); + + gcc_pure gcc_nonnull_all + static AllocatedPath Build(const_pointer a, const AllocatedPath &b) { + return Build(a, b.c_str()); + } + + gcc_pure gcc_nonnull_all + static AllocatedPath Build(const AllocatedPath &a, const_pointer b) { + return Build(a.c_str(), b); + } + + gcc_pure + static AllocatedPath Build(const AllocatedPath &a, + const AllocatedPath &b) { + return Build(a.c_str(), b.c_str()); + } + + /** + * Convert a C string that is already in the filesystem + * character set to a #Path instance. + */ + gcc_pure + static AllocatedPath FromFS(const_pointer fs) { + return AllocatedPath(fs); + } + + /** + * Convert a UTF-8 C string to a #AllocatedPath instance. + * Returns return a "nulled" instance on error. + */ + gcc_pure gcc_nonnull_all + static AllocatedPath FromUTF8(const char *path_utf8); + + gcc_pure gcc_nonnull_all + static AllocatedPath FromUTF8(const char *path_utf8, Error &error); + + /** + * Copy a #AllocatedPath object. + */ + AllocatedPath &operator=(const AllocatedPath &) = default; + + /** + * Move a #AllocatedPath object. + */ + AllocatedPath &operator=(AllocatedPath &&other) { + value = std::move(other.value); + return *this; + } + + /** + * Check if this is a "nulled" instance. A "nulled" instance + * must not be used. + */ + bool IsNull() const { + return value.empty(); + } + + /** + * Clear this object's value, make it "nulled". + * + * @see IsNull() + */ + void SetNull() { + value.clear(); + } + + /** + * @return the length of this string in number of "value_type" + * elements (which may not be the number of characters). + */ + gcc_pure + size_t length() const { + return value.length(); + } + + /** + * Returns the value as a const C string. The returned + * pointer is invalidated whenever the value of life of this + * instance ends. + */ + gcc_pure + const_pointer c_str() const { + return value.c_str(); + } + + /** + * Returns a pointer to the raw value, not necessarily + * null-terminated. + */ + gcc_pure + const_pointer data() const { + return value.data(); + } + + /** + * Convert the path to UTF-8. + * Returns empty string on error or if this instance is "nulled" + * (#IsNull returns true). + */ + gcc_pure + std::string ToUTF8() const; + + /** + * Gets directory name of this path. + * Returns a "nulled" instance on error. + */ + gcc_pure + AllocatedPath GetDirectoryName() const; + + /** + * Determine the relative part of the given path to this + * object, not including the directory separator. Returns an + * empty string if the given path equals this object or + * nullptr on mismatch. + */ + gcc_pure + const char *RelativeFS(const char *other_fs) const; + + /** + * Chop trailing directory separators. + */ + void ChopSeparators(); + + gcc_pure + bool IsAbsolute() { + return PathTraits::IsAbsoluteFS(c_str()); + } +}; + +#endif diff --git a/src/fs/DirectoryReader.hxx b/src/fs/DirectoryReader.hxx index 4e4a56345..c9d2c04b8 100644 --- a/src/fs/DirectoryReader.hxx +++ b/src/fs/DirectoryReader.hxx @@ -21,7 +21,7 @@ #define MPD_FS_DIRECTORY_READER_HXX #include "check.h" -#include "Path.hxx" +#include "AllocatedPath.hxx" #include <dirent.h> @@ -35,7 +35,7 @@ public: /** * Creates new directory reader for the specified #dir. */ - explicit DirectoryReader(const Path &dir) + explicit DirectoryReader(Path dir) : dirp(opendir(dir.c_str())), ent(nullptr) { } @@ -78,9 +78,9 @@ public: /** * Extracts directory entry that was previously read by #ReadEntry. */ - Path GetEntry() const { + AllocatedPath GetEntry() const { assert(HasEntry()); - return Path::FromFS(ent->d_name); + return AllocatedPath::FromFS(ent->d_name); } }; diff --git a/src/fs/FileSystem.cxx b/src/fs/FileSystem.cxx index 7f740e3af..4cd9f33b2 100644 --- a/src/fs/FileSystem.cxx +++ b/src/fs/FileSystem.cxx @@ -19,26 +19,28 @@ #include "config.h" #include "FileSystem.hxx" +#include "AllocatedPath.hxx" #include "Limits.hxx" #include <errno.h> -Path ReadLink(const Path &path) +AllocatedPath +ReadLink(Path path) { #ifdef WIN32 (void)path; errno = EINVAL; - return Path::Null(); + return AllocatedPath::Null(); #else char buffer[MPD_PATH_MAX]; ssize_t size = readlink(path.c_str(), buffer, MPD_PATH_MAX); if (size < 0) - return Path::Null(); + return AllocatedPath::Null(); if (size_t(size) >= MPD_PATH_MAX) { errno = ENOMEM; - return Path::Null(); + return AllocatedPath::Null(); } buffer[size] = '\0'; - return Path::FromFS(buffer); + return AllocatedPath::FromFS(buffer); #endif } diff --git a/src/fs/FileSystem.hxx b/src/fs/FileSystem.hxx index faa00751a..cb2f82d22 100644 --- a/src/fs/FileSystem.hxx +++ b/src/fs/FileSystem.hxx @@ -31,6 +31,8 @@ #include <assert.h> #include <stdio.h> +class AllocatedPath; + namespace FOpenMode { /** * Open mode for reading text files. @@ -67,7 +69,7 @@ namespace FOpenMode { * Wrapper for fopen() that uses #Path names. */ static inline FILE * -FOpen(const Path &file, PathTraits::const_pointer mode) +FOpen(Path file, PathTraits::const_pointer mode) { return fopen(file.c_str(), mode); } @@ -75,7 +77,8 @@ FOpen(const Path &file, PathTraits::const_pointer mode) /** * Wrapper for open_cloexec() that uses #Path names. */ -static inline int OpenFile(const Path &file, int flags, int mode) +static inline int +OpenFile(Path file, int flags, int mode) { return open_cloexec(file.c_str(), flags, mode); } @@ -83,7 +86,8 @@ static inline int OpenFile(const Path &file, int flags, int mode) /** * Wrapper for rename() that uses #Path names. */ -static inline bool RenameFile(const Path &oldpath, const Path &newpath) +static inline bool +RenameFile(Path oldpath, Path newpath) { return rename(oldpath.c_str(), newpath.c_str()) == 0; } @@ -91,8 +95,8 @@ static inline bool RenameFile(const Path &oldpath, const Path &newpath) /** * Wrapper for stat() that uses #Path names. */ -static inline bool StatFile(const Path &file, struct stat &buf, - bool follow_symlinks = true) +static inline bool +StatFile(Path file, struct stat &buf, bool follow_symlinks = true) { #ifdef WIN32 (void)follow_symlinks; @@ -108,7 +112,8 @@ static inline bool StatFile(const Path &file, struct stat &buf, /** * Wrapper for unlink() that uses #Path names. */ -static inline bool RemoveFile(const Path &file) +static inline bool +RemoveFile(Path file) { return unlink(file.c_str()) == 0; } @@ -116,12 +121,13 @@ static inline bool RemoveFile(const Path &file) /** * Wrapper for readlink() that uses #Path names. */ -Path ReadLink(const Path &path); +AllocatedPath +ReadLink(Path path); #ifndef WIN32 static inline bool -MakeFifo(const Path &path, mode_t mode) +MakeFifo(Path path, mode_t mode) { return mkfifo(path.c_str(), mode) == 0; } @@ -131,7 +137,8 @@ MakeFifo(const Path &path, mode_t mode) /** * Wrapper for access() that uses #Path names. */ -static inline bool CheckAccess(const Path &path, int mode) +static inline bool +CheckAccess(Path path, int mode) { #ifdef WIN32 (void)path; @@ -145,8 +152,8 @@ static inline bool CheckAccess(const Path &path, int mode) /** * Checks if #Path exists and is a regular file. */ -static inline bool FileExists(const Path &path, - bool follow_symlinks = true) +static inline bool +FileExists(Path path, bool follow_symlinks = true) { struct stat buf; return StatFile(path, buf, follow_symlinks) && S_ISREG(buf.st_mode); @@ -155,8 +162,8 @@ static inline bool FileExists(const Path &path, /** * Checks if #Path exists and is a directory. */ -static inline bool DirectoryExists(const Path &path, - bool follow_symlinks = true) +static inline bool +DirectoryExists(Path path, bool follow_symlinks = true) { struct stat buf; return StatFile(path, buf, follow_symlinks) && S_ISDIR(buf.st_mode); @@ -165,8 +172,8 @@ static inline bool DirectoryExists(const Path &path, /** * Checks if #Path exists. */ -static inline bool PathExists(const Path &path, - bool follow_symlinks = true) +static inline bool +PathExists(Path path, bool follow_symlinks = true) { struct stat buf; return StatFile(path, buf, follow_symlinks); diff --git a/src/fs/Path.cxx b/src/fs/Path.cxx index ecdf73e49..0ff0591fb 100644 --- a/src/fs/Path.cxx +++ b/src/fs/Path.cxx @@ -19,57 +19,12 @@ #include "config.h" #include "Path.hxx" -#include "Domain.hxx" #include "Charset.hxx" -#include "util/Error.hxx" -#include "Compiler.h" - -#include <glib.h> - -#include <assert.h> -#include <string.h> - -inline Path::Path(Donate, pointer _value) - :value(_value) { - g_free(_value); -} - -/* no inlining, please */ -Path::~Path() {} - -Path -Path::Build(const_pointer a, const_pointer b) -{ - return Path(Donate(), g_build_filename(a, b, nullptr)); -} - -Path Path::FromUTF8(const char *path_utf8) -{ - return Path(Donate(), ::PathFromUTF8(path_utf8)); -} - -Path -Path::FromUTF8(const char *path_utf8, Error &error) -{ - Path path = FromUTF8(path_utf8); - if (path.IsNull()) - error.Format(path_domain, - "Failed to convert to file system charset: %s", - path_utf8); - - return path; -} - -Path -Path::GetDirectoryName() const -{ - return Path(Donate(), g_path_get_dirname(value.c_str())); -} std::string Path::ToUTF8() const { - return ::PathToUTF8(value.c_str()); + return ::PathToUTF8(c_str()); } const char * @@ -93,20 +48,3 @@ Path::RelativeFS(const char *other_fs) const return other_fs; } - -void -Path::ChopSeparators() -{ - size_t l = length(); - const char *p = data(); - - while (l >= 2 && PathTraits::IsSeparatorFS(p[l - 1])) { - --l; - -#if GCC_CHECK_VERSION(4,7) && !defined(__clang__) - value.pop_back(); -#else - value.erase(value.end() - 1, value.end()); -#endif - } -} diff --git a/src/fs/Path.hxx b/src/fs/Path.hxx index 558e2923f..6ea954577 100644 --- a/src/fs/Path.hxx +++ b/src/fs/Path.hxx @@ -24,50 +24,33 @@ #include "Compiler.h" #include "Traits.hxx" -#ifdef WIN32 -#include <glib.h> -#endif - -#include <utility> #include <string> #include <assert.h> +#include <string.h> class Error; /** * A path name in the native file system character set. + * + * This class manages a pointer to an existing path string. While an + * instance lives, the string must not be invalidated. */ class Path { - typedef std::string string; - typedef PathTraits::value_type value_type; typedef PathTraits::pointer pointer; typedef PathTraits::const_pointer const_pointer; - string value; - - struct Donate {}; + const char *value; - /** - * Donate the allocated pointer to a new #Path object. - */ - Path(Donate, pointer _value); - - Path(const_pointer _value):value(_value) {} + constexpr Path(const_pointer _value):value(_value) {} public: /** * Copy a #Path object. */ - Path(const Path &) = default; - - /** - * Move a #Path object. - */ - Path(Path &&other):value(std::move(other.value)) {} - - ~Path(); + constexpr Path(const Path &) = default; /** * Return a "nulled" instance. Its IsNull() method will @@ -75,70 +58,29 @@ public: * * @see IsNull() */ - gcc_const - static Path Null() { - return Path(""); + static constexpr Path Null() { + return Path(nullptr); } /** - * Join two path components with the path separator. + * Create a new instance pointing to the specified path + * string. */ - gcc_pure gcc_nonnull_all - static Path Build(const_pointer a, const_pointer b); - - gcc_pure gcc_nonnull_all - static Path Build(const_pointer a, const Path &b) { - return Build(a, b.c_str()); - } - - gcc_pure gcc_nonnull_all - static Path Build(const Path &a, const_pointer b) { - return Build(a.c_str(), b); - } - - gcc_pure - static Path Build(const Path &a, const Path &b) { - return Build(a.c_str(), b.c_str()); - } - - /** - * Convert a C string that is already in the filesystem - * character set to a #Path instance. - */ - gcc_pure - static Path FromFS(const_pointer fs) { + static constexpr Path FromFS(const_pointer fs) { return Path(fs); } /** - * Convert a UTF-8 C string to a #Path instance. - * Returns return a "nulled" instance on error. - */ - gcc_pure gcc_nonnull_all - static Path FromUTF8(const char *path_utf8); - - gcc_pure gcc_nonnull_all - static Path FromUTF8(const char *path_utf8, Error &error); - - /** * Copy a #Path object. */ Path &operator=(const Path &) = default; /** - * Move a #Path object. - */ - Path &operator=(Path &&other) { - value = std::move(other.value); - return *this; - } - - /** * Check if this is a "nulled" instance. A "nulled" instance * must not be used. */ bool IsNull() const { - return value.empty(); + return value == nullptr; } /** @@ -147,7 +89,7 @@ public: * @see IsNull() */ void SetNull() { - value.clear(); + value = nullptr; } /** @@ -156,7 +98,9 @@ public: */ gcc_pure size_t length() const { - return value.length(); + assert(value != nullptr); + + return strlen(value); } /** @@ -166,7 +110,7 @@ public: */ gcc_pure const_pointer c_str() const { - return value.c_str(); + return value; } /** @@ -175,7 +119,7 @@ public: */ gcc_pure const_pointer data() const { - return value.data(); + return value; } /** @@ -187,13 +131,6 @@ public: std::string ToUTF8() const; /** - * Gets directory name of this path. - * Returns a "nulled" instance on error. - */ - gcc_pure - Path GetDirectoryName() const; - - /** * Determine the relative part of the given path to this * object, not including the directory separator. Returns an * empty string if the given path equals this object or @@ -202,11 +139,6 @@ public: gcc_pure const char *RelativeFS(const char *other_fs) const; - /** - * Chop trailing directory separators. - */ - void ChopSeparators(); - gcc_pure bool IsAbsolute() { return PathTraits::IsAbsoluteFS(c_str()); diff --git a/src/output/FifoOutputPlugin.cxx b/src/output/FifoOutputPlugin.cxx index babda5f9e..aeb9a6a87 100644 --- a/src/output/FifoOutputPlugin.cxx +++ b/src/output/FifoOutputPlugin.cxx @@ -23,7 +23,7 @@ #include "OutputAPI.hxx" #include "Timer.hxx" #include "system/fd_util.h" -#include "fs/Path.hxx" +#include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -41,7 +41,7 @@ struct FifoOutput { struct audio_output base; - Path path; + AllocatedPath path; std::string path_utf8; int input; @@ -50,7 +50,8 @@ struct FifoOutput { Timer *timer; FifoOutput() - :path(Path::Null()), input(-1), output(-1), created(false) {} + :path(AllocatedPath::Null()), input(-1), output(-1), + created(false) {} bool Initialize(const config_param ¶m, Error &error) { return ao_base_init(&base, &fifo_output_plugin, param, |