diff -r 155bdef7fe7e -r 1df803e06076 src/server/webdav/webdav.c --- a/src/server/webdav/webdav.c Sun May 31 13:08:42 2020 +0200 +++ b/src/server/webdav/webdav.c Sun May 31 16:58:23 2020 +0200 @@ -461,9 +461,101 @@ return REQ_ABORTED; } +typedef struct DeleteFile { + char *path; + struct stat s; +} DeleteFile; + +typedef struct DeleteLists { + UcxAllocator *a; + UcxList *dirs_begin; + UcxList *dirs_end; + UcxList *files_begin; + UcxList *files_end; +} DeleteOp; + +static int deletelist_add( + VFSContext *vfs, + const char *href, + const char *path, + VFSDir *parent, + struct stat *s, + void *userdata) +{ + DeleteOp *op = userdata; + + // create object for this file + DeleteFile *file = almalloc(op->a, sizeof(DeleteFile)); + if(!file) { + return 1; + } + file->path = sstrdup_a(op->a, sstr((char*)path)).ptr; + if(!file->path) { + return 1; + } + file->s = *s; + + // determine which list to use + UcxList **begin; + UcxList **end; + if(S_ISDIR(s->st_mode)) { + begin = &op->dirs_begin; + end = &op->dirs_end; + } else { + begin = &op->files_begin; + end = &op->files_end; + } + + // add file to list + UcxList *elm = ucx_list_append_a(op->a, NULL, file); + if(!elm) { + alfree(op->a, file->path); // at least do some cleanup, although it + alfree(op->a, file); // isn't really necessary + return 1; + } + if(*begin == NULL) { + *begin = elm; + *end = elm; + } else { + ucx_list_concat(*end, elm); + *end = elm; + } + + return 0; +} + static int webdav_delete_collection(WebdavVFSOperation *op) { - // TODO + DeleteOp del; + ZERO(&del, sizeof(DeleteOp)); + del.a = session_get_allocator(op->sn); + + // get a list of all files + if(webdav_op_iterate_children(op->vfs, -1, NULL, op->path, + deletelist_add, &del)) + { + return 1; + } + + // delete files first + UCX_FOREACH(elm, del.files_begin) { + DeleteFile *file = elm->data; + WebdavVFSOperation sub = webdav_vfs_sub_op(op, file->path, &file->s); + if(webdav_vfs_op_do(&sub, WEBDAV_VFS_DELETE)) { + return 1; + } + } + + // delete directories, reverse order + for(UcxList *elm=del.dirs_end;elm;elm=elm->prev) { + DeleteFile *file = elm->data; + WebdavVFSOperation sub = webdav_vfs_sub_op(op, file->path, &file->s); + if(webdav_vfs_op_do(&sub, WEBDAV_VFS_DELETE)) { + return 1; + } + } + + return 0; } int webdav_delete(pblock *pb, Session *sn, Request *rq) {