ConfigPath: return a Path object
Migrate all callers to use Path directly, instead of doing the conversion in each caller.
This commit is contained in:
parent
abe090ec1f
commit
b76a29a69a
@ -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
|
|||||||
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 @@
|
|||||||
#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 {
|
|||||||
* 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 @@
|
|||||||
#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)
|
|||||||
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);
|
|||||||
/**
|
/**
|
||||||
* 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 @@
|
|||||||
|
|
||||||
#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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
|
|
||||||
#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 @@
|
|||||||
#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;
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@
|
|||||||
#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
|
||||||
|
|
||||||
|
34
src/Log.cxx
34
src/Log.cxx
@ -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;
|
|||||||
|
|
||||||
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
src/Main.cxx
46
src/Main.cxx
@ -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
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
#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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|
||||||
"Failed to convert playlist path to FS encoding");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
check_directory(path_utf8, playlist_dir_fs);
|
playlist_dir_fs = path;
|
||||||
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,
|
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 (!_playlist_dir.IsNull())
|
||||||
if (!mapper_set_playlist_dir(_playlist_dir, error_r))
|
mapper_set_playlist_dir(std::move(_playlist_dir));
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mapper_finish(void)
|
void mapper_finish(void)
|
||||||
|
@ -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 @@
|
|||||||
#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 {
|
|||||||
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 @@
|
|||||||
|
|
||||||
#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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 @@
|
|||||||
|
|
||||||
#include "gerror.h"
|
#include "gerror.h"
|
||||||
|
|
||||||
|
class Path;
|
||||||
struct sticker;
|
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 ¶m, 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 ¶m, 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)
|
|||||||
*/
|
*/
|
||||||
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 @@
|
|||||||
#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 @@
|
|||||||
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 ¶m, GError **error_r) {
|
bool Initialize(const config_param ¶m, 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)
|
|||||||
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()
|
|||||||
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()
|
|||||||
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
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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 *
|
|||||||
fifo_output_init(const config_param ¶m, GError **error_r)
|
fifo_output_init(const config_param ¶m, 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 ¶m, 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)
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user