Commit b76a29a6 authored by Max Kellermann's avatar Max Kellermann

ConfigPath: return a Path object

Migrate all callers to use Path directly, instead of doing the conversion in each caller.
parent abe090ec
...@@ -17,9 +17,11 @@ ...@@ -17,9 +17,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "config.h"
#include "ConfigData.hxx" #include "ConfigData.hxx"
#include "ConfigParser.hxx" #include "ConfigParser.hxx"
#include "ConfigPath.hxx" #include "ConfigPath.hxx"
#include "fs/Path.hxx"
#include "mpd_error.h" #include "mpd_error.h"
#include <glib.h> #include <glib.h>
...@@ -92,18 +94,18 @@ config_param::DupBlockString(const char *name, const char *default_value) const ...@@ -92,18 +94,18 @@ config_param::DupBlockString(const char *name, const char *default_value) const
return g_strdup(GetBlockValue(name, default_value)); return g_strdup(GetBlockValue(name, default_value));
} }
char * Path
config_param::DupBlockPath(const char *name, GError **error_r) const config_param::GetBlockPath(const char *name, GError **error_r) const
{ {
assert(error_r != nullptr); assert(error_r != nullptr);
assert(*error_r == nullptr); assert(*error_r == nullptr);
const block_param *bp = GetBlockParam(name); const block_param *bp = GetBlockParam(name);
if (bp == nullptr) if (bp == nullptr)
return nullptr; return Path::Null();
char *path = parsePath(bp->value.c_str(), error_r); Path path = ParsePath(bp->value.c_str(), error_r);
if (G_UNLIKELY(path == nullptr)) if (gcc_unlikely(path.IsNull()))
g_prefix_error(error_r, g_prefix_error(error_r,
"Invalid path in \"%s\" at line %i: ", "Invalid path in \"%s\" at line %i: ",
name, bp->line); name, bp->line);
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <array> #include <array>
#include <vector> #include <vector>
class Path;
struct block_param { struct block_param {
std::string name; std::string name;
std::string value; std::string value;
...@@ -110,8 +112,7 @@ struct config_param { ...@@ -110,8 +112,7 @@ struct config_param {
* Same as config_dup_path(), but looks up the setting in the * Same as config_dup_path(), but looks up the setting in the
* specified block. * specified block.
*/ */
gcc_malloc Path GetBlockPath(const char *name, GError **error_r) const;
char *DupBlockPath(const char *name, GError **error_r) const;
gcc_pure gcc_pure
unsigned GetBlockValue(const char *name, unsigned default_value) const; unsigned GetBlockValue(const char *name, unsigned default_value) const;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "ConfigData.hxx" #include "ConfigData.hxx"
#include "ConfigFile.hxx" #include "ConfigFile.hxx"
#include "ConfigPath.hxx" #include "ConfigPath.hxx"
#include "fs/Path.hxx"
#include "mpd_error.h" #include "mpd_error.h"
#include <glib.h> #include <glib.h>
...@@ -96,18 +97,18 @@ config_get_string(ConfigOption option, const char *default_value) ...@@ -96,18 +97,18 @@ config_get_string(ConfigOption option, const char *default_value)
return param->value; return param->value;
} }
char * Path
config_dup_path(ConfigOption option, GError **error_r) config_get_path(ConfigOption option, GError **error_r)
{ {
assert(error_r != NULL); assert(error_r != NULL);
assert(*error_r == NULL); assert(*error_r == NULL);
const struct config_param *param = config_get_param(option); const struct config_param *param = config_get_param(option);
if (param == NULL) if (param == NULL)
return NULL; return Path::Null();
char *path = parsePath(param->value, error_r); Path path = ParsePath(param->value, error_r);
if (G_UNLIKELY(path == NULL)) if (gcc_unlikely(path.IsNull()))
g_prefix_error(error_r, g_prefix_error(error_r,
"Invalid path at line %i: ", "Invalid path at line %i: ",
param->line); param->line);
......
...@@ -72,14 +72,11 @@ config_get_string(enum ConfigOption option, const char *default_value); ...@@ -72,14 +72,11 @@ config_get_string(enum ConfigOption option, const char *default_value);
/** /**
* Returns an optional configuration variable which contains an * Returns an optional configuration variable which contains an
* absolute path. If there is a tilde prefix, it is expanded. * 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 * Returns Path::Null() if the value is not present. If the path
* parsed, returns NULL and sets the error. * could not be parsed, returns Path::Null() and sets the error.
*
* The return value must be freed with g_free().
*/ */
gcc_malloc Path
char * config_get_path(enum ConfigOption option, GError **error_r);
config_dup_path(enum ConfigOption option, GError **error_r);
gcc_pure gcc_pure
unsigned unsigned
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "config.h" #include "config.h"
#include "ConfigPath.hxx" #include "ConfigPath.hxx"
#include "fs/Path.hxx"
#include "conf.h" #include "conf.h"
#include <glib.h> #include <glib.h>
...@@ -52,17 +53,25 @@ parse_path_quark(void) ...@@ -52,17 +53,25 @@ parse_path_quark(void)
return g_quark_from_static_string("path"); return g_quark_from_static_string("path");
} }
char * Path
parsePath(const char *path, gcc_unused GError **error_r) ParsePath(const char *path, GError **error_r)
{ {
assert(path != nullptr); assert(path != nullptr);
assert(error_r == nullptr || *error_r == 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 #ifndef WIN32
if (!g_path_is_absolute(path) && path[0] != '~') { if (!g_path_is_absolute(path) && path[0] != '~') {
g_set_error(error_r, parse_path_quark(), 0, g_set_error(error_r, parse_path_quark(), 0,
"not an absolute path: %s", path); "not an absolute path: %s", path);
return nullptr; return Path::Null();
} else if (path[0] == '~') { } else if (path[0] == '~') {
const char *home; const char *home;
...@@ -73,7 +82,7 @@ parsePath(const char *path, gcc_unused GError **error_r) ...@@ -73,7 +82,7 @@ parsePath(const char *path, gcc_unused GError **error_r)
if (!passwd) { if (!passwd) {
g_set_error(error_r, parse_path_quark(), 0, g_set_error(error_r, parse_path_quark(), 0,
"no such user: %s", user); "no such user: %s", user);
return nullptr; return Path::Null();
} }
home = passwd->pw_dir; home = passwd->pw_dir;
...@@ -83,7 +92,7 @@ parsePath(const char *path, gcc_unused GError **error_r) ...@@ -83,7 +92,7 @@ parsePath(const char *path, gcc_unused GError **error_r)
g_set_error_literal(error_r, parse_path_quark(), 0, g_set_error_literal(error_r, parse_path_quark(), 0,
"problems getting home " "problems getting home "
"for current user"); "for current user");
return nullptr; return Path::Null();
} }
} }
...@@ -101,7 +110,7 @@ parsePath(const char *path, gcc_unused GError **error_r) ...@@ -101,7 +110,7 @@ parsePath(const char *path, gcc_unused GError **error_r)
g_set_error(error_r, parse_path_quark(), 0, g_set_error(error_r, parse_path_quark(), 0,
"no such user: %s", user); "no such user: %s", user);
g_free(user); g_free(user);
return nullptr; return Path::Null();
} }
g_free(user); g_free(user);
...@@ -110,10 +119,10 @@ parsePath(const char *path, gcc_unused GError **error_r) ...@@ -110,10 +119,10 @@ parsePath(const char *path, gcc_unused GError **error_r)
path = slash; path = slash;
} }
return g_strconcat(home, path, nullptr); return Path::Build(home, path2);
} else { } else {
#endif #endif
return g_strdup(path); return path2;
#ifndef WIN32 #ifndef WIN32
} }
#endif #endif
......
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
#include "gerror.h" #include "gerror.h"
char * class Path;
parsePath(const char *path, GError **error_r);
Path
ParsePath(const char *path, GError **error_r);
#endif #endif
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include "config.h" #include "config.h"
#include "Daemon.hxx" #include "Daemon.hxx"
#include "system/FatalError.hxx" #include "system/FatalError.hxx"
#include "fs/Path.hxx"
#include "fs/FileSystem.hxx"
#include <glib.h> #include <glib.h>
...@@ -52,7 +54,7 @@ static uid_t user_uid = (uid_t)-1; ...@@ -52,7 +54,7 @@ static uid_t user_uid = (uid_t)-1;
static gid_t user_gid = (pid_t)-1; static gid_t user_gid = (pid_t)-1;
/** the absolute path of the pidfile */ /** the absolute path of the pidfile */
static char *pidfile; static Path pidfile = Path::Null();
/* whether "group" conf. option was given */ /* whether "group" conf. option was given */
static bool had_group = false; static bool had_group = false;
...@@ -64,17 +66,20 @@ daemonize_kill(void) ...@@ -64,17 +66,20 @@ daemonize_kill(void)
FILE *fp; FILE *fp;
int pid, ret; int pid, ret;
if (pidfile == nullptr) if (pidfile.IsNull())
FatalError("no pid_file specified in the config file"); FatalError("no pid_file specified in the config file");
fp = fopen(pidfile, "r"); fp = FOpen(pidfile, "r");
if (fp == nullptr) if (fp == nullptr) {
const std::string utf8 = pidfile.ToUTF8();
FormatFatalSystemError("Unable to open pid file \"%s\"", FormatFatalSystemError("Unable to open pid file \"%s\"",
pidfile); utf8.c_str());
}
if (fscanf(fp, "%i", &pid) != 1) { if (fscanf(fp, "%i", &pid) != 1) {
const std::string utf8 = pidfile.ToUTF8();
FormatFatalError("unable to read the pid from file \"%s\"", FormatFatalError("unable to read the pid from file \"%s\"",
pidfile); utf8.c_str());
} }
fclose(fp); fclose(fp);
...@@ -173,21 +178,22 @@ daemonize(bool detach) ...@@ -173,21 +178,22 @@ daemonize(bool detach)
{ {
FILE *fp = nullptr; FILE *fp = nullptr;
if (pidfile != nullptr) { if (!pidfile.IsNull()) {
/* do this before daemon'izing so we can fail gracefully if we can't /* do this before daemon'izing so we can fail gracefully if we can't
* write to the pid file */ * write to the pid file */
g_debug("opening pid file"); g_debug("opening pid file");
fp = fopen(pidfile, "w+"); fp = FOpen(pidfile, "w+");
if (!fp) { if (!fp) {
const std::string utf8 = pidfile.ToUTF8();
FormatFatalSystemError("Failed to create pid file \"%s\"", FormatFatalSystemError("Failed to create pid file \"%s\"",
pidfile); pidfile.c_str());
} }
} }
if (detach) if (detach)
daemonize_detach(); daemonize_detach();
if (pidfile != nullptr) { if (!pidfile.IsNull()) {
g_debug("writing pid file"); g_debug("writing pid file");
fprintf(fp, "%lu\n", (unsigned long)getpid()); fprintf(fp, "%lu\n", (unsigned long)getpid());
fclose(fp); fclose(fp);
...@@ -195,7 +201,7 @@ daemonize(bool detach) ...@@ -195,7 +201,7 @@ daemonize(bool detach)
} }
void void
daemonize_init(const char *user, const char *group, const char *_pidfile) daemonize_init(const char *user, const char *group, Path &&_pidfile)
{ {
if (user) { if (user) {
struct passwd *pwd = getpwnam(user); struct passwd *pwd = getpwnam(user);
...@@ -220,17 +226,18 @@ daemonize_init(const char *user, const char *group, const char *_pidfile) ...@@ -220,17 +226,18 @@ daemonize_init(const char *user, const char *group, const char *_pidfile)
} }
pidfile = g_strdup(_pidfile); pidfile = _pidfile;
} }
void void
daemonize_finish(void) daemonize_finish(void)
{ {
if (pidfile != nullptr) if (!pidfile.IsNull()) {
unlink(pidfile); RemoveFile(pidfile);
pidfile = Path::Null();
}
g_free(user_name); g_free(user_name);
g_free(pidfile);
} }
#endif #endif
...@@ -20,12 +20,14 @@ ...@@ -20,12 +20,14 @@
#ifndef MPD_DAEMON_HXX #ifndef MPD_DAEMON_HXX
#define MPD_DAEMON_HXX #define MPD_DAEMON_HXX
class Path;
#ifndef WIN32 #ifndef WIN32
void void
daemonize_init(const char *user, const char *group, const char *pidfile); daemonize_init(const char *user, const char *group, Path &&pidfile);
#else #else
static inline void 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; } { (void)user; (void)group; (void)pidfile; }
#endif #endif
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "conf.h" #include "conf.h"
#include "system/fd_util.h" #include "system/fd_util.h"
#include "system/FatalError.hxx" #include "system/FatalError.hxx"
#include "fs/Path.hxx"
#include "fs/FileSystem.hxx"
#include "mpd_error.h" #include "mpd_error.h"
#include <assert.h> #include <assert.h>
...@@ -55,7 +57,7 @@ static const char *log_charset; ...@@ -55,7 +57,7 @@ static const char *log_charset;
static bool stdout_mode = true; static bool stdout_mode = true;
static int out_fd; static int out_fd;
static char *out_filename; static Path out_path = Path::Null();
static void redirect_logs(int fd) static void redirect_logs(int fd)
{ {
...@@ -128,21 +130,22 @@ log_init_stdout(void) ...@@ -128,21 +130,22 @@ log_init_stdout(void)
static int static int
open_log_file(void) 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 static bool
log_init_file(unsigned line, GError **error_r) log_init_file(unsigned line, GError **error_r)
{ {
assert(out_filename != NULL); assert(!out_path.IsNull());
out_fd = open_log_file(); out_fd = open_log_file();
if (out_fd < 0) { if (out_fd < 0) {
const std::string out_path_utf8 = out_path.ToUTF8();
g_set_error(error_r, log_quark(), errno, g_set_error(error_r, log_quark(), errno,
"failed to open log file \"%s\" (config line %u): %s", "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; return false;
} }
...@@ -204,7 +207,7 @@ syslog_log_func(const gchar *log_domain, ...@@ -204,7 +207,7 @@ syslog_log_func(const gchar *log_domain,
static void static void
log_init_syslog(void) log_init_syslog(void)
{ {
assert(out_filename == NULL); assert(out_path.IsNull());
openlog(PACKAGE, 0, LOG_DAEMON); openlog(PACKAGE, 0, LOG_DAEMON);
g_log_set_default_handler(syslog_log_func, NULL); g_log_set_default_handler(syslog_log_func, NULL);
...@@ -271,8 +274,8 @@ log_init(bool verbose, bool use_stdout, GError **error_r) ...@@ -271,8 +274,8 @@ log_init(bool verbose, bool use_stdout, GError **error_r)
return true; return true;
#endif #endif
} else { } else {
out_filename = config_dup_path(CONF_LOG_FILE, error_r); out_path = config_get_path(CONF_LOG_FILE, error_r);
return out_filename != NULL && return !out_path.IsNull() &&
log_init_file(param->line, error_r); log_init_file(param->line, error_r);
} }
} }
...@@ -285,7 +288,7 @@ close_log_files(void) ...@@ -285,7 +288,7 @@ close_log_files(void)
return; return;
#ifdef HAVE_SYSLOG #ifdef HAVE_SYSLOG
if (out_filename == NULL) if (out_path.IsNull())
closelog(); closelog();
#endif #endif
} }
...@@ -294,7 +297,7 @@ void ...@@ -294,7 +297,7 @@ void
log_deinit(void) log_deinit(void)
{ {
close_log_files(); close_log_files();
g_free(out_filename); out_path = Path::Null();
} }
...@@ -303,7 +306,7 @@ void setup_log_output(bool use_stdout) ...@@ -303,7 +306,7 @@ void setup_log_output(bool use_stdout)
fflush(NULL); fflush(NULL);
if (!use_stdout) { if (!use_stdout) {
#ifndef WIN32 #ifndef WIN32
if (out_filename == NULL) if (out_path.IsNull())
out_fd = open("/dev/null", O_WRONLY); out_fd = open("/dev/null", O_WRONLY);
#endif #endif
...@@ -321,16 +324,19 @@ int cycle_log_files(void) ...@@ -321,16 +324,19 @@ int cycle_log_files(void)
{ {
int fd; int fd;
if (stdout_mode || out_filename == NULL) if (stdout_mode || out_path.IsNull())
return 0; return 0;
assert(out_filename);
assert(!out_path.IsNull());
g_debug("Cycling log files...\n"); g_debug("Cycling log files...\n");
close_log_files(); close_log_files();
fd = open_log_file(); fd = open_log_file();
if (fd < 0) { 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; return -1;
} }
......
...@@ -111,16 +111,15 @@ glue_daemonize_init(const struct options *options, GError **error_r) ...@@ -111,16 +111,15 @@ glue_daemonize_init(const struct options *options, GError **error_r)
{ {
GError *error = NULL; GError *error = NULL;
char *pid_file = config_dup_path(CONF_PID_FILE, &error); Path pid_file = config_get_path(CONF_PID_FILE, &error);
if (pid_file == NULL && error != NULL) { if (pid_file.IsNull() && error != NULL) {
g_propagate_error(error_r, error); g_propagate_error(error_r, error);
return false; return false;
} }
daemonize_init(config_get_string(CONF_USER, NULL), daemonize_init(config_get_string(CONF_USER, NULL),
config_get_string(CONF_GROUP, NULL), config_get_string(CONF_GROUP, NULL),
pid_file); std::move(pid_file));
g_free(pid_file);
if (options->kill) if (options->kill)
daemonize_kill(); daemonize_kill();
...@@ -132,28 +131,22 @@ static bool ...@@ -132,28 +131,22 @@ static bool
glue_mapper_init(GError **error_r) glue_mapper_init(GError **error_r)
{ {
GError *error = NULL; GError *error = NULL;
char *music_dir = config_dup_path(CONF_MUSIC_DIR, &error); Path music_dir = config_get_path(CONF_MUSIC_DIR, &error);
if (music_dir == NULL && error != NULL) { if (music_dir.IsNull() && error != NULL) {
g_propagate_error(error_r, error); g_propagate_error(error_r, error);
return false; return false;
} }
char *playlist_dir = config_dup_path(CONF_PLAYLIST_DIR, &error); Path playlist_dir = config_get_path(CONF_PLAYLIST_DIR, &error);
if (playlist_dir == NULL && error != NULL) { if (playlist_dir.IsNull() && error != NULL) {
g_propagate_error(error_r, error); g_propagate_error(error_r, error);
return false; return false;
} }
if (music_dir == NULL) if (music_dir.IsNull())
music_dir = g_strdup(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC)); music_dir = Path::FromUTF8(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC));
if (!mapper_init(music_dir, playlist_dir, &error)) { mapper_init(std::move(music_dir), std::move(playlist_dir));
g_propagate_error(error_r, error);
return false;
}
g_free(music_dir);
g_free(playlist_dir);
return true; return true;
} }
...@@ -213,14 +206,12 @@ glue_sticker_init(void) ...@@ -213,14 +206,12 @@ glue_sticker_init(void)
{ {
#ifdef ENABLE_SQLITE #ifdef ENABLE_SQLITE
GError *error = NULL; GError *error = NULL;
char *sticker_file = config_dup_path(CONF_STICKER_FILE, &error); Path sticker_file = config_get_path(CONF_STICKER_FILE, &error);
if (sticker_file == NULL && error != NULL) if (sticker_file.IsNull() && error != NULL)
FatalError(error); FatalError(error);
if (!sticker_global_init(sticker_file, &error)) if (!sticker_global_init(std::move(sticker_file), &error))
FatalError(error); FatalError(error);
g_free(sticker_file);
#endif #endif
} }
...@@ -229,8 +220,8 @@ glue_state_file_init(GError **error_r) ...@@ -229,8 +220,8 @@ glue_state_file_init(GError **error_r)
{ {
GError *error = NULL; GError *error = NULL;
char *path = config_dup_path(CONF_STATE_FILE, &error); Path path_fs = config_get_path(CONF_STATE_FILE, &error);
if (path == nullptr) { if (path_fs.IsNull()) {
if (error != nullptr) { if (error != nullptr) {
g_propagate_error(error_r, error); g_propagate_error(error_r, error);
return false; return false;
...@@ -239,19 +230,14 @@ glue_state_file_init(GError **error_r) ...@@ -239,19 +230,14 @@ glue_state_file_init(GError **error_r)
return true; return true;
} }
Path path_fs = Path::FromUTF8(path);
if (path_fs.IsNull()) { if (path_fs.IsNull()) {
g_free(path);
g_set_error(error_r, main_quark(), 0, g_set_error(error_r, main_quark(), 0,
"Failed to convert state file path to FS encoding"); "Failed to convert state file path to FS encoding");
return false; return false;
} }
state_file = new StateFile(std::move(path_fs), path, state_file = new StateFile(std::move(path_fs),
*instance->partition, *main_loop); *instance->partition, *main_loop);
g_free(path);
state_file->Read(); state_file->Read();
return true; return true;
} }
......
...@@ -104,52 +104,40 @@ check_directory(const char *path_utf8, const Path &path_fs) ...@@ -104,52 +104,40 @@ check_directory(const char *path_utf8, const Path &path_fs)
g_warning("No permission to read directory: %s", path_utf8); g_warning("No permission to read directory: %s", path_utf8);
} }
static bool static void
mapper_set_music_dir(const char *path_utf8, GError **error_r) mapper_set_music_dir(Path &&path)
{ {
music_dir_fs = Path::FromUTF8(path_utf8); assert(!path.IsNull());
if (music_dir_fs.IsNull()) {
g_set_error(error_r, mapper_quark(), 0,
"Failed to convert music path to FS encoding");
return false;
}
music_dir_fs = path;
music_dir_fs_length = music_dir_fs.length(); 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); music_dir_utf8_length = strlen(music_dir_utf8);
check_directory(path_utf8, music_dir_fs); check_directory(music_dir_utf8, music_dir_fs);
return true;
} }
static bool static void
mapper_set_playlist_dir(const char *path_utf8, GError **error_r) mapper_set_playlist_dir(Path &&path)
{ {
playlist_dir_fs = Path::FromUTF8(path_utf8); assert(!path.IsNull());
if (playlist_dir_fs.IsNull()) {
g_set_error(error_r, mapper_quark(), 0, playlist_dir_fs = path;
"Failed to convert playlist path to FS encoding");
return false;
}
check_directory(path_utf8, playlist_dir_fs); const auto utf8 = playlist_dir_fs.ToUTF8();
return true; check_directory(utf8.c_str(), playlist_dir_fs);
} }
bool mapper_init(const char *_music_dir, const char *_playlist_dir, void
GError **error_r) mapper_init(Path &&_music_dir, Path &&_playlist_dir)
{ {
if (_music_dir != NULL) if (!_music_dir.IsNull())
if (!mapper_set_music_dir(_music_dir, error_r)) mapper_set_music_dir(std::move(_music_dir));
return false;
if (_playlist_dir != NULL)
if (!mapper_set_playlist_dir(_playlist_dir, error_r))
return false;
return true; if (!_playlist_dir.IsNull())
mapper_set_playlist_dir(std::move(_playlist_dir));
} }
void mapper_finish(void) void mapper_finish(void)
......
...@@ -33,8 +33,8 @@ class Path; ...@@ -33,8 +33,8 @@ class Path;
struct Directory; struct Directory;
struct Song; struct Song;
bool mapper_init(const char *_music_dir, const char *_playlist_dir, void
GError **error_r); mapper_init(Path &&music_dir, Path &&playlist_dir);
void mapper_finish(void); void mapper_finish(void);
......
...@@ -34,9 +34,10 @@ ...@@ -34,9 +34,10 @@
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "state_file" #define G_LOG_DOMAIN "state_file"
StateFile::StateFile(Path &&_path, const char *_path_utf8, StateFile::StateFile(Path &&_path,
Partition &_partition, EventLoop &_loop) Partition &_partition, EventLoop &_loop)
:TimeoutMonitor(_loop), path(std::move(_path)), path_utf8(_path_utf8), :TimeoutMonitor(_loop),
path(std::move(_path)), path_utf8(path.ToUTF8()),
partition(_partition), partition(_partition),
prev_volume_version(0), prev_output_version(0), prev_volume_version(0), prev_output_version(0),
prev_playlist_version(0) prev_playlist_version(0)
......
...@@ -42,8 +42,7 @@ class StateFile final : private TimeoutMonitor { ...@@ -42,8 +42,7 @@ class StateFile final : private TimeoutMonitor {
prev_playlist_version; prev_playlist_version;
public: public:
StateFile(Path &&path, const char *path_utf8, StateFile(Path &&path, Partition &partition, EventLoop &loop);
Partition &partition, EventLoop &loop);
void Read(); void Read();
void Write(); void Write();
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "config.h" #include "config.h"
#include "StickerDatabase.hxx" #include "StickerDatabase.hxx"
#include "fs/Path.hxx"
#include "Idle.hxx" #include "Idle.hxx"
#include <string> #include <string>
...@@ -104,21 +105,22 @@ sticker_prepare(const char *sql, GError **error_r) ...@@ -104,21 +105,22 @@ sticker_prepare(const char *sql, GError **error_r)
} }
bool bool
sticker_global_init(const char *path, GError **error_r) sticker_global_init(Path &&path, GError **error_r)
{ {
int ret; int ret;
if (path == NULL) if (path.IsNull())
/* not configured */ /* not configured */
return true; return true;
/* open/create the sqlite database */ /* open/create the sqlite database */
ret = sqlite3_open(path, &sticker_db); ret = sqlite3_open(path.c_str(), &sticker_db);
if (ret != SQLITE_OK) { if (ret != SQLITE_OK) {
const std::string utf8 = path.ToUTF8();
g_set_error(error_r, sticker_quark(), ret, g_set_error(error_r, sticker_quark(), ret,
"Failed to open sqlite database '%s': %s", "Failed to open sqlite database '%s': %s",
path, sqlite3_errmsg(sticker_db)); utf8.c_str(), sqlite3_errmsg(sticker_db));
return false; return false;
} }
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "gerror.h" #include "gerror.h"
class Path;
struct sticker; struct sticker;
/** /**
...@@ -54,7 +55,7 @@ struct sticker; ...@@ -54,7 +55,7 @@ struct sticker;
* @return true on success, false on error * @return true on success, false on error
*/ */
bool bool
sticker_global_init(const char *path, GError **error_r); sticker_global_init(Path &&path, GError **error_r);
/** /**
* Close the sticker database. * Close the sticker database.
......
...@@ -57,8 +57,8 @@ SimpleDatabase::Configure(const config_param &param, GError **error_r) ...@@ -57,8 +57,8 @@ SimpleDatabase::Configure(const config_param &param, GError **error_r)
{ {
GError *error = NULL; GError *error = NULL;
char *_path = param.DupBlockPath("path", &error); path = param.GetBlockPath("path", &error);
if (_path == NULL) { if (path.IsNull()) {
if (error != NULL) if (error != NULL)
g_propagate_error(error_r, error); g_propagate_error(error_r, error);
else else
...@@ -67,16 +67,7 @@ SimpleDatabase::Configure(const config_param &param, GError **error_r) ...@@ -67,16 +67,7 @@ SimpleDatabase::Configure(const config_param &param, GError **error_r)
return false; return false;
} }
path = Path::FromUTF8(_path); path_utf8 = path.ToUTF8();
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;
}
return true; return true;
} }
......
...@@ -116,6 +116,12 @@ static inline bool RemoveFile(const Path &file) ...@@ -116,6 +116,12 @@ static inline bool RemoveFile(const Path &file)
*/ */
Path ReadLink(const Path &path); 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. * Wrapper for access() that uses #Path names.
*/ */
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "OutputAPI.hxx" #include "OutputAPI.hxx"
#include "Timer.hxx" #include "Timer.hxx"
#include "system/fd_util.h" #include "system/fd_util.h"
#include "fs/Path.hxx"
#include "fs/FileSystem.hxx"
#include "open.h" #include "open.h"
#include <glib.h> #include <glib.h>
...@@ -40,18 +42,16 @@ ...@@ -40,18 +42,16 @@
struct FifoOutput { struct FifoOutput {
struct audio_output base; struct audio_output base;
char *path; Path path;
std::string path_utf8;
int input; int input;
int output; int output;
bool created; bool created;
Timer *timer; Timer *timer;
FifoOutput() FifoOutput()
:path(nullptr), input(-1), output(-1), created(false) {} :path(Path::Null()), input(-1), output(-1), created(false) {}
~FifoOutput() {
g_free(path);
}
bool Initialize(const config_param &param, GError **error_r) { bool Initialize(const config_param &param, GError **error_r) {
return ao_base_init(&base, &fifo_output_plugin, param, return ao_base_init(&base, &fifo_output_plugin, param,
...@@ -82,11 +82,11 @@ fifo_output_quark(void) ...@@ -82,11 +82,11 @@ fifo_output_quark(void)
inline void inline void
FifoOutput::Delete() 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", g_warning("Could not remove FIFO \"%s\": %s",
path, g_strerror(errno)); path_utf8.c_str(), g_strerror(errno));
return; return;
} }
...@@ -96,8 +96,6 @@ FifoOutput::Delete() ...@@ -96,8 +96,6 @@ FifoOutput::Delete()
void void
FifoOutput::Close() FifoOutput::Close()
{ {
struct stat st;
if (input >= 0) { if (input >= 0) {
close(input); close(input);
input = -1; input = -1;
...@@ -108,17 +106,18 @@ FifoOutput::Close() ...@@ -108,17 +106,18 @@ FifoOutput::Close()
output = -1; output = -1;
} }
if (created && (stat(path, &st) == 0)) struct stat st;
if (created && StatFile(path, st))
Delete(); Delete();
} }
inline bool inline bool
FifoOutput::Create(GError **error_r) FifoOutput::Create(GError **error_r)
{ {
if (mkfifo(path, 0666) < 0) { if (!MakeFifo(path, 0666)) {
g_set_error(error_r, fifo_output_quark(), errno, g_set_error(error_r, fifo_output_quark(), errno,
"Couldn't create FIFO \"%s\": %s", "Couldn't create FIFO \"%s\": %s",
path, g_strerror(errno)); path_utf8.c_str(), g_strerror(errno));
return false; return false;
} }
...@@ -130,7 +129,7 @@ inline bool ...@@ -130,7 +129,7 @@ inline bool
FifoOutput::Check(GError **error_r) FifoOutput::Check(GError **error_r)
{ {
struct stat st; struct stat st;
if (stat(path, &st) < 0) { if (!StatFile(path, st)) {
if (errno == ENOENT) { if (errno == ENOENT) {
/* Path doesn't exist */ /* Path doesn't exist */
return Create(error_r); return Create(error_r);
...@@ -138,14 +137,14 @@ FifoOutput::Check(GError **error_r) ...@@ -138,14 +137,14 @@ FifoOutput::Check(GError **error_r)
g_set_error(error_r, fifo_output_quark(), errno, g_set_error(error_r, fifo_output_quark(), errno,
"Failed to stat FIFO \"%s\": %s", "Failed to stat FIFO \"%s\": %s",
path, g_strerror(errno)); path_utf8.c_str(), g_strerror(errno));
return false; return false;
} }
if (!S_ISFIFO(st.st_mode)) { if (!S_ISFIFO(st.st_mode)) {
g_set_error(error_r, fifo_output_quark(), 0, g_set_error(error_r, fifo_output_quark(), 0,
"\"%s\" already exists, but is not a FIFO", "\"%s\" already exists, but is not a FIFO",
path); path_utf8.c_str());
return false; return false;
} }
...@@ -158,20 +157,20 @@ FifoOutput::Open(GError **error_r) ...@@ -158,20 +157,20 @@ FifoOutput::Open(GError **error_r)
if (!Check(error_r)) if (!Check(error_r))
return false; 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) { if (input < 0) {
g_set_error(error_r, fifo_output_quark(), errno, g_set_error(error_r, fifo_output_quark(), errno,
"Could not open FIFO \"%s\" for reading: %s", "Could not open FIFO \"%s\" for reading: %s",
path, g_strerror(errno)); path_utf8.c_str(), g_strerror(errno));
Close(); Close();
return false; 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) { if (output < 0) {
g_set_error(error_r, fifo_output_quark(), errno, g_set_error(error_r, fifo_output_quark(), errno,
"Could not open FIFO \"%s\" for writing: %s", "Could not open FIFO \"%s\" for writing: %s",
path, g_strerror(errno)); path_utf8.c_str(), g_strerror(errno));
Close(); Close();
return false; return false;
} }
...@@ -189,8 +188,12 @@ static struct audio_output * ...@@ -189,8 +188,12 @@ static struct audio_output *
fifo_output_init(const config_param &param, GError **error_r) fifo_output_init(const config_param &param, GError **error_r)
{ {
GError *error = nullptr; 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) if (error != nullptr)
g_propagate_error(error_r, error); g_propagate_error(error_r, error);
else else
...@@ -199,8 +202,7 @@ fifo_output_init(const config_param &param, GError **error_r) ...@@ -199,8 +202,7 @@ fifo_output_init(const config_param &param, GError **error_r)
return nullptr; return nullptr;
} }
FifoOutput *fd = new FifoOutput(); fd->path_utf8 = fd->path.ToUTF8();
fd->path = path;
if (!fd->Initialize(param, error_r)) { if (!fd->Initialize(param, error_r)) {
delete fd; delete fd;
...@@ -259,7 +261,7 @@ fifo_output_cancel(struct audio_output *ao) ...@@ -259,7 +261,7 @@ fifo_output_cancel(struct audio_output *ao)
if (bytes < 0 && errno != EAGAIN) { if (bytes < 0 && errno != EAGAIN) {
g_warning("Flush of FIFO \"%s\" failed: %s", 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, ...@@ -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, g_set_error(error, fifo_output_quark(), errno,
"Failed to write to FIFO %s: %s", "Failed to write to FIFO %s: %s",
fd->path, g_strerror(errno)); fd->path_utf8.c_str(), g_strerror(errno));
return 0; return 0;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment