src/server/webdav/operation.c

branch
webdav
changeset 245
a193c42fc809
parent 241
4adad7faf452
child 246
155bdef7fe7e
equal deleted inserted replaced
244:e59abb210584 245:a193c42fc809
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <errno.h>
31 32
32 #include <ucx/list.h> 33 #include <ucx/list.h>
33 34
34 #include "../daemon/session.h" 35 #include "../daemon/session.h"
36 #include "../util/pblock.h"
35 37
36 #include "operation.h" 38 #include "operation.h"
37 39
38 #define WEBDAV_PATH_MAX 8192 40 #define WEBDAV_PATH_MAX 8192
39 41
521 WebdavResource *resource) 523 WebdavResource *resource)
522 { 524 {
523 return 0; // NOP 525 return 0; // NOP
524 } 526 }
525 527
528
529 /****************************************************************************
530 *
531 * VFS OPERATION
532 *
533 ****************************************************************************/
534
535 WebdavVFSOperation* webdav_vfs_op(
536 Session *sn,
537 Request *rq,
538 WebdavBackend *dav,
539 WSBool precondition)
540 {
541 WebdavVFSOperation *op = pool_malloc(sn->pool, sizeof(WebdavVFSOperation));
542 if(!op) {
543 return NULL;
544 }
545 ZERO(op, sizeof(WebdavVFSOperation));
546
547 op->sn = sn;
548 op->rq = rq;
549 op->dav = dav;
550 op->stat = NULL;
551 op->stat_errno = 0;
552
553 // create VFS context
554 VFSContext *vfs = vfs_request_context(sn, rq);
555 if(!vfs) {
556 pool_free(sn->pool, op);
557 return NULL;
558 }
559 op->vfs = vfs;
560
561 char *path = pblock_findkeyval(pb_key_path, rq->vars);
562 op->path = path;
563
564 return op;
565 }
566
567 int webdav_vfs_stat(WebdavVFSOperation *op) {
568 if(op->stat) {
569 return 0;
570 } else if(op->stat_errno != 0) {
571 // previous stat failed
572 return 1;
573 }
574
575 // stat file
576 struct stat sbuf;
577 int ret = vfs_stat(op->vfs, op->path, &sbuf);
578 if(!ret) {
579 // save result in op->stat and in s
580 op->stat = pool_malloc(op->sn->pool, sizeof(struct stat));
581 if(op->stat) {
582 memcpy(op->stat, &sbuf, sizeof(struct stat));
583 } else {
584 ret = 1;
585 op->stat_errno = ENOMEM;
586 }
587 } else {
588 op->stat_errno = errno;
589 }
590
591 return ret;
592 }
593
594 int webdav_vfs_op_do(WebdavVFSOperation *op, WebdavVFSOpType type) {
595 WSBool exec_vfs = TRUE;
596
597 // requests for each backends
598 WebdavVFSRequest **requests = pool_calloc(
599 op->sn->pool,
600 webdav_num_backends(op->dav),
601 sizeof(WebdavVFSRequest*));
602 if(requests == NULL) {
603 return REQ_ABORTED;
604 }
605
606 int ret = REQ_PROCEED;
607
608 // call opt_* func for each backend
609 WebdavBackend *dav = op->dav;
610 int called_backends = 0;
611 while(dav) {
612 WebdavVFSRequest *request = NULL;
613
614 // get vfs operation functions
615 vfs_op_func op_func = NULL;
616 vfs_op_finish_func op_finish_func = NULL;
617
618 if(type == WEBDAV_VFS_MKDIR) {
619 op_func = dav->opt_mkcol;
620 op_finish_func = dav->opt_mkcol_finish;
621 } else if(type == WEBDAV_VFS_DELETE) {
622 op_func = dav->opt_delete;
623 op_finish_func = dav->opt_delete_finish;
624 }
625
626 if(op_func || op_finish_func) {
627 // we need a request object
628 request = pool_malloc(op->sn->pool, sizeof(WebdavVFSRequest));
629 if(!request) {
630 exec_vfs = FALSE;
631 ret = REQ_ABORTED;
632 break;
633 }
634 request->sn = op->sn;
635 request->rq = op->rq;
636 request->path = op->path;
637 request->userdata = NULL;
638
639 requests[called_backends] = request;
640 }
641
642 // exec backend func for this operation
643 // this will set 'done' to TRUE, if no further vfs call is required
644 WSBool done = FALSE;
645 called_backends++;
646 if(op_func) {
647 if(op_func(request, &done)) {
648 exec_vfs = FALSE;
649 ret = REQ_ABORTED;
650 break;
651 }
652 }
653 if(done) {
654 exec_vfs = FALSE;
655 }
656
657 dav = dav->next;
658 }
659
660 // if needed, call vfs func for this operation
661 if(exec_vfs) {
662 int r = 0;
663 if(type == WEBDAV_VFS_MKDIR) {
664 r = vfs_mkdir(op->vfs, op->path);
665 } else if(type == WEBDAV_VFS_DELETE) {
666 r = webdav_vfs_unlink(op);
667 }
668
669 if(r) {
670 ret = REQ_ABORTED;
671 }
672 }
673
674 WSBool success = ret == REQ_PROCEED ? TRUE : FALSE;
675
676 // finish mkcol (cleanup) by calling opt_*_finish for each backend
677 dav = op->dav;
678 int i = 0;
679 while(dav && i < called_backends) {
680 // get vfs operation functions
681 vfs_op_finish_func op_finish_func = NULL;
682
683 if(type == WEBDAV_VFS_MKDIR) {
684 op_finish_func = dav->opt_mkcol_finish;
685 } else if(type == WEBDAV_VFS_DELETE) {
686 op_finish_func = dav->opt_delete_finish;
687 }
688
689 if(op_finish_func) {
690 if(op_finish_func(requests[i], success)) {
691 ret = REQ_ABORTED; // don't exit loop
692 }
693 }
694
695 dav = dav->next;
696 i++;
697 }
698
699 return ret;
700 }
701
702 int webdav_vfs_unlink(WebdavVFSOperation *op) {
703 // stat the file first, to check if the file is a directory
704 // deletion of simple files can be done just here,
705 // whereas deleting directories is more complicated
706 if(webdav_vfs_stat(op)) {
707 return 1; // error
708 } else {
709 int r = 0;
710 if(!S_ISDIR(op->stat->st_mode)) {
711 return vfs_unlink(op->vfs, op->path);
712 }
713 }
714
715 // delete directory:
716
717
718
719 return 0;
720 }

mercurial