From 2cca3ed6ad118b58365ec2a87e71536f03055cf8 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 17 Jan 2013 00:56:57 +0100 Subject: Path: new class "Path" wraps filesystem path strings --- src/DecoderThread.cxx | 3 +- src/Mapper.cxx | 82 ++++++++++++------------------- src/Mapper.hxx | 19 ++++---- src/Path.hxx | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ src/PlaylistFile.cxx | 71 +++++++++++---------------- src/PlaylistMapper.cxx | 13 ++--- src/PlaylistSave.cxx | 47 +++++++----------- src/PlaylistSong.cxx | 4 +- src/SongUpdate.cxx | 18 +++---- src/UpdateArchive.cxx | 10 ++-- src/UpdateContainer.cxx | 13 +++-- src/UpdateIO.cxx | 47 ++++++++---------- src/UpdateWalk.cxx | 29 +++++------ 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 + +#include + +#include +#include #include #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 @@ -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; -- cgit v1.2.3