diff options
-rw-r--r-- | src/command.c | 40 | ||||
-rw-r--r-- | src/directory.c | 38 | ||||
-rw-r--r-- | src/directory.h | 10 |
3 files changed, 58 insertions, 30 deletions
diff --git a/src/command.c b/src/command.c index ce41abb64..70bfa78b5 100644 --- a/src/command.c +++ b/src/command.c @@ -36,6 +36,7 @@ #include "os_compat.h" #include "player_error.h" #include "outputBuffer.h" +#include "path.h" #define COMMAND_PLAY "play" #define COMMAND_PLAYID "playid" @@ -805,7 +806,10 @@ static int print_update_result(int fd, int ret) fdprintf(fd, "updating_db: %i\n", ret); return 0; } - commandError(fd, ACK_ERROR_UPDATE_ALREADY, "already updating"); + if (ret == -2) + commandError(fd, ACK_ERROR_ARG, "invalid path"); + else + commandError(fd, ACK_ERROR_UPDATE_ALREADY, "already updating"); return -1; } @@ -815,20 +819,28 @@ static int listHandleUpdate(int fd, char *argv[], struct strnode *cmdnode, CommandEntry * cmd) { - List *pathList = makeList(NULL, 1); + static char **pathv; + static int pathc; CommandEntry *nextCmd = NULL; struct strnode *next = cmdnode->next; + int last = pathc++; - if (argc == 2) - insertInList(pathList, argv[1], NULL); - else - insertInList(pathList, "", NULL); + pathv = xrealloc(pathv, pathc * sizeof(char *)); + pathv[last] = sanitizePathDup(argc == 2 ? argv[1] : ""); if (next) nextCmd = getCommandEntryFromString(next->data, permission); - if (cmd != nextCmd) - return print_update_result(fd, updateInit(pathList)); + if (cmd != nextCmd) { + int ret = print_update_result(fd, updateInit(pathc, pathv)); + if (pathc) { + assert(pathv); + free(pathv); + pathv = NULL; + pathc = 0; + } + return ret; + } return 0; } @@ -836,14 +848,12 @@ static int listHandleUpdate(int fd, static int handleUpdate(int fd, mpd_unused int *permission, mpd_unused int argc, char *argv[]) { - List *pathList = NULL; + char *pathv[1]; - if (argc == 2) { - pathList = makeList(NULL, 1); - insertInList(pathList, argv[1], NULL); - } - - return print_update_result(fd, updateInit(pathList)); + assert(argc <= 2); + if (argc == 2) + pathv[0] = sanitizePathDup(argv[1]); + return print_update_result(fd, updateInit(argc - 1, pathv)); } static int handleNext(mpd_unused int fd, mpd_unused int *permission, diff --git a/src/directory.c b/src/directory.c index a332316ff..8d36985dc 100644 --- a/src/directory.c +++ b/src/directory.c @@ -114,16 +114,15 @@ void reap_update_task(void) progress = UPDATE_PROGRESS_IDLE; } -static void * update_task(void *arg) +/* @argv represents a null-terminated array of (null-terminated) strings */ +static void * update_task(void *argv) { - List *path_list = (List *)arg; enum update_return ret = UPDATE_RETURN_NOUPDATE; - if (path_list) { - ListNode *node = path_list->firstNode; - - while (node) { - switch (updatePath(node->key)) { + if (argv) { + char **pathv; + for (pathv = (char **)argv; *pathv; pathv++) { + switch (updatePath(*pathv)) { case UPDATE_RETURN_ERROR: ret = UPDATE_RETURN_ERROR; goto out; @@ -132,9 +131,9 @@ static void * update_task(void *arg) case UPDATE_RETURN_UPDATED: ret = UPDATE_RETURN_UPDATED; } - node = node->nextNode; + free(*pathv); } - freeList(path_list); + free(argv); } else { ret = updateDirectory(music_root); } @@ -147,17 +146,32 @@ out: return (void *)ret; } -int updateInit(List * path_list) +int updateInit(int argc, char *argv[]) { pthread_attr_t attr; + char **pathv = NULL; + int i; - if (progress != UPDATE_PROGRESS_IDLE) + if (progress != UPDATE_PROGRESS_IDLE) { + for (i = argc; --i >= 0; ) + free(argv[i]); return -1; + } + + for (i = argc; --i >= 0; ) { + if (!argv[i]) + return -2; + } progress = UPDATE_PROGRESS_RUNNING; + if (argc > 0) { + pathv = xmalloc((argc + 1) * sizeof(char *)); + memcpy(pathv, argv, argc * sizeof(char *)); + pathv[argc] = NULL; + } pthread_attr_init(&attr); - if (pthread_create(&update_thr, &attr, update_task, path_list)) + if (pthread_create(&update_thr, &attr, update_task, pathv)) FATAL("Failed to spawn update task: %s\n", strerror(errno)); directory_updateJobId++; if (directory_updateJobId > 1 << 15) diff --git a/src/directory.h b/src/directory.h index 9161efc38..eb1b35aa7 100644 --- a/src/directory.h +++ b/src/directory.h @@ -21,7 +21,6 @@ #include "song.h" #include "songvec.h" -#include "list.h" struct dirvec { struct _Directory **base; @@ -42,8 +41,13 @@ void reap_update_task(void); int isUpdatingDB(void); -/* returns the non-negative update job ID on success, -1 on error */ -int updateInit(List * pathList); +/* + * returns the non-negative update job ID on success, + * -1 if busy, -2 if invalid argument + * @argv itself is safe to free once updateInit returns, but the + * string values contained by @argv MUST NOT be freed manually + */ +int updateInit(int argc, char *argv[]); void directory_init(void); |