diff options
Diffstat (limited to '')
-rw-r--r-- | src/ConfigData.cxx | 12 | ||||
-rw-r--r-- | src/ConfigData.hxx | 5 | ||||
-rw-r--r-- | src/ConfigGlobal.cxx | 11 | ||||
-rw-r--r-- | src/ConfigGlobal.hxx | 11 | ||||
-rw-r--r-- | src/ConfigPath.cxx | 25 | ||||
-rw-r--r-- | src/ConfigPath.hxx | 6 | ||||
-rw-r--r-- | src/Daemon.cxx | 37 | ||||
-rw-r--r-- | src/Daemon.hxx | 6 | ||||
-rw-r--r-- | src/Log.cxx | 34 | ||||
-rw-r--r-- | src/Main.cxx | 46 | ||||
-rw-r--r-- | src/Mapper.cxx | 52 | ||||
-rw-r--r-- | src/Mapper.hxx | 4 | ||||
-rw-r--r-- | src/StateFile.cxx | 7 | ||||
-rw-r--r-- | src/StateFile.hxx | 3 | ||||
-rw-r--r-- | src/StickerDatabase.cxx | 10 | ||||
-rw-r--r-- | src/StickerDatabase.hxx | 3 | ||||
-rw-r--r-- | src/db/SimpleDatabasePlugin.cxx | 15 | ||||
-rw-r--r-- | src/fs/FileSystem.hxx | 6 | ||||
-rw-r--r-- | src/output/FifoOutputPlugin.cxx | 56 |
19 files changed, 176 insertions, 173 deletions
diff --git a/src/ConfigData.cxx b/src/ConfigData.cxx index 7ac517935..12aa9f69f 100644 --- a/src/ConfigData.cxx +++ b/src/ConfigData.cxx @@ -17,9 +17,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" #include "ConfigData.hxx" #include "ConfigParser.hxx" #include "ConfigPath.hxx" +#include "fs/Path.hxx" #include "mpd_error.h" #include <glib.h> @@ -92,18 +94,18 @@ config_param::DupBlockString(const char *name, const char *default_value) const return g_strdup(GetBlockValue(name, default_value)); } -char * -config_param::DupBlockPath(const char *name, GError **error_r) const +Path +config_param::GetBlockPath(const char *name, GError **error_r) const { assert(error_r != nullptr); assert(*error_r == nullptr); const block_param *bp = GetBlockParam(name); if (bp == nullptr) - return nullptr; + return Path::Null(); - char *path = parsePath(bp->value.c_str(), error_r); - if (G_UNLIKELY(path == nullptr)) + Path path = ParsePath(bp->value.c_str(), error_r); + if (gcc_unlikely(path.IsNull())) g_prefix_error(error_r, "Invalid path in \"%s\" at line %i: ", name, bp->line); diff --git a/src/ConfigData.hxx b/src/ConfigData.hxx index 2586ed4b2..4d9c0af79 100644 --- a/src/ConfigData.hxx +++ b/src/ConfigData.hxx @@ -28,6 +28,8 @@ #include <array> #include <vector> +class Path; + struct block_param { std::string name; std::string value; @@ -110,8 +112,7 @@ struct config_param { * Same as config_dup_path(), but looks up the setting in the * specified block. */ - gcc_malloc - char *DupBlockPath(const char *name, GError **error_r) const; + Path GetBlockPath(const char *name, GError **error_r) const; gcc_pure unsigned GetBlockValue(const char *name, unsigned default_value) const; diff --git a/src/ConfigGlobal.cxx b/src/ConfigGlobal.cxx index a66c03748..1f89a1283 100644 --- a/src/ConfigGlobal.cxx +++ b/src/ConfigGlobal.cxx @@ -23,6 +23,7 @@ #include "ConfigData.hxx" #include "ConfigFile.hxx" #include "ConfigPath.hxx" +#include "fs/Path.hxx" #include "mpd_error.h" #include <glib.h> @@ -96,18 +97,18 @@ config_get_string(ConfigOption option, const char *default_value) return param->value; } -char * -config_dup_path(ConfigOption option, GError **error_r) +Path +config_get_path(ConfigOption option, GError **error_r) { assert(error_r != NULL); assert(*error_r == NULL); const struct config_param *param = config_get_param(option); if (param == NULL) - return NULL; + return Path::Null(); - char *path = parsePath(param->value, error_r); - if (G_UNLIKELY(path == NULL)) + Path path = ParsePath(param->value, error_r); + if (gcc_unlikely(path.IsNull())) g_prefix_error(error_r, "Invalid path at line %i: ", param->line); diff --git a/src/ConfigGlobal.hxx b/src/ConfigGlobal.hxx index fff813f3e..aaae82bd1 100644 --- a/src/ConfigGlobal.hxx +++ b/src/ConfigGlobal.hxx @@ -72,14 +72,11 @@ 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 NULL if the value is not present. If the path could not be - * parsed, returns NULL and sets the error. - * - * The return value must be freed with g_free(). + * Returns Path::Null() if the value is not present. If the path + * could not be parsed, returns Path::Null() and sets the error. */ -gcc_malloc -char * -config_dup_path(enum ConfigOption option, GError **error_r); +Path +config_get_path(enum ConfigOption option, GError **error_r); gcc_pure unsigned diff --git a/src/ConfigPath.cxx b/src/ConfigPath.cxx index 074891433..b90956a2a 100644 --- a/src/ConfigPath.cxx +++ b/src/ConfigPath.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "ConfigPath.hxx" +#include "fs/Path.hxx" #include "conf.h" #include <glib.h> @@ -52,17 +53,25 @@ parse_path_quark(void) return g_quark_from_static_string("path"); } -char * -parsePath(const char *path, gcc_unused GError **error_r) +Path +ParsePath(const char *path, GError **error_r) { assert(path != nullptr); assert(error_r == nullptr || *error_r == nullptr); + Path path2 = Path::FromUTF8(path); + if (path2.IsNull()) { + g_set_error(error_r, parse_path_quark(), 0, + "Failed to convert path to file system charset: %s", + path); + return Path::Null(); + } + #ifndef WIN32 if (!g_path_is_absolute(path) && path[0] != '~') { g_set_error(error_r, parse_path_quark(), 0, "not an absolute path: %s", path); - return nullptr; + return Path::Null(); } else if (path[0] == '~') { const char *home; @@ -73,7 +82,7 @@ parsePath(const char *path, gcc_unused GError **error_r) if (!passwd) { g_set_error(error_r, parse_path_quark(), 0, "no such user: %s", user); - return nullptr; + return Path::Null(); } home = passwd->pw_dir; @@ -83,7 +92,7 @@ parsePath(const char *path, gcc_unused GError **error_r) g_set_error_literal(error_r, parse_path_quark(), 0, "problems getting home " "for current user"); - return nullptr; + return Path::Null(); } } @@ -101,7 +110,7 @@ parsePath(const char *path, gcc_unused GError **error_r) g_set_error(error_r, parse_path_quark(), 0, "no such user: %s", user); g_free(user); - return nullptr; + return Path::Null(); } g_free(user); @@ -110,10 +119,10 @@ parsePath(const char *path, gcc_unused GError **error_r) path = slash; } - return g_strconcat(home, path, nullptr); + return Path::Build(home, path2); } else { #endif - return g_strdup(path); + return path2; #ifndef WIN32 } #endif diff --git a/src/ConfigPath.hxx b/src/ConfigPath.hxx index 42e51215f..79da04bb1 100644 --- a/src/ConfigPath.hxx +++ b/src/ConfigPath.hxx @@ -22,7 +22,9 @@ #include "gerror.h" -char * -parsePath(const char *path, GError **error_r); +class Path; + +Path +ParsePath(const char *path, GError **error_r); #endif diff --git a/src/Daemon.cxx b/src/Daemon.cxx index e0990d146..6b4e398fa 100644 --- a/src/Daemon.cxx +++ b/src/Daemon.cxx @@ -20,6 +20,8 @@ #include "config.h" #include "Daemon.hxx" #include "system/FatalError.hxx" +#include "fs/Path.hxx" +#include "fs/FileSystem.hxx" #include <glib.h> @@ -52,7 +54,7 @@ static uid_t user_uid = (uid_t)-1; static gid_t user_gid = (pid_t)-1; /** the absolute path of the pidfile */ -static char *pidfile; +static Path pidfile = Path::Null(); /* whether "group" conf. option was given */ static bool had_group = false; @@ -64,17 +66,20 @@ daemonize_kill(void) FILE *fp; int pid, ret; - if (pidfile == nullptr) + if (pidfile.IsNull()) FatalError("no pid_file specified in the config file"); - fp = fopen(pidfile, "r"); - if (fp == nullptr) + fp = FOpen(pidfile, "r"); + if (fp == nullptr) { + const std::string utf8 = pidfile.ToUTF8(); FormatFatalSystemError("Unable to open pid file \"%s\"", - pidfile); + utf8.c_str()); + } if (fscanf(fp, "%i", &pid) != 1) { + const std::string utf8 = pidfile.ToUTF8(); FormatFatalError("unable to read the pid from file \"%s\"", - pidfile); + utf8.c_str()); } fclose(fp); @@ -173,21 +178,22 @@ daemonize(bool detach) { FILE *fp = nullptr; - if (pidfile != nullptr) { + if (!pidfile.IsNull()) { /* do this before daemon'izing so we can fail gracefully if we can't * write to the pid file */ g_debug("opening pid file"); - fp = fopen(pidfile, "w+"); + fp = FOpen(pidfile, "w+"); if (!fp) { + const std::string utf8 = pidfile.ToUTF8(); FormatFatalSystemError("Failed to create pid file \"%s\"", - pidfile); + pidfile.c_str()); } } if (detach) daemonize_detach(); - if (pidfile != nullptr) { + if (!pidfile.IsNull()) { g_debug("writing pid file"); fprintf(fp, "%lu\n", (unsigned long)getpid()); fclose(fp); @@ -195,7 +201,7 @@ daemonize(bool detach) } void -daemonize_init(const char *user, const char *group, const char *_pidfile) +daemonize_init(const char *user, const char *group, Path &&_pidfile) { if (user) { struct passwd *pwd = getpwnam(user); @@ -220,17 +226,18 @@ daemonize_init(const char *user, const char *group, const char *_pidfile) } - pidfile = g_strdup(_pidfile); + pidfile = _pidfile; } void daemonize_finish(void) { - if (pidfile != nullptr) - unlink(pidfile); + if (!pidfile.IsNull()) { + RemoveFile(pidfile); + pidfile = Path::Null(); + } g_free(user_name); - g_free(pidfile); } #endif diff --git a/src/Daemon.hxx b/src/Daemon.hxx index 6c27ebc3e..c662b9bee 100644 --- a/src/Daemon.hxx +++ b/src/Daemon.hxx @@ -20,12 +20,14 @@ #ifndef MPD_DAEMON_HXX #define MPD_DAEMON_HXX +class Path; + #ifndef WIN32 void -daemonize_init(const char *user, const char *group, const char *pidfile); +daemonize_init(const char *user, const char *group, Path &&pidfile); #else static inline void -daemonize_init(const char *user, const char *group, const char *pidfile) +daemonize_init(const char *user, const char *group, Path &&pidfile) { (void)user; (void)group; (void)pidfile; } #endif diff --git a/src/Log.cxx b/src/Log.cxx index 52b8be3ba..fac5d95f1 100644 --- a/src/Log.cxx +++ b/src/Log.cxx @@ -22,6 +22,8 @@ #include "conf.h" #include "system/fd_util.h" #include "system/FatalError.hxx" +#include "fs/Path.hxx" +#include "fs/FileSystem.hxx" #include "mpd_error.h" #include <assert.h> @@ -55,7 +57,7 @@ static const char *log_charset; static bool stdout_mode = true; static int out_fd; -static char *out_filename; +static Path out_path = Path::Null(); static void redirect_logs(int fd) { @@ -128,21 +130,22 @@ log_init_stdout(void) static int open_log_file(void) { - assert(out_filename != NULL); + assert(!out_path.IsNull()); - return open_cloexec(out_filename, O_CREAT | O_WRONLY | O_APPEND, 0666); + return OpenFile(out_path, O_CREAT | O_WRONLY | O_APPEND, 0666); } static bool log_init_file(unsigned line, GError **error_r) { - assert(out_filename != NULL); + assert(!out_path.IsNull()); out_fd = open_log_file(); if (out_fd < 0) { + const std::string out_path_utf8 = out_path.ToUTF8(); g_set_error(error_r, log_quark(), errno, "failed to open log file \"%s\" (config line %u): %s", - out_filename, line, g_strerror(errno)); + out_path_utf8.c_str(), line, g_strerror(errno)); return false; } @@ -204,7 +207,7 @@ syslog_log_func(const gchar *log_domain, static void log_init_syslog(void) { - assert(out_filename == NULL); + assert(out_path.IsNull()); openlog(PACKAGE, 0, LOG_DAEMON); g_log_set_default_handler(syslog_log_func, NULL); @@ -271,8 +274,8 @@ log_init(bool verbose, bool use_stdout, GError **error_r) return true; #endif } else { - out_filename = config_dup_path(CONF_LOG_FILE, error_r); - return out_filename != NULL && + out_path = config_get_path(CONF_LOG_FILE, error_r); + return !out_path.IsNull() && log_init_file(param->line, error_r); } } @@ -285,7 +288,7 @@ close_log_files(void) return; #ifdef HAVE_SYSLOG - if (out_filename == NULL) + if (out_path.IsNull()) closelog(); #endif } @@ -294,7 +297,7 @@ void log_deinit(void) { close_log_files(); - g_free(out_filename); + out_path = Path::Null(); } @@ -303,7 +306,7 @@ void setup_log_output(bool use_stdout) fflush(NULL); if (!use_stdout) { #ifndef WIN32 - if (out_filename == NULL) + if (out_path.IsNull()) out_fd = open("/dev/null", O_WRONLY); #endif @@ -321,16 +324,19 @@ int cycle_log_files(void) { int fd; - if (stdout_mode || out_filename == NULL) + if (stdout_mode || out_path.IsNull()) return 0; - assert(out_filename); + + assert(!out_path.IsNull()); g_debug("Cycling log files...\n"); close_log_files(); fd = open_log_file(); if (fd < 0) { - g_warning("error re-opening log file: %s\n", out_filename); + const std::string out_path_utf8 = out_path.ToUTF8(); + g_warning("error re-opening log file: %s", + out_path_utf8.c_str()); return -1; } diff --git a/src/Main.cxx b/src/Main.cxx index 42403922c..56f5b2c07 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -111,16 +111,15 @@ glue_daemonize_init(const struct options *options, GError **error_r) { GError *error = NULL; - char *pid_file = config_dup_path(CONF_PID_FILE, &error); - if (pid_file == NULL && error != NULL) { + Path pid_file = config_get_path(CONF_PID_FILE, &error); + if (pid_file.IsNull() && error != NULL) { g_propagate_error(error_r, error); return false; } daemonize_init(config_get_string(CONF_USER, NULL), config_get_string(CONF_GROUP, NULL), - pid_file); - g_free(pid_file); + std::move(pid_file)); if (options->kill) daemonize_kill(); @@ -132,28 +131,22 @@ static bool glue_mapper_init(GError **error_r) { GError *error = NULL; - char *music_dir = config_dup_path(CONF_MUSIC_DIR, &error); - if (music_dir == NULL && error != NULL) { + Path music_dir = config_get_path(CONF_MUSIC_DIR, &error); + if (music_dir.IsNull() && error != NULL) { g_propagate_error(error_r, error); return false; } - char *playlist_dir = config_dup_path(CONF_PLAYLIST_DIR, &error); - if (playlist_dir == NULL && error != NULL) { + Path playlist_dir = config_get_path(CONF_PLAYLIST_DIR, &error); + if (playlist_dir.IsNull() && error != NULL) { g_propagate_error(error_r, error); return false; } - if (music_dir == NULL) - music_dir = g_strdup(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC)); + if (music_dir.IsNull()) + music_dir = Path::FromUTF8(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC)); - if (!mapper_init(music_dir, playlist_dir, &error)) { - g_propagate_error(error_r, error); - return false; - } - - g_free(music_dir); - g_free(playlist_dir); + mapper_init(std::move(music_dir), std::move(playlist_dir)); return true; } @@ -213,14 +206,12 @@ glue_sticker_init(void) { #ifdef ENABLE_SQLITE GError *error = NULL; - char *sticker_file = config_dup_path(CONF_STICKER_FILE, &error); - if (sticker_file == NULL && error != NULL) + Path sticker_file = config_get_path(CONF_STICKER_FILE, &error); + if (sticker_file.IsNull() && error != NULL) FatalError(error); - if (!sticker_global_init(sticker_file, &error)) + if (!sticker_global_init(std::move(sticker_file), &error)) FatalError(error); - - g_free(sticker_file); #endif } @@ -229,8 +220,8 @@ glue_state_file_init(GError **error_r) { GError *error = NULL; - char *path = config_dup_path(CONF_STATE_FILE, &error); - if (path == nullptr) { + Path path_fs = config_get_path(CONF_STATE_FILE, &error); + if (path_fs.IsNull()) { if (error != nullptr) { g_propagate_error(error_r, error); return false; @@ -239,19 +230,14 @@ glue_state_file_init(GError **error_r) return true; } - Path path_fs = Path::FromUTF8(path); - if (path_fs.IsNull()) { - g_free(path); g_set_error(error_r, main_quark(), 0, "Failed to convert state file path to FS encoding"); return false; } - state_file = new StateFile(std::move(path_fs), path, + state_file = new StateFile(std::move(path_fs), *instance->partition, *main_loop); - g_free(path); - state_file->Read(); return true; } diff --git a/src/Mapper.cxx b/src/Mapper.cxx index 6f4a9cdcc..c07cb12d0 100644 --- a/src/Mapper.cxx +++ b/src/Mapper.cxx @@ -104,52 +104,40 @@ check_directory(const char *path_utf8, const Path &path_fs) g_warning("No permission to read directory: %s", path_utf8); } -static bool -mapper_set_music_dir(const char *path_utf8, GError **error_r) +static void +mapper_set_music_dir(Path &&path) { - music_dir_fs = Path::FromUTF8(path_utf8); - if (music_dir_fs.IsNull()) { - g_set_error(error_r, mapper_quark(), 0, - "Failed to convert music path to FS encoding"); - return false; - } + assert(!path.IsNull()); + music_dir_fs = path; music_dir_fs_length = music_dir_fs.length(); - music_dir_utf8 = strdup_chop_slash(path_utf8); + const auto utf8 = music_dir_fs.ToUTF8(); + music_dir_utf8 = strdup_chop_slash(utf8.c_str()); music_dir_utf8_length = strlen(music_dir_utf8); - check_directory(path_utf8, music_dir_fs); - - return true; + check_directory(music_dir_utf8, music_dir_fs); } -static bool -mapper_set_playlist_dir(const char *path_utf8, GError **error_r) +static void +mapper_set_playlist_dir(Path &&path) { - playlist_dir_fs = Path::FromUTF8(path_utf8); - if (playlist_dir_fs.IsNull()) { - g_set_error(error_r, mapper_quark(), 0, - "Failed to convert playlist path to FS encoding"); - return false; - } + assert(!path.IsNull()); + + playlist_dir_fs = path; - check_directory(path_utf8, playlist_dir_fs); - return true; + const auto utf8 = playlist_dir_fs.ToUTF8(); + check_directory(utf8.c_str(), playlist_dir_fs); } -bool mapper_init(const char *_music_dir, const char *_playlist_dir, - GError **error_r) +void +mapper_init(Path &&_music_dir, Path &&_playlist_dir) { - if (_music_dir != NULL) - if (!mapper_set_music_dir(_music_dir, error_r)) - return false; - - if (_playlist_dir != NULL) - if (!mapper_set_playlist_dir(_playlist_dir, error_r)) - return false; + if (!_music_dir.IsNull()) + mapper_set_music_dir(std::move(_music_dir)); - return true; + if (!_playlist_dir.IsNull()) + mapper_set_playlist_dir(std::move(_playlist_dir)); } void mapper_finish(void) diff --git a/src/Mapper.hxx b/src/Mapper.hxx index f114f27f0..1d3da3c00 100644 --- a/src/Mapper.hxx +++ b/src/Mapper.hxx @@ -33,8 +33,8 @@ class Path; struct Directory; struct Song; -bool mapper_init(const char *_music_dir, const char *_playlist_dir, - GError **error_r); +void +mapper_init(Path &&music_dir, Path &&playlist_dir); void mapper_finish(void); diff --git a/src/StateFile.cxx b/src/StateFile.cxx index 73af1777c..caba82da8 100644 --- a/src/StateFile.cxx +++ b/src/StateFile.cxx @@ -34,9 +34,10 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "state_file" -StateFile::StateFile(Path &&_path, const char *_path_utf8, - Partition &_partition, EventLoop &_loop) - :TimeoutMonitor(_loop), path(std::move(_path)), path_utf8(_path_utf8), +StateFile::StateFile(Path &&_path, + Partition &_partition, EventLoop &_loop) + :TimeoutMonitor(_loop), + path(std::move(_path)), path_utf8(path.ToUTF8()), partition(_partition), prev_volume_version(0), prev_output_version(0), prev_playlist_version(0) diff --git a/src/StateFile.hxx b/src/StateFile.hxx index a97e4e2c3..041650d14 100644 --- a/src/StateFile.hxx +++ b/src/StateFile.hxx @@ -42,8 +42,7 @@ class StateFile final : private TimeoutMonitor { prev_playlist_version; public: - StateFile(Path &&path, const char *path_utf8, - Partition &partition, EventLoop &loop); + StateFile(Path &&path, Partition &partition, EventLoop &loop); void Read(); void Write(); diff --git a/src/StickerDatabase.cxx b/src/StickerDatabase.cxx index 2d77e4b63..f153231de 100644 --- a/src/StickerDatabase.cxx +++ b/src/StickerDatabase.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "StickerDatabase.hxx" +#include "fs/Path.hxx" #include "Idle.hxx" #include <string> @@ -104,21 +105,22 @@ sticker_prepare(const char *sql, GError **error_r) } bool -sticker_global_init(const char *path, GError **error_r) +sticker_global_init(Path &&path, GError **error_r) { int ret; - if (path == NULL) + if (path.IsNull()) /* not configured */ return true; /* open/create the sqlite database */ - ret = sqlite3_open(path, &sticker_db); + ret = sqlite3_open(path.c_str(), &sticker_db); if (ret != SQLITE_OK) { + const std::string utf8 = path.ToUTF8(); g_set_error(error_r, sticker_quark(), ret, "Failed to open sqlite database '%s': %s", - path, sqlite3_errmsg(sticker_db)); + utf8.c_str(), sqlite3_errmsg(sticker_db)); return false; } diff --git a/src/StickerDatabase.hxx b/src/StickerDatabase.hxx index 90ff9b066..9034c8bb8 100644 --- a/src/StickerDatabase.hxx +++ b/src/StickerDatabase.hxx @@ -44,6 +44,7 @@ #include "gerror.h" +class Path; struct sticker; /** @@ -54,7 +55,7 @@ struct sticker; * @return true on success, false on error */ bool -sticker_global_init(const char *path, GError **error_r); +sticker_global_init(Path &&path, GError **error_r); /** * Close the sticker database. diff --git a/src/db/SimpleDatabasePlugin.cxx b/src/db/SimpleDatabasePlugin.cxx index 7690a188b..373064c3f 100644 --- a/src/db/SimpleDatabasePlugin.cxx +++ b/src/db/SimpleDatabasePlugin.cxx @@ -57,8 +57,8 @@ SimpleDatabase::Configure(const config_param ¶m, GError **error_r) { GError *error = NULL; - char *_path = param.DupBlockPath("path", &error); - if (_path == NULL) { + path = param.GetBlockPath("path", &error); + if (path.IsNull()) { if (error != NULL) g_propagate_error(error_r, error); else @@ -67,16 +67,7 @@ SimpleDatabase::Configure(const config_param ¶m, GError **error_r) return false; } - path = Path::FromUTF8(_path); - path_utf8 = _path; - - free(_path); - - if (path.IsNull()) { - g_set_error(error_r, simple_db_quark(), 0, - "Failed to convert database path to FS encoding"); - return false; - } + path_utf8 = path.ToUTF8(); return true; } diff --git a/src/fs/FileSystem.hxx b/src/fs/FileSystem.hxx index 4df415e0a..aab5f3bfb 100644 --- a/src/fs/FileSystem.hxx +++ b/src/fs/FileSystem.hxx @@ -116,6 +116,12 @@ static inline bool RemoveFile(const Path &file) */ Path ReadLink(const Path &path); +static inline bool +MakeFifo(const Path &path, mode_t mode) +{ + return mkfifo(path.c_str(), mode) == 0; +} + /** * Wrapper for access() that uses #Path names. */ diff --git a/src/output/FifoOutputPlugin.cxx b/src/output/FifoOutputPlugin.cxx index 4d1b56e69..29dd50cb1 100644 --- a/src/output/FifoOutputPlugin.cxx +++ b/src/output/FifoOutputPlugin.cxx @@ -22,6 +22,8 @@ #include "OutputAPI.hxx" #include "Timer.hxx" #include "system/fd_util.h" +#include "fs/Path.hxx" +#include "fs/FileSystem.hxx" #include "open.h" #include <glib.h> @@ -40,18 +42,16 @@ struct FifoOutput { struct audio_output base; - char *path; + Path path; + std::string path_utf8; + int input; int output; bool created; Timer *timer; FifoOutput() - :path(nullptr), input(-1), output(-1), created(false) {} - - ~FifoOutput() { - g_free(path); - } + :path(Path::Null()), input(-1), output(-1), created(false) {} bool Initialize(const config_param ¶m, GError **error_r) { return ao_base_init(&base, &fifo_output_plugin, param, @@ -82,11 +82,11 @@ fifo_output_quark(void) inline void FifoOutput::Delete() { - g_debug("Removing FIFO \"%s\"", path); + g_debug("Removing FIFO \"%s\"", path_utf8.c_str()); - if (unlink(path) < 0) { + if (!RemoveFile(path)) { g_warning("Could not remove FIFO \"%s\": %s", - path, g_strerror(errno)); + path_utf8.c_str(), g_strerror(errno)); return; } @@ -96,8 +96,6 @@ FifoOutput::Delete() void FifoOutput::Close() { - struct stat st; - if (input >= 0) { close(input); input = -1; @@ -108,17 +106,18 @@ FifoOutput::Close() output = -1; } - if (created && (stat(path, &st) == 0)) + struct stat st; + if (created && StatFile(path, st)) Delete(); } inline bool FifoOutput::Create(GError **error_r) { - if (mkfifo(path, 0666) < 0) { + if (!MakeFifo(path, 0666)) { g_set_error(error_r, fifo_output_quark(), errno, "Couldn't create FIFO \"%s\": %s", - path, g_strerror(errno)); + path_utf8.c_str(), g_strerror(errno)); return false; } @@ -130,7 +129,7 @@ inline bool FifoOutput::Check(GError **error_r) { struct stat st; - if (stat(path, &st) < 0) { + if (!StatFile(path, st)) { if (errno == ENOENT) { /* Path doesn't exist */ return Create(error_r); @@ -138,14 +137,14 @@ FifoOutput::Check(GError **error_r) g_set_error(error_r, fifo_output_quark(), errno, "Failed to stat FIFO \"%s\": %s", - path, g_strerror(errno)); + path_utf8.c_str(), g_strerror(errno)); return false; } if (!S_ISFIFO(st.st_mode)) { g_set_error(error_r, fifo_output_quark(), 0, "\"%s\" already exists, but is not a FIFO", - path); + path_utf8.c_str()); return false; } @@ -158,20 +157,20 @@ FifoOutput::Open(GError **error_r) if (!Check(error_r)) return false; - input = open_cloexec(path, O_RDONLY|O_NONBLOCK|O_BINARY, 0); + input = OpenFile(path, O_RDONLY|O_NONBLOCK|O_BINARY, 0); if (input < 0) { g_set_error(error_r, fifo_output_quark(), errno, "Could not open FIFO \"%s\" for reading: %s", - path, g_strerror(errno)); + path_utf8.c_str(), g_strerror(errno)); Close(); return false; } - output = open_cloexec(path, O_WRONLY|O_NONBLOCK|O_BINARY, 0); + output = OpenFile(path, O_WRONLY|O_NONBLOCK|O_BINARY, 0); if (output < 0) { g_set_error(error_r, fifo_output_quark(), errno, "Could not open FIFO \"%s\" for writing: %s", - path, g_strerror(errno)); + path_utf8.c_str(), g_strerror(errno)); Close(); return false; } @@ -189,8 +188,12 @@ static struct audio_output * fifo_output_init(const config_param ¶m, GError **error_r) { GError *error = nullptr; - char *path = param.DupBlockPath("path", &error); - if (!path) { + + FifoOutput *fd = new FifoOutput(); + + fd->path = param.GetBlockPath("path", &error); + if (fd->path.IsNull()) { + delete fd; if (error != nullptr) g_propagate_error(error_r, error); else @@ -199,8 +202,7 @@ fifo_output_init(const config_param ¶m, GError **error_r) return nullptr; } - FifoOutput *fd = new FifoOutput(); - fd->path = path; + fd->path_utf8 = fd->path.ToUTF8(); if (!fd->Initialize(param, error_r)) { delete fd; @@ -259,7 +261,7 @@ fifo_output_cancel(struct audio_output *ao) if (bytes < 0 && errno != EAGAIN) { g_warning("Flush of FIFO \"%s\" failed: %s", - fd->path, g_strerror(errno)); + fd->path_utf8.c_str(), g_strerror(errno)); } } @@ -301,7 +303,7 @@ fifo_output_play(struct audio_output *ao, const void *chunk, size_t size, g_set_error(error, fifo_output_quark(), errno, "Failed to write to FIFO %s: %s", - fd->path, g_strerror(errno)); + fd->path_utf8.c_str(), g_strerror(errno)); return 0; } } |