diff options
-rw-r--r-- | src/ls.c | 82 | ||||
-rw-r--r-- | src/stored_playlist.c | 79 | ||||
-rw-r--r-- | src/stored_playlist.h | 18 |
3 files changed, 106 insertions, 73 deletions
@@ -23,6 +23,7 @@ #include "log.h" #include "utils.h" #include "list.h" +#include "stored_playlist.h" #include "os_compat.h" static const char *remoteUrlPrefixes[] = { @@ -99,84 +100,19 @@ int isRemoteUrl(const char *url) int lsPlaylists(struct client *client, const char *utf8path) { - DIR *dir; - struct stat st; - struct dirent *ent; - char *duplicated; - char *utf8; - char s[MPD_PATH_MAX]; - char path_max_tmp[MPD_PATH_MAX]; - List *list = NULL; - ListNode *node; - char *actualPath = rpp2app_r(path_max_tmp, - utf8_to_fs_charset(path_max_tmp, - utf8path)); - size_t actlen = strlen(actualPath) + 1; - size_t maxlen = MPD_PATH_MAX - actlen; - size_t suflen = strlen(PLAYLIST_FILE_SUFFIX) + 1; - ssize_t suff; - - if (actlen > MPD_PATH_MAX - 1 || (dir = opendir(actualPath)) == NULL) { + GPtrArray *list = spl_list(); + if (list == NULL) return 0; - } - - s[MPD_PATH_MAX - 1] = '\0'; - /* this is safe, notice actlen > MPD_PATH_MAX-1 above */ - strcpy(s, actualPath); - strcat(s, "/"); - - while ((ent = readdir(dir))) { - size_t len = strlen(ent->d_name) + 1; - duplicated = ent->d_name; - if (mpd_likely(len <= maxlen) && - duplicated[0] != '.' && - (suff = (ssize_t)(strlen(duplicated) - suflen)) > 0 && - duplicated[suff] == '.' && - strcmp(duplicated + suff + 1, PLAYLIST_FILE_SUFFIX) == 0) { - memcpy(s + actlen, ent->d_name, len); - if (stat(s, &st) == 0) { - if (S_ISREG(st.st_mode)) { - if (list == NULL) - list = makeList(NULL, 1); - duplicated[suff] = '\0'; - utf8 = fs_charset_to_utf8(path_max_tmp, - duplicated); - if (utf8) - insertInList(list, utf8, NULL); - } - } - } - } - closedir(dir); - - if (list) { - int i; - sortList(list); - - duplicated = xmalloc(strlen(utf8path) + 2); - strcpy(duplicated, utf8path); - for (i = strlen(duplicated) - 1; - i >= 0 && duplicated[i] == '/'; - i--) { - duplicated[i] = '\0'; - } - if (strlen(duplicated)) - strcat(duplicated, "/"); - - node = list->firstNode; - while (node != NULL) { - if (!strchr(node->key, '\n')) { - client_printf(client, "playlist: %s%s\n", - duplicated, node->key); - } - node = node->nextNode; - } + for (unsigned i = 0; i < list->len; ++i) { + struct stored_playlist_info *playlist = + g_ptr_array_index(list, i); - freeList(list); - free(duplicated); + client_printf(client, "playlist: %s%s\n", + utf8path, playlist->name); } + spl_list_free(list); return 0; } diff --git a/src/stored_playlist.c b/src/stored_playlist.c index ad9e43ce4..121f5ed3d 100644 --- a/src/stored_playlist.c +++ b/src/stored_playlist.c @@ -27,6 +27,85 @@ #include "idle.h" #include "os_compat.h" +static struct stored_playlist_info * +load_playlist_info(const char *parent_path_fs, const char *name_fs) +{ + size_t name_length = strlen(name_fs); + char buffer[MPD_PATH_MAX], *name, *name_utf8; + int ret; + struct stat st; + struct stored_playlist_info *playlist; + + if (name_length < 1 + sizeof(PLAYLIST_FILE_SUFFIX) || + strlen(parent_path_fs) + name_length >= sizeof(buffer) || + memchr(name_fs, '\n', name_length) != NULL) + return NULL; + + if (name_fs[name_length - sizeof(PLAYLIST_FILE_SUFFIX)] != '.' || + memcmp(name_fs + name_length - sizeof(PLAYLIST_FILE_SUFFIX) + 1, + PLAYLIST_FILE_SUFFIX, + sizeof(PLAYLIST_FILE_SUFFIX) - 1) != 0) + return NULL; + + pfx_dir(buffer, name_fs, name_length, + parent_path_fs, strlen(parent_path_fs)); + + ret = stat(buffer, &st); + if (ret < 0 || !S_ISREG(st.st_mode)) + return NULL; + + name = g_strdup(name_fs); + name[name_length - sizeof(PLAYLIST_FILE_SUFFIX)] = 0; + name_utf8 = fs_charset_to_utf8(buffer, name); + g_free(name); + if (name_utf8 == NULL) + return NULL; + + playlist = g_new(struct stored_playlist_info, 1); + playlist->name = g_strdup(name_utf8); + playlist->mtime = st.st_mtime; + return playlist; +} + +GPtrArray * +spl_list(void) +{ + char parent_path_fs[MPD_PATH_MAX]; + DIR *dir; + struct dirent *ent; + GPtrArray *list; + struct stored_playlist_info *playlist; + + rpp2app_r(parent_path_fs, ""); + dir = opendir(parent_path_fs); + if (dir == NULL) + return NULL; + + list = g_ptr_array_new(); + + while ((ent = readdir(dir)) != NULL) { + playlist = load_playlist_info(parent_path_fs, ent->d_name); + if (playlist != NULL) + g_ptr_array_add(list, playlist); + } + + closedir(dir); + return list; +} + +void +spl_list_free(GPtrArray *list) +{ + for (unsigned i = 0; i < list->len; ++i) { + struct stored_playlist_info *playlist = + g_ptr_array_index(list, i); + g_free(playlist->name); + g_free(playlist); + } + + g_ptr_array_free(list, true); +} + static ListNode * spl_get_index(List *list, int idx) { diff --git a/src/stored_playlist.h b/src/stored_playlist.h index 637a1093d..f524829df 100644 --- a/src/stored_playlist.h +++ b/src/stored_playlist.h @@ -22,8 +22,26 @@ #include "list.h" #include "playlist.h" +#include <glib.h> + struct song; +struct stored_playlist_info { + char *name; + + time_t mtime; +}; + +/** + * Returns a list of stored_playlist_info struct pointers. Returns + * NULL if an error occured. + */ +GPtrArray * +spl_list(void); + +void +spl_list_free(GPtrArray *list); + List * spl_load(const char *utf8path); |