aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ConfigData.cxx12
-rw-r--r--src/ConfigData.hxx5
-rw-r--r--src/ConfigGlobal.cxx11
-rw-r--r--src/ConfigGlobal.hxx11
-rw-r--r--src/ConfigPath.cxx25
-rw-r--r--src/ConfigPath.hxx6
-rw-r--r--src/Daemon.cxx37
-rw-r--r--src/Daemon.hxx6
-rw-r--r--src/Log.cxx34
-rw-r--r--src/Main.cxx46
-rw-r--r--src/Mapper.cxx52
-rw-r--r--src/Mapper.hxx4
-rw-r--r--src/StateFile.cxx7
-rw-r--r--src/StateFile.hxx3
-rw-r--r--src/StickerDatabase.cxx10
-rw-r--r--src/StickerDatabase.hxx3
-rw-r--r--src/db/SimpleDatabasePlugin.cxx15
-rw-r--r--src/fs/FileSystem.hxx6
-rw-r--r--src/output/FifoOutputPlugin.cxx56
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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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;
}
}