aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/command.c40
-rw-r--r--src/directory.c38
-rw-r--r--src/directory.h10
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);