aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2013-01-17 00:56:57 +0100
committerMax Kellermann <max@duempel.org>2013-01-17 00:56:57 +0100
commit2cca3ed6ad118b58365ec2a87e71536f03055cf8 (patch)
treea511887a2b7a38a98969e04f6501dcbb711f1236
parent21fe376d1d9ffa6064cf89faab7860d443d9f7fd (diff)
downloadmpd-path.tar.gz
mpd-path.tar.xz
mpd-path.zip
Path: new class "Path" wraps filesystem path stringspath
-rw-r--r--src/DecoderThread.cxx3
-rw-r--r--src/Mapper.cxx82
-rw-r--r--src/Mapper.hxx19
-rw-r--r--src/Path.hxx125
-rw-r--r--src/PlaylistFile.cxx71
-rw-r--r--src/PlaylistMapper.cxx13
-rw-r--r--src/PlaylistSave.cxx47
-rw-r--r--src/PlaylistSong.cxx4
-rw-r--r--src/SongUpdate.cxx18
-rw-r--r--src/UpdateArchive.cxx10
-rw-r--r--src/UpdateContainer.cxx13
-rw-r--r--src/UpdateIO.cxx47
-rw-r--r--src/UpdateWalk.cxx29
13 files changed, 269 insertions, 212 deletions
diff --git a/src/DecoderThread.cxx b/src/DecoderThread.cxx
index 21653830b..9ca478fae 100644
--- a/src/DecoderThread.cxx
+++ b/src/DecoderThread.cxx
@@ -26,6 +26,7 @@
#include "song.h"
#include "mpd_error.h"
#include "Mapper.hxx"
+#include "Path.hxx"
#include "decoder_api.h"
#include "tag.h"
#include "input_stream.h"
@@ -431,7 +432,7 @@ decoder_run(struct decoder_control *dc)
assert(song != NULL);
if (song_is_file(song))
- uri = map_song_fs(song);
+ uri = map_song_fs(song).Steal();
else
uri = song_get_uri(song);
diff --git a/src/Mapper.cxx b/src/Mapper.cxx
index 1a5ebe111..09fa190f3 100644
--- a/src/Mapper.cxx
+++ b/src/Mapper.cxx
@@ -156,67 +156,54 @@ map_to_relative_path(const char *path_utf8)
: path_utf8;
}
-char *
+Path
map_uri_fs(const char *uri)
{
- char *uri_fs, *path_fs;
-
assert(uri != NULL);
assert(*uri != '/');
if (music_dir_fs == NULL)
- return NULL;
+ return Path::Null();
- uri_fs = utf8_to_fs_charset(uri);
- if (uri_fs == NULL)
- return NULL;
-
- path_fs = g_build_filename(music_dir_fs, uri_fs, NULL);
- g_free(uri_fs);
+ const Path uri_fs = Path::FromUTF8(uri);
+ if (uri_fs.IsNull())
+ return Path::Null();
- return path_fs;
+ return Path::Build(music_dir_fs, uri_fs);
}
-char *
+Path
map_directory_fs(const Directory *directory)
{
assert(music_dir_utf8 != NULL);
assert(music_dir_fs != NULL);
if (directory->IsRoot())
- return g_strdup(music_dir_fs);
+ return Path::FromFS(music_dir_fs);
return map_uri_fs(directory->GetPath());
}
-char *
+Path
map_directory_child_fs(const Directory *directory, const char *name)
{
assert(music_dir_utf8 != NULL);
assert(music_dir_fs != NULL);
- char *name_fs, *parent_fs, *path;
-
/* check for invalid or unauthorized base names */
if (*name == 0 || strchr(name, '/') != NULL ||
strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
- return NULL;
+ return Path::Null();
- parent_fs = map_directory_fs(directory);
- if (parent_fs == NULL)
- return NULL;
+ const Path parent_fs = map_directory_fs(directory);
+ if (parent_fs.IsNull())
+ return Path::Null();
- name_fs = utf8_to_fs_charset(name);
- if (name_fs == NULL) {
- g_free(parent_fs);
- return NULL;
- }
-
- path = g_build_filename(parent_fs, name_fs, NULL);
- g_free(parent_fs);
- g_free(name_fs);
+ const Path name_fs = Path::FromUTF8(name);
+ if (name_fs.IsNull())
+ return Path::Null();
- return path;
+ return Path::Build(parent_fs, name_fs);
}
/**
@@ -224,19 +211,17 @@ map_directory_child_fs(const Directory *directory, const char *name)
* not have a real parent directory, only the dummy object
* #detached_root.
*/
-static char *
+static Path
map_detached_song_fs(const char *uri_utf8)
{
- char *uri_fs = utf8_to_fs_charset(uri_utf8);
- if (uri_fs == NULL)
- return NULL;
+ Path uri_fs = Path::FromUTF8(uri_utf8);
+ if (uri_fs.IsNull())
+ return Path::Null();
- char *path = g_build_filename(music_dir_fs, uri_fs, NULL);
- g_free(uri_fs);
- return path;
+ return Path::Build(music_dir_fs, uri_fs);
}
-char *
+Path
map_song_fs(const struct song *song)
{
assert(song_is_file(song));
@@ -246,7 +231,7 @@ map_song_fs(const struct song *song)
? map_detached_song_fs(song->uri)
: map_directory_child_fs(song->parent, song->uri);
else
- return utf8_to_fs_charset(song->uri);
+ return Path::FromUTF8(song->uri);
}
char *
@@ -273,22 +258,17 @@ map_spl_path(void)
return playlist_dir_fs;
}
-char *
+Path
map_spl_utf8_to_fs(const char *name)
{
- char *filename_utf8, *filename_fs, *path;
-
if (playlist_dir_fs == NULL)
- return NULL;
+ return Path::Null();
- filename_utf8 = g_strconcat(name, PLAYLIST_FILE_SUFFIX, NULL);
- filename_fs = utf8_to_fs_charset(filename_utf8);
+ char *filename_utf8 = g_strconcat(name, PLAYLIST_FILE_SUFFIX, NULL);
+ const Path filename_fs = Path::FromUTF8(filename_utf8);
g_free(filename_utf8);
- if (filename_fs == NULL)
- return NULL;
-
- path = g_build_filename(playlist_dir_fs, filename_fs, NULL);
- g_free(filename_fs);
+ if (filename_fs.IsNull())
+ return Path::Null();
- return path;
+ return Path::Build(playlist_dir_fs, filename_fs);
}
diff --git a/src/Mapper.hxx b/src/Mapper.hxx
index 2ced38a10..01c947b5a 100644
--- a/src/Mapper.hxx
+++ b/src/Mapper.hxx
@@ -29,6 +29,7 @@
#define PLAYLIST_FILE_SUFFIX ".m3u"
+class Path;
struct Directory;
struct song;
@@ -75,8 +76,8 @@ map_to_relative_path(const char *path_utf8);
* is basically done by converting the URI to the file system charset
* and prepending the music directory.
*/
-gcc_malloc
-char *
+gcc_pure
+Path
map_uri_fs(const char *uri);
/**
@@ -85,8 +86,8 @@ map_uri_fs(const char *uri);
* @param directory the directory object
* @return the path in file system encoding, or nullptr if mapping failed
*/
-gcc_malloc
-char *
+gcc_pure
+Path
map_directory_fs(const Directory *directory);
/**
@@ -97,8 +98,8 @@ map_directory_fs(const Directory *directory);
* @param name the child's name in UTF-8
* @return the path in file system encoding, or nullptr if mapping failed
*/
-gcc_malloc
-char *
+gcc_pure
+Path
map_directory_child_fs(const Directory *directory, const char *name);
/**
@@ -108,8 +109,8 @@ map_directory_child_fs(const Directory *directory, const char *name);
* @param song the song object
* @return the path in file system encoding, or nullptr if mapping failed
*/
-gcc_malloc
-char *
+gcc_pure
+Path
map_song_fs(const struct song *song);
/**
@@ -138,7 +139,7 @@ map_spl_path(void);
* @return the path in file system encoding, or nullptr if mapping failed
*/
gcc_pure
-char *
+Path
map_spl_utf8_to_fs(const char *name);
#endif
diff --git a/src/Path.hxx b/src/Path.hxx
index db3f95961..ad40fa551 100644
--- a/src/Path.hxx
+++ b/src/Path.hxx
@@ -21,7 +21,14 @@
#define MPD_PATH_HXX
#include "check.h"
+#include "gcc.h"
+#include <glib.h>
+
+#include <algorithm>
+
+#include <assert.h>
+#include <string.h>
#include <limits.h>
#if !defined(MPD_PATH_MAX)
@@ -54,4 +61,122 @@ utf8_to_fs_charset(const char *path_utf8);
const char *path_get_fs_charset();
+/**
+ * A path name in the native file system character set.
+ */
+class Path {
+ char *value;
+
+ struct Donate {};
+
+ Path(Donate, char *_value):value(_value) {}
+
+public:
+ Path(Path &&other):value(other.value) {
+ other.value = nullptr;
+ }
+
+ Path(const Path &other) = delete;
+
+#if 0
+ /* this is the correct implementation, but unfortunately it
+ disables compiler optimizations */
+ Path(const Path &other)
+ :value(g_strdup(other.value)) {}
+#endif
+
+
+ ~Path() {
+ /* free() can be optimized by gcc, while g_free() can
+ not: when the compiler knows that the value is
+ nullptr, it will not emit a free() call in the
+ inlined destructor; however on Windows, we need to
+ call g_free(), because the value has been allocated
+ by GLib, and on Windows, this matters */
+#ifdef WIN32
+ g_free(value);
+#else
+ free(value);
+#endif
+ }
+
+ gcc_const
+ static Path Null() {
+ return Path(Donate(), nullptr);
+ }
+
+ gcc_pure
+ static Path Build(const char *a, const char *b) {
+ return Path(Donate(), g_build_filename(a, b, nullptr));
+ }
+
+ static Path Build(const char *a, const Path &b) {
+ return Build(a, b.c_str());
+ }
+
+ static Path Build(const Path &a, const Path &b) {
+ return Build(a.c_str(), b.c_str());
+ }
+
+ gcc_pure
+ static Path FromFS(const char *fs) {
+ return Path(Donate(), g_strdup(fs));
+ }
+
+ gcc_pure
+ static Path FromUTF8(const char *utf8) {
+ return Path(Donate(), utf8_to_fs_charset(utf8));
+ }
+
+ Path &operator=(const Path &other) {
+ value = g_strdup(other.value);
+ return *this;
+ }
+
+ Path &operator=(Path &&other) {
+ std::swap(value, other.value);
+ return *this;
+ }
+
+ char *Steal() {
+ char *result = value;
+ value = nullptr;
+ return result;
+ }
+
+ bool IsNull() const {
+ return value == nullptr;
+ }
+
+ void SetNull() {
+ g_free(value);
+ value = nullptr;
+ }
+
+ gcc_pure
+ size_t length() const {
+ assert(value != nullptr);
+
+ return strlen(value);
+ }
+
+ gcc_pure
+ const char *c_str() const {
+ assert(value != nullptr);
+
+ return value;
+ }
+
+ /**
+ * Convert the path to UTF-8. The caller is responsible for
+ * freeing the return value with g_free(). Returns nullptr on
+ * error.
+ */
+ char *ToUTF8() const {
+ return value != nullptr
+ ? fs_charset_to_utf8(value)
+ : nullptr;
+ }
+};
+
#endif
diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx
index 486c93994..e98f2a215 100644
--- a/src/PlaylistFile.cxx
+++ b/src/PlaylistFile.cxx
@@ -106,15 +106,15 @@ spl_check_name(const char *name_utf8, GError **error_r)
return true;
}
-static char *
+static Path
spl_map_to_fs(const char *name_utf8, GError **error_r)
{
if (spl_map(error_r) == NULL ||
!spl_check_name(name_utf8, error_r))
- return NULL;
+ return Path::Null();
- char *path_fs = map_spl_utf8_to_fs(name_utf8);
- if (path_fs == NULL)
+ Path path_fs = map_spl_utf8_to_fs(name_utf8);
+ if (path_fs.IsNull())
g_set_error_literal(error_r, playlist_quark(),
PLAYLIST_RESULT_BAD_NAME,
"Bad playlist name");
@@ -209,12 +209,11 @@ SavePlaylistFile(const PlaylistFileContents &contents, const char *utf8path,
if (spl_map(error_r) == NULL)
return false;
- char *path_fs = spl_map_to_fs(utf8path, error_r);
- if (path_fs == NULL)
+ const Path path_fs = spl_map_to_fs(utf8path, error_r);
+ if (path_fs.IsNull())
return false;
- FILE *file = fopen(path_fs, "w");
- g_free(path_fs);
+ FILE *file = fopen(path_fs.c_str(), "w");
if (file == NULL) {
playlist_errno(error_r);
return false;
@@ -235,11 +234,11 @@ LoadPlaylistFile(const char *utf8path, GError **error_r)
if (spl_map(error_r) == NULL)
return contents;
- char *path_fs = spl_map_to_fs(utf8path, error_r);
- if (path_fs == NULL)
+ const Path path_fs = spl_map_to_fs(utf8path, error_r);
+ if (path_fs.IsNull())
return contents;
- TextFile file(path_fs);
+ TextFile file(path_fs.c_str());
if (file.HasFailed()) {
playlist_errno(error_r);
return contents;
@@ -308,17 +307,14 @@ spl_move_index(const char *utf8path, unsigned src, unsigned dest,
bool
spl_clear(const char *utf8path, GError **error_r)
{
- FILE *file;
-
if (spl_map(error_r) == NULL)
return false;
- char *path_fs = spl_map_to_fs(utf8path, error_r);
- if (path_fs == NULL)
+ const Path path_fs = spl_map_to_fs(utf8path, error_r);
+ if (path_fs.IsNull())
return false;
- file = fopen(path_fs, "w");
- g_free(path_fs);
+ FILE *file = fopen(path_fs.c_str(), "w");
if (file == NULL) {
playlist_errno(error_r);
return false;
@@ -333,12 +329,11 @@ spl_clear(const char *utf8path, GError **error_r)
bool
spl_delete(const char *name_utf8, GError **error_r)
{
- char *path_fs = spl_map_to_fs(name_utf8, error_r);
- if (path_fs == NULL)
+ const Path path_fs = spl_map_to_fs(name_utf8, error_r);
+ if (path_fs.IsNull())
return false;
- int ret = unlink(path_fs);
- g_free(path_fs);
+ int ret = unlink(path_fs.c_str());
if (ret < 0) {
playlist_errno(error_r);
return false;
@@ -376,17 +371,14 @@ spl_remove_index(const char *utf8path, unsigned pos, GError **error_r)
bool
spl_append_song(const char *utf8path, struct song *song, GError **error_r)
{
- FILE *file;
-
if (spl_map(error_r) == NULL)
return false;
- char *path_fs = spl_map_to_fs(utf8path, error_r);
- if (path_fs == NULL)
+ const Path path_fs = spl_map_to_fs(utf8path, error_r);
+ if (path_fs.IsNull())
return false;
- file = fopen(path_fs, "a");
- g_free(path_fs);
+ FILE *file = fopen(path_fs.c_str(), "a");
if (file == NULL) {
playlist_errno(error_r);
return false;
@@ -439,24 +431,24 @@ spl_append_uri(const char *url, const char *utf8file, GError **error_r)
}
static bool
-spl_rename_internal(const char *from_path_fs, const char *to_path_fs,
+spl_rename_internal(const Path &from_path_fs, const Path &to_path_fs,
GError **error_r)
{
- if (!g_file_test(from_path_fs, G_FILE_TEST_IS_REGULAR)) {
+ if (!g_file_test(from_path_fs.c_str(), G_FILE_TEST_IS_REGULAR)) {
g_set_error_literal(error_r, playlist_quark(),
PLAYLIST_RESULT_NO_SUCH_LIST,
"No such playlist");
return false;
}
- if (g_file_test(to_path_fs, G_FILE_TEST_EXISTS)) {
+ if (g_file_test(to_path_fs.c_str(), G_FILE_TEST_EXISTS)) {
g_set_error_literal(error_r, playlist_quark(),
PLAYLIST_RESULT_LIST_EXISTS,
"Playlist exists already");
return false;
}
- if (rename(from_path_fs, to_path_fs) < 0) {
+ if (rename(from_path_fs.c_str(), to_path_fs.c_str()) < 0) {
playlist_errno(error_r);
return false;
}
@@ -471,20 +463,13 @@ spl_rename(const char *utf8from, const char *utf8to, GError **error_r)
if (spl_map(error_r) == NULL)
return false;
- char *from_path_fs = spl_map_to_fs(utf8from, error_r);
- if (from_path_fs == NULL)
+ Path from_path_fs = spl_map_to_fs(utf8from, error_r);
+ if (from_path_fs.IsNull())
return false;
- char *to_path_fs = spl_map_to_fs(utf8to, error_r);
- if (to_path_fs == NULL) {
- g_free(from_path_fs);
+ Path to_path_fs = spl_map_to_fs(utf8to, error_r);
+ if (to_path_fs.IsNull())
return false;
- }
-
- bool success = spl_rename_internal(from_path_fs, to_path_fs, error_r);
-
- g_free(from_path_fs);
- g_free(to_path_fs);
- return success;
+ return spl_rename_internal(from_path_fs, to_path_fs, error_r);
}
diff --git a/src/PlaylistMapper.cxx b/src/PlaylistMapper.cxx
index 01b8f7dd8..e6b8ee439 100644
--- a/src/PlaylistMapper.cxx
+++ b/src/PlaylistMapper.cxx
@@ -21,6 +21,7 @@
#include "PlaylistMapper.hxx"
#include "PlaylistFile.hxx"
#include "Mapper.hxx"
+#include "Path.hxx"
extern "C" {
#include "playlist_list.h"
@@ -75,19 +76,13 @@ static struct playlist_provider *
playlist_open_in_music_dir(const char *uri, GMutex *mutex, GCond *cond,
struct input_stream **is_r)
{
- char *path_fs;
-
assert(uri_safe_local(uri));
- path_fs = map_uri_fs(uri);
- if (path_fs == NULL)
+ Path path = map_uri_fs(uri);
+ if (path.IsNull())
return NULL;
- struct playlist_provider *playlist =
- playlist_open_path(path_fs, mutex, cond, is_r);
- g_free(path_fs);
-
- return playlist;
+ return playlist_open_path(path.c_str(), mutex, cond, is_r);
}
struct playlist_provider *
diff --git a/src/PlaylistSave.cxx b/src/PlaylistSave.cxx
index 5f47d73c0..89feebbde 100644
--- a/src/PlaylistSave.cxx
+++ b/src/PlaylistSave.cxx
@@ -38,62 +38,47 @@ void
playlist_print_song(FILE *file, const struct song *song)
{
if (playlist_saveAbsolutePaths && song_in_database(song)) {
- char *path = map_song_fs(song);
- if (path != NULL) {
- fprintf(file, "%s\n", path);
- g_free(path);
- }
+ const Path path = map_song_fs(song);
+ if (!path.IsNull())
+ fprintf(file, "%s\n", path.c_str());
} else {
- char *uri = song_get_uri(song), *uri_fs;
-
- uri_fs = utf8_to_fs_charset(uri);
+ char *uri = song_get_uri(song);
+ const Path uri_fs = Path::FromUTF8(uri);
g_free(uri);
- fprintf(file, "%s\n", uri_fs);
- g_free(uri_fs);
+ fprintf(file, "%s\n", uri_fs.c_str());
}
}
void
playlist_print_uri(FILE *file, const char *uri)
{
- char *s;
-
- if (playlist_saveAbsolutePaths && !uri_has_scheme(uri) &&
- !g_path_is_absolute(uri))
- s = map_uri_fs(uri);
- else
- s = utf8_to_fs_charset(uri);
+ Path path = playlist_saveAbsolutePaths && !uri_has_scheme(uri) &&
+ !g_path_is_absolute(uri)
+ ? map_uri_fs(uri)
+ : Path::FromUTF8(uri);
- if (s != NULL) {
- fprintf(file, "%s\n", s);
- g_free(s);
- }
+ if (!path.IsNull())
+ fprintf(file, "%s\n", path.c_str());
}
enum playlist_result
spl_save_queue(const char *name_utf8, const struct queue *queue)
{
- char *path_fs;
- FILE *file;
-
if (map_spl_path() == NULL)
return PLAYLIST_RESULT_DISABLED;
if (!spl_valid_name(name_utf8))
return PLAYLIST_RESULT_BAD_NAME;
- path_fs = map_spl_utf8_to_fs(name_utf8);
- if (path_fs == NULL)
+ const Path path_fs = map_spl_utf8_to_fs(name_utf8);
+ if (path_fs.IsNull())
return PLAYLIST_RESULT_BAD_NAME;
- if (g_file_test(path_fs, G_FILE_TEST_EXISTS)) {
- g_free(path_fs);
+ if (g_file_test(path_fs.c_str(), G_FILE_TEST_EXISTS))
return PLAYLIST_RESULT_LIST_EXISTS;
- }
- file = fopen(path_fs, "w");
- g_free(path_fs);
+ FILE *file = fopen(path_fs.c_str(), "w");
if (file == NULL)
return PLAYLIST_RESULT_ERRNO;
diff --git a/src/PlaylistSong.cxx b/src/PlaylistSong.cxx
index ec27656f2..0d60c1413 100644
--- a/src/PlaylistSong.cxx
+++ b/src/PlaylistSong.cxx
@@ -65,8 +65,8 @@ apply_song_metadata(struct song *dest, const struct song *src)
return dest;
if (song_in_database(dest)) {
- char *path_fs = map_song_fs(dest);
- if (path_fs == NULL)
+ char *path_fs = map_song_fs(dest).Steal();
+ if (path_fs == nullptr)
return dest;
char *path_utf8 = fs_charset_to_utf8(path_fs);
diff --git a/src/SongUpdate.cxx b/src/SongUpdate.cxx
index b96c7c43e..6353737e7 100644
--- a/src/SongUpdate.cxx
+++ b/src/SongUpdate.cxx
@@ -26,6 +26,7 @@ extern "C" {
#include "Directory.hxx"
#include "Mapper.hxx"
+#include "Path.hxx"
#include "tag.h"
#include "input_stream.h"
@@ -85,7 +86,6 @@ bool
song_file_update(struct song *song)
{
const char *suffix;
- char *path_fs;
const struct decoder_plugin *plugin;
struct stat st;
struct input_stream *is = NULL;
@@ -102,8 +102,8 @@ song_file_update(struct song *song)
if (plugin == NULL)
return false;
- path_fs = map_song_fs(song);
- if (path_fs == NULL)
+ const Path path_fs = map_song_fs(song);
+ if (path_fs.IsNull())
return false;
if (song->tag != NULL) {
@@ -111,8 +111,7 @@ song_file_update(struct song *song)
song->tag = NULL;
}
- if (stat(path_fs, &st) < 0 || !S_ISREG(st.st_mode)) {
- g_free(path_fs);
+ if (stat(path_fs.c_str(), &st) < 0 || !S_ISREG(st.st_mode)) {
return false;
}
@@ -129,7 +128,7 @@ song_file_update(struct song *song)
do {
/* load file tag */
song->tag = tag_new();
- if (decoder_plugin_scan_file(plugin, path_fs,
+ if (decoder_plugin_scan_file(plugin, path_fs.c_str(),
&full_tag_handler, song->tag))
break;
@@ -143,7 +142,8 @@ song_file_update(struct song *song)
if (is == NULL) {
mutex = g_mutex_new();
cond = g_cond_new();
- is = input_stream_open(path_fs, mutex, cond,
+ is = input_stream_open(path_fs.c_str(),
+ mutex, cond,
NULL);
}
@@ -174,9 +174,9 @@ song_file_update(struct song *song)
}
if (song->tag != NULL && tag_is_empty(song->tag))
- tag_scan_fallback(path_fs, &full_tag_handler, song->tag);
+ tag_scan_fallback(path_fs.c_str(), &full_tag_handler,
+ song->tag);
- g_free(path_fs);
return song->tag != NULL;
}
diff --git a/src/UpdateArchive.cxx b/src/UpdateArchive.cxx
index 72f7aaf19..c45e1b733 100644
--- a/src/UpdateArchive.cxx
+++ b/src/UpdateArchive.cxx
@@ -24,6 +24,7 @@
#include "Directory.hxx"
#include "song.h"
#include "Mapper.hxx"
+#include "Path.hxx"
extern "C" {
#include "archive_list.h"
@@ -96,20 +97,19 @@ update_archive_file2(Directory *parent, const char *name,
changed since - don't consider updating it */
return;
- char *path_fs = map_directory_child_fs(parent, name);
+ const Path path_fs = map_directory_child_fs(parent, name);
/* open archive */
GError *error = NULL;
- struct archive_file *file = archive_file_open(plugin, path_fs, &error);
+ struct archive_file *file = archive_file_open(plugin, path_fs.c_str(),
+ &error);
if (file == NULL) {
- g_free(path_fs);
g_warning("%s", error->message);
g_error_free(error);
return;
}
- g_debug("archive %s opened", path_fs);
- g_free(path_fs);
+ g_debug("archive %s opened", path_fs.c_str());
if (directory == NULL) {
g_debug("creating archive directory: %s", name);
diff --git a/src/UpdateContainer.cxx b/src/UpdateContainer.cxx
index daa7f1ec4..d59fa96c0 100644
--- a/src/UpdateContainer.cxx
+++ b/src/UpdateContainer.cxx
@@ -26,6 +26,7 @@
#include "song.h"
#include "decoder_plugin.h"
#include "Mapper.hxx"
+#include "Path.hxx"
extern "C" {
#include "tag_handler.h"
@@ -84,22 +85,22 @@ update_container_file(Directory *directory,
contdir->device = DEVICE_CONTAINER;
db_unlock();
- char *const pathname = map_directory_child_fs(directory, name);
+ const Path pathname = map_directory_child_fs(directory, name);
char *vtrack;
unsigned int tnum = 0;
- while ((vtrack = plugin->container_scan(pathname, ++tnum)) != NULL) {
+ while ((vtrack = plugin->container_scan(pathname.c_str(), ++tnum)) != NULL) {
struct song *song = song_file_new(vtrack, contdir);
// shouldn't be necessary but it's there..
song->mtime = st->st_mtime;
- char *child_path_fs = map_directory_child_fs(contdir, vtrack);
+ const Path child_path_fs =
+ map_directory_child_fs(contdir, vtrack);
song->tag = tag_new();
- decoder_plugin_scan_file(plugin, child_path_fs,
+ decoder_plugin_scan_file(plugin, child_path_fs.c_str(),
&add_tag_handler, song->tag);
- g_free(child_path_fs);
db_lock();
contdir->AddSong(song);
@@ -111,8 +112,6 @@ update_container_file(Directory *directory,
g_free(vtrack);
}
- g_free(pathname);
-
if (tnum == 1) {
db_lock();
delete_directory(contdir);
diff --git a/src/UpdateIO.cxx b/src/UpdateIO.cxx
index 2aee56514..cbf05b6fc 100644
--- a/src/UpdateIO.cxx
+++ b/src/UpdateIO.cxx
@@ -21,6 +21,7 @@
#include "UpdateIO.hxx"
#include "Directory.hxx"
#include "Mapper.hxx"
+#include "Path.hxx"
#include "glib_compat.h"
#include <glib.h>
@@ -31,15 +32,15 @@
int
stat_directory(const Directory *directory, struct stat *st)
{
- char *path_fs = map_directory_fs(directory);
- if (path_fs == NULL)
+ const Path path_fs = map_directory_fs(directory);
+ if (path_fs.IsNull())
return -1;
- int ret = stat(path_fs, st);
+ int ret = stat(path_fs.c_str(), st);
if (ret < 0)
- g_warning("Failed to stat %s: %s", path_fs, g_strerror(errno));
+ g_warning("Failed to stat %s: %s",
+ path_fs.c_str(), g_strerror(errno));
- g_free(path_fs);
return ret;
}
@@ -47,23 +48,23 @@ int
stat_directory_child(const Directory *parent, const char *name,
struct stat *st)
{
- char *path_fs = map_directory_child_fs(parent, name);
- if (path_fs == NULL)
+ const Path path_fs = map_directory_child_fs(parent, name);
+ if (path_fs.IsNull())
return -1;
- int ret = stat(path_fs, st);
+ int ret = stat(path_fs.c_str(), st);
if (ret < 0)
- g_warning("Failed to stat %s: %s", path_fs, g_strerror(errno));
+ g_warning("Failed to stat %s: %s",
+ path_fs.c_str(), g_strerror(errno));
- g_free(path_fs);
return ret;
}
bool
directory_exists(const Directory *directory)
{
- char *path_fs = map_directory_fs(directory);
- if (path_fs == NULL)
+ const Path path_fs = map_directory_fs(directory);
+ if (path_fs.IsNull())
/* invalid path: cannot exist */
return false;
@@ -72,25 +73,19 @@ directory_exists(const Directory *directory)
? G_FILE_TEST_IS_REGULAR
: G_FILE_TEST_IS_DIR;
- bool exists = g_file_test(path_fs, test);
- g_free(path_fs);
-
- return exists;
+ return g_file_test(path_fs.c_str(), test);
}
bool
directory_child_is_regular(const Directory *directory,
const char *name_utf8)
{
- char *path_fs = map_directory_child_fs(directory, name_utf8);
- if (path_fs == NULL)
+ const Path path_fs = map_directory_child_fs(directory, name_utf8);
+ if (path_fs.IsNull())
return false;
struct stat st;
- bool is_regular = stat(path_fs, &st) == 0 && S_ISREG(st.st_mode);
- g_free(path_fs);
-
- return is_regular;
+ return stat(path_fs.c_str(), &st) == 0 && S_ISREG(st.st_mode);
}
bool
@@ -104,14 +99,12 @@ directory_child_access(const Directory *directory,
(void)mode;
return true;
#else
- char *path = map_directory_child_fs(directory, name);
- if (path == NULL)
+ const Path path = map_directory_child_fs(directory, name);
+ if (path.IsNull())
/* something went wrong, but that isn't a permission
problem */
return true;
- bool success = access(path, mode) == 0 || errno != EACCES;
- g_free(path);
- return success;
+ return access(path.c_str(), mode) == 0 || errno != EACCES;
#endif
}
diff --git a/src/UpdateWalk.cxx b/src/UpdateWalk.cxx
index 1716862b5..a0f331bfe 100644
--- a/src/UpdateWalk.cxx
+++ b/src/UpdateWalk.cxx
@@ -102,27 +102,23 @@ remove_excluded_from_directory(Directory *directory,
Directory *child, *n;
directory_for_each_child_safe(child, n, directory) {
- char *name_fs = utf8_to_fs_charset(child->GetName());
+ const Path name_fs = Path::FromUTF8(child->GetName());
- if (exclude_list.Check(name_fs)) {
+ if (exclude_list.Check(name_fs.c_str())) {
delete_directory(child);
modified = true;
}
-
- g_free(name_fs);
}
struct song *song, *ns;
directory_for_each_song_safe(song, ns, directory) {
assert(song->parent == directory);
- char *name_fs = utf8_to_fs_charset(song->uri);
- if (exclude_list.Check(name_fs)) {
+ const Path name_fs = Path::FromUTF8(song->uri);
+ if (exclude_list.Check(name_fs.c_str())) {
delete_song(directory, song);
modified = true;
}
-
- g_free(name_fs);
}
db_unlock();
@@ -145,18 +141,16 @@ purge_deleted_from_directory(Directory *directory)
struct song *song, *ns;
directory_for_each_song_safe(song, ns, directory) {
- char *path;
struct stat st;
- if ((path = map_song_fs(song)) == NULL ||
- stat(path, &st) < 0 || !S_ISREG(st.st_mode)) {
+ const Path path = map_song_fs(song);
+ if (path.IsNull() ||
+ stat(path.c_str(), &st) < 0 || !S_ISREG(st.st_mode)) {
db_lock();
delete_song(directory, song);
db_unlock();
modified = true;
}
-
- g_free(path);
}
for (auto i = directory->playlists.begin(),
@@ -283,13 +277,12 @@ static bool
skip_symlink(const Directory *directory, const char *utf8_name)
{
#ifndef WIN32
- char *path_fs = map_directory_child_fs(directory, utf8_name);
- if (path_fs == NULL)
+ const Path path_fs = map_directory_child_fs(directory, utf8_name);
+ if (path_fs.IsNull())
return true;
char buffer[MPD_PATH_MAX];
- ssize_t length = readlink(path_fs, buffer, sizeof(buffer));
- g_free(path_fs);
+ ssize_t length = readlink(path_fs.c_str(), buffer, sizeof(buffer));
if (length < 0)
/* don't skip if this is not a symlink */
return errno != EINVAL;
@@ -359,7 +352,7 @@ update_directory(Directory *directory, const struct stat *st)
directory_set_stat(directory, st);
- char *path_fs = map_directory_fs(directory);
+ char *path_fs = map_directory_fs(directory).Steal();
if (path_fs == NULL)
return false;