From ca419c84b83d017c3e4309e22f92273500197eea Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 11 Sep 2011 07:41:25 +0200 Subject: stored_playlist: return GError, code is playlist_result Improve error reporting and handling. command.c gets the new function print_error(), which sends a GError to the client. --- src/stored_playlist.c | 304 +++++++++++++++++++++++++++++++------------------- 1 file changed, 190 insertions(+), 114 deletions(-) (limited to 'src/stored_playlist.c') diff --git a/src/stored_playlist.c b/src/stored_playlist.c index c3785a6f3..39ba2bac1 100644 --- a/src/stored_playlist.c +++ b/src/stored_playlist.c @@ -28,6 +28,7 @@ #include "database.h" #include "idle.h" #include "conf.h" +#include "glib_compat.h" #include #include @@ -72,6 +73,67 @@ spl_valid_name(const char *name_utf8) strchr(name_utf8, '\r') == NULL; } +static const char * +spl_map(GError **error_r) +{ + const char *path_fs = map_spl_path(); + if (path_fs == NULL) + g_set_error_literal(error_r, playlist_quark(), + PLAYLIST_RESULT_DISABLED, + "Stored playlists are disabled"); + + return path_fs; +} + +static bool +spl_check_name(const char *name_utf8, GError **error_r) +{ + if (!spl_valid_name(name_utf8)) { + g_set_error_literal(error_r, playlist_quark(), + PLAYLIST_RESULT_BAD_NAME, + "Bad playlist name"); + return false; + } + + return true; +} + +static char * +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; + + char *path_fs = map_spl_utf8_to_fs(name_utf8); + if (path_fs == NULL) + g_set_error_literal(error_r, playlist_quark(), + PLAYLIST_RESULT_BAD_NAME, + "Bad playlist name"); + + return path_fs; +} + +/** + * Create a GError for the current errno. + */ +static void +playlist_errno(GError **error_r) +{ + switch (errno) { + case ENOENT: + g_set_error_literal(error_r, playlist_quark(), + PLAYLIST_RESULT_NO_SUCH_LIST, + "No such playlist"); + break; + + default: + g_set_error_literal(error_r, g_file_error_quark(), errno, + g_strerror(errno)); + break; + } +} + static struct stored_playlist_info * load_playlist_info(const char *parent_path_fs, const char *name_fs) { @@ -108,9 +170,9 @@ load_playlist_info(const char *parent_path_fs, const char *name_fs) } GPtrArray * -spl_list(void) +spl_list(GError **error_r) { - const char *parent_path_fs = map_spl_path(); + const char *parent_path_fs = spl_map(error_r); DIR *dir; struct dirent *ent; GPtrArray *list; @@ -120,8 +182,11 @@ spl_list(void) return NULL; dir = opendir(parent_path_fs); - if (dir == NULL) + if (dir == NULL) { + g_set_error_literal(error_r, g_file_error_quark(), errno, + g_strerror(errno)); return NULL; + } list = g_ptr_array_new(); @@ -148,25 +213,26 @@ spl_list_free(GPtrArray *list) g_ptr_array_free(list, true); } -static enum playlist_result -spl_save(GPtrArray *list, const char *utf8path) +static bool +spl_save(GPtrArray *list, const char *utf8path, GError **error_r) { FILE *file; - char *path_fs; assert(utf8path != NULL); - if (map_spl_path() == NULL) - return PLAYLIST_RESULT_DISABLED; + if (spl_map(error_r) == NULL) + return false; - path_fs = map_spl_utf8_to_fs(utf8path); + char *path_fs = spl_map_to_fs(utf8path, error_r); if (path_fs == NULL) - return PLAYLIST_RESULT_BAD_NAME; + return false; file = fopen(path_fs, "w"); g_free(path_fs); - if (file == NULL) - return PLAYLIST_RESULT_ERRNO; + if (file == NULL) { + playlist_errno(error_r); + return false; + } for (unsigned i = 0; i < list->len; ++i) { const char *uri = g_ptr_array_index(list, i); @@ -174,27 +240,29 @@ spl_save(GPtrArray *list, const char *utf8path) } fclose(file); - return PLAYLIST_RESULT_SUCCESS; + return true; } GPtrArray * -spl_load(const char *utf8path) +spl_load(const char *utf8path, GError **error_r) { FILE *file; GPtrArray *list; char *path_fs; - if (!spl_valid_name(utf8path) || map_spl_path() == NULL) + if (spl_map(error_r) == NULL) return NULL; - path_fs = map_spl_utf8_to_fs(utf8path); + path_fs = spl_map_to_fs(utf8path, error_r); if (path_fs == NULL) return NULL; file = fopen(path_fs, "r"); g_free(path_fs); - if (file == NULL) + if (file == NULL) { + playlist_errno(error_r); return NULL; + } list = g_ptr_array_new(); @@ -260,30 +328,33 @@ spl_insert_index_internal(GPtrArray *list, unsigned idx, char *uri) g_ptr_array_index(list, idx) = uri; } -enum playlist_result -spl_move_index(const char *utf8path, unsigned src, unsigned dest) +bool +spl_move_index(const char *utf8path, unsigned src, unsigned dest, + GError **error_r) { - GPtrArray *list; char *uri; - enum playlist_result result; if (src == dest) /* this doesn't check whether the playlist exists, but what the hell.. */ - return PLAYLIST_RESULT_SUCCESS; + return true; - if (!(list = spl_load(utf8path))) - return PLAYLIST_RESULT_NO_SUCH_LIST; + GPtrArray *list = spl_load(utf8path, error_r); + if (list == NULL) + return false; if (src >= list->len || dest >= list->len) { spl_free(list); - return PLAYLIST_RESULT_BAD_RANGE; + g_set_error_literal(error_r, playlist_quark(), + PLAYLIST_RESULT_BAD_RANGE, + "Bad range"); + return false; } uri = spl_remove_index_internal(list, src); spl_insert_index_internal(list, dest, uri); - result = spl_save(list, utf8path); + bool result = spl_save(list, utf8path, error_r); spl_free(list); @@ -291,78 +362,72 @@ spl_move_index(const char *utf8path, unsigned src, unsigned dest) return result; } -enum playlist_result -spl_clear(const char *utf8path) +bool +spl_clear(const char *utf8path, GError **error_r) { - char *path_fs; FILE *file; - if (map_spl_path() == NULL) - return PLAYLIST_RESULT_DISABLED; - - if (!spl_valid_name(utf8path)) - return PLAYLIST_RESULT_BAD_NAME; + if (spl_map(error_r) == NULL) + return false; - path_fs = map_spl_utf8_to_fs(utf8path); + char *path_fs = spl_map_to_fs(utf8path, error_r); if (path_fs == NULL) - return PLAYLIST_RESULT_BAD_NAME; + return false; file = fopen(path_fs, "w"); g_free(path_fs); - if (file == NULL) - return PLAYLIST_RESULT_ERRNO; + if (file == NULL) { + playlist_errno(error_r); + return false; + } fclose(file); idle_add(IDLE_STORED_PLAYLIST); - return PLAYLIST_RESULT_SUCCESS; + return true; } -enum playlist_result -spl_delete(const char *name_utf8) +bool +spl_delete(const char *name_utf8, GError **error_r) { char *path_fs; int ret; - 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); + path_fs = spl_map_to_fs(name_utf8, error_r); if (path_fs == NULL) - return PLAYLIST_RESULT_BAD_NAME; + return false; ret = unlink(path_fs); g_free(path_fs); - if (ret < 0) - return errno == ENOENT - ? PLAYLIST_RESULT_NO_SUCH_LIST - : PLAYLIST_RESULT_ERRNO; + if (ret < 0) { + playlist_errno(error_r); + return false; + } idle_add(IDLE_STORED_PLAYLIST); - return PLAYLIST_RESULT_SUCCESS; + return true; } -enum playlist_result -spl_remove_index(const char *utf8path, unsigned pos) +bool +spl_remove_index(const char *utf8path, unsigned pos, GError **error_r) { - GPtrArray *list; char *uri; - enum playlist_result result; - if (!(list = spl_load(utf8path))) - return PLAYLIST_RESULT_NO_SUCH_LIST; + GPtrArray *list = spl_load(utf8path, error_r); + if (list == NULL) + return false; if (pos >= list->len) { spl_free(list); - return PLAYLIST_RESULT_BAD_RANGE; + g_set_error_literal(error_r, playlist_quark(), + PLAYLIST_RESULT_BAD_RANGE, + "Bad range"); + return false; } uri = spl_remove_index_internal(list, pos); g_free(uri); - result = spl_save(list, utf8path); + bool result = spl_save(list, utf8path, error_r); spl_free(list); @@ -370,38 +435,38 @@ spl_remove_index(const char *utf8path, unsigned pos) return result; } -enum playlist_result -spl_append_song(const char *utf8path, struct song *song) +bool +spl_append_song(const char *utf8path, struct song *song, GError **error_r) { FILE *file; struct stat st; - char *path_fs; - if (map_spl_path() == NULL) - return PLAYLIST_RESULT_DISABLED; + if (spl_map(error_r) == NULL) + return false; - if (!spl_valid_name(utf8path)) - return PLAYLIST_RESULT_BAD_NAME; - - path_fs = map_spl_utf8_to_fs(utf8path); + char *path_fs = spl_map_to_fs(utf8path, error_r); if (path_fs == NULL) - return PLAYLIST_RESULT_BAD_NAME; + return false; file = fopen(path_fs, "a"); g_free(path_fs); - if (file == NULL) - return PLAYLIST_RESULT_ERRNO; + if (file == NULL) { + playlist_errno(error_r); + return false; + } if (fstat(fileno(file), &st) < 0) { - int save_errno = errno; + playlist_errno(error_r); fclose(file); - errno = save_errno; - return PLAYLIST_RESULT_ERRNO; + return false; } if (st.st_size / (MPD_PATH_MAX + 1) >= (off_t)playlist_max_length) { fclose(file); - return PLAYLIST_RESULT_TOO_LARGE; + g_set_error_literal(error_r, playlist_quark(), + PLAYLIST_RESULT_TOO_LARGE, + "Stored playlist is too large"); + return false; } playlist_print_song(file, song); @@ -409,68 +474,79 @@ spl_append_song(const char *utf8path, struct song *song) fclose(file); idle_add(IDLE_STORED_PLAYLIST); - return PLAYLIST_RESULT_SUCCESS; + return true; } -enum playlist_result -spl_append_uri(const char *url, const char *utf8file) +bool +spl_append_uri(const char *url, const char *utf8file, GError **error_r) { struct song *song; if (uri_has_scheme(url)) { - enum playlist_result ret; - song = song_remote_new(url); - ret = spl_append_song(utf8file, song); + bool success = spl_append_song(utf8file, song, error_r); song_free(song); - return ret; + return success; } else { song = db_get_song(url); - if (song == NULL) - return PLAYLIST_RESULT_NO_SUCH_SONG; - - return spl_append_song(utf8file, song); + if (song == NULL) { + g_set_error_literal(error_r, playlist_quark(), + PLAYLIST_RESULT_NO_SUCH_SONG, + "No such song"); + return false; + } + + return spl_append_song(utf8file, song, error_r); } } -static enum playlist_result -spl_rename_internal(const char *from_path_fs, const char *to_path_fs) +static bool +spl_rename_internal(const char *from_path_fs, const char *to_path_fs, + GError **error_r) { - if (!g_file_test(from_path_fs, G_FILE_TEST_IS_REGULAR)) - return PLAYLIST_RESULT_NO_SUCH_LIST; + if (!g_file_test(from_path_fs, 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)) - return PLAYLIST_RESULT_LIST_EXISTS; + if (g_file_test(to_path_fs, 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) - return PLAYLIST_RESULT_ERRNO; + if (rename(from_path_fs, to_path_fs) < 0) { + playlist_errno(error_r); + return false; + } idle_add(IDLE_STORED_PLAYLIST); - return PLAYLIST_RESULT_SUCCESS; + return true; } -enum playlist_result -spl_rename(const char *utf8from, const char *utf8to) +bool +spl_rename(const char *utf8from, const char *utf8to, GError **error_r) { - char *from_path_fs, *to_path_fs; - static enum playlist_result ret; - - if (map_spl_path() == NULL) - return PLAYLIST_RESULT_DISABLED; + if (spl_map(error_r) == NULL) + return false; - if (!spl_valid_name(utf8from) || !spl_valid_name(utf8to)) - return PLAYLIST_RESULT_BAD_NAME; + char *from_path_fs = spl_map_to_fs(utf8from, error_r); + if (from_path_fs == NULL) + return false; - from_path_fs = map_spl_utf8_to_fs(utf8from); - to_path_fs = map_spl_utf8_to_fs(utf8to); + char *to_path_fs = spl_map_to_fs(utf8to, error_r); + if (to_path_fs == NULL) { + g_free(from_path_fs); + return false; + } - if (from_path_fs != NULL && to_path_fs != NULL) - ret = spl_rename_internal(from_path_fs, to_path_fs); - else - ret = PLAYLIST_RESULT_BAD_NAME; + bool success = spl_rename_internal(from_path_fs, to_path_fs, error_r); g_free(from_path_fs); g_free(to_path_fs); - return ret; + return success; } -- cgit v1.2.3