src/server/webdav/webdav.c

branch
webdav
changeset 247
1df803e06076
parent 246
155bdef7fe7e
child 249
3b302093945c
--- 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) { 

mercurial