comparison src/http/modules/ngx_http_dav_module.c @ 1825:2e0fbfef56d4

do not delete target until all tests will be done, fix single file COPY/MOVE
author Igor Sysoev <igor@sysoev.ru>
date Thu, 03 Jan 2008 21:44:38 +0000
parents 8299cd253745
children 1f3c2b6607e0
comparison
equal deleted inserted replaced
1824:8299cd253745 1825:2e0fbfef56d4
49 49
50 static ngx_int_t ngx_http_dav_copy_move_handler(ngx_http_request_t *r); 50 static ngx_int_t ngx_http_dav_copy_move_handler(ngx_http_request_t *r);
51 static ngx_int_t ngx_http_dav_copy_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path); 51 static ngx_int_t ngx_http_dav_copy_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path);
52 static ngx_int_t ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx, 52 static ngx_int_t ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx,
53 ngx_str_t *path); 53 ngx_str_t *path);
54 static ngx_int_t ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); 54 static ngx_int_t ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx,
55 ngx_str_t *path);
56 static ngx_int_t ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from,
57 u_char *to);
55 58
56 static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt); 59 static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt);
57 static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, 60 static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err,
58 ngx_int_t not_found, char *failed, u_char *path); 61 ngx_int_t not_found, char *failed, u_char *path);
59 static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r, u_char *path); 62 static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r, u_char *path);
580 { 583 {
581 u_char *p, *desthost, *last, ch; 584 u_char *p, *desthost, *last, ch;
582 size_t len, root; 585 size_t len, root;
583 ngx_err_t err; 586 ngx_err_t err;
584 ngx_int_t rc, depth; 587 ngx_int_t rc, depth;
585 ngx_uint_t overwrite, slash; 588 ngx_uint_t overwrite, slash, dir;
586 ngx_str_t path, uri; 589 ngx_str_t path, uri;
587 ngx_tree_ctx_t tree; 590 ngx_tree_ctx_t tree;
588 ngx_file_info_t fi; 591 ngx_file_info_t fi;
589 ngx_table_elt_t *host, *dest, *over; 592 ngx_table_elt_t *host, *dest, *over;
590 ngx_http_dav_copy_ctx_t copy; 593 ngx_http_dav_copy_ctx_t copy;
594 ngx_http_dav_loc_conf_t *dlcf;
591 595
592 if (r->headers_in.content_length_n > 0) { 596 if (r->headers_in.content_length_n > 0) {
593 return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; 597 return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
594 } 598 }
595 599
752 copy.path.data); 756 copy.path.data);
753 } 757 }
754 758
755 /* destination does not exist */ 759 /* destination does not exist */
756 760
761 overwrite = 0;
762 dir = 0;
763
757 } else { 764 } else {
758 765
759 /* destination exists */ 766 /* destination exists */
760 767
761 if (ngx_is_dir(&fi) && !slash) { 768 if (ngx_is_dir(&fi) && !slash) {
769 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EEXIST, 776 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EEXIST,
770 "\"%s\" could not be created", copy.path.data); 777 "\"%s\" could not be created", copy.path.data);
771 return NGX_HTTP_PRECONDITION_FAILED; 778 return NGX_HTTP_PRECONDITION_FAILED;
772 } 779 }
773 780
774 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 781 dir = ngx_is_dir(&fi);
775 "http delete: \"%s\"", copy.path.data);
776
777 rc = ngx_http_dav_delete_path(r, &copy.path, ngx_is_dir(&fi));
778
779 if (rc != NGX_OK) {
780 return rc;
781 }
782 } 782 }
783 783
784 if (ngx_file_info(path.data, &fi) == -1) { 784 if (ngx_file_info(path.data, &fi) == -1) {
785 return ngx_http_dav_error(r->connection->log, ngx_errno, 785 return ngx_http_dav_error(r->connection->log, ngx_errno,
786 NGX_HTTP_NOT_FOUND, ngx_file_info_n, 786 NGX_HTTP_NOT_FOUND, ngx_file_info_n,
787 path.data); 787 path.data);
788 } 788 }
789 789
790
791 if (ngx_is_dir(&fi)) { 790 if (ngx_is_dir(&fi)) {
792 791
793 if (r->uri.data[r->uri.len - 1] != '/') { 792 if (r->uri.data[r->uri.len - 1] != '/') {
794 /* TODO: 301 */ 793 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
794 "\"%V\" is collection", &r->uri);
795 return NGX_HTTP_BAD_REQUEST; 795 return NGX_HTTP_BAD_REQUEST;
796 } 796 }
797
798 if (overwrite) {
799 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
800 "http delete: \"%s\"", copy.path.data);
801
802 rc = ngx_http_dav_delete_path(r, &copy.path, dir);
803
804 if (rc != NGX_OK) {
805 return rc;
806 }
807 }
808 }
809
810 if (ngx_is_dir(&fi)) {
797 811
798 path.len -= 2; /* omit "/\0" */ 812 path.len -= 2; /* omit "/\0" */
799 813
800 if (r->method == NGX_HTTP_MOVE) { 814 if (r->method == NGX_HTTP_MOVE) {
801 if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) { 815 if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) {
812 } 826 }
813 827
814 copy.len = path.len; 828 copy.len = path.len;
815 829
816 tree.init_handler = NULL; 830 tree.init_handler = NULL;
817 tree.file_handler = ngx_http_dav_copy_file; 831 tree.file_handler = ngx_http_dav_copy_tree_file;
818 tree.pre_tree_handler = ngx_http_dav_copy_dir; 832 tree.pre_tree_handler = ngx_http_dav_copy_dir;
819 tree.post_tree_handler = ngx_http_dav_copy_dir_time; 833 tree.post_tree_handler = ngx_http_dav_copy_dir_time;
820 tree.spec_handler = ngx_http_dav_noop; 834 tree.spec_handler = ngx_http_dav_noop;
821 tree.data = &copy; 835 tree.data = &copy;
822 tree.alloc = 0; 836 tree.alloc = 0;
835 return NGX_HTTP_CREATED; 849 return NGX_HTTP_CREATED;
836 } 850 }
837 851
838 } else { 852 } else {
839 853
840 if (dest->value.data[dest->value.len - 1] == '/') {
841 return NGX_HTTP_BAD_REQUEST;
842 }
843
844 if (r->method == NGX_HTTP_MOVE) { 854 if (r->method == NGX_HTTP_MOVE) {
845 if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) { 855 if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) {
846 return NGX_HTTP_NO_CONTENT; 856 return NGX_HTTP_NO_CONTENT;
847 } 857 }
848 } 858 }
849 859
850 tree.data = &copy; 860 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
861
862 tree.size = ngx_file_size(&fi);
863 tree.mtime = ngx_file_mtime(&fi);
864 tree.access = dlcf->access;
851 tree.log = r->connection->log; 865 tree.log = r->connection->log;
852 866
853 if (ngx_http_dav_copy_file(&tree, &path) != NGX_FILE_ERROR) { 867 if (ngx_http_dav_copy_file(&tree, path.data, copy.path.data) == NGX_OK)
854 868 {
855 if (r->method == NGX_HTTP_MOVE) { 869 if (r->method == NGX_HTTP_MOVE) {
856 rc = ngx_http_dav_delete_path(r, &path, 0); 870 rc = ngx_http_dav_delete_path(r, &path, 0);
857 871
858 if (rc != NGX_OK) { 872 if (rc != NGX_OK) {
859 return rc; 873 return rc;
967 return NGX_OK; 981 return NGX_OK;
968 } 982 }
969 983
970 984
971 static ngx_int_t 985 static ngx_int_t
972 ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) 986 ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path)
973 { 987 {
974 u_char *p, *file; 988 u_char *p, *file;
975 size_t len; 989 size_t len;
976 off_t size;
977 ssize_t n;
978 ngx_fd_t fd, copy_fd;
979 ngx_http_dav_copy_ctx_t *copy; 990 ngx_http_dav_copy_ctx_t *copy;
980 u_char buf[NGX_HTTP_DAV_COPY_BLOCK];
981 991
982 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, 992 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
983 "http copy file: \"%s\"", path->data); 993 "http copy file: \"%s\"", path->data);
984 994
985 copy = ctx->data; 995 copy = ctx->data;
995 (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1); 1005 (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1);
996 1006
997 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, 1007 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
998 "http copy file to: \"%s\"", file); 1008 "http copy file to: \"%s\"", file);
999 1009
1000 fd = ngx_open_file(path->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); 1010 (void) ngx_http_dav_copy_file(ctx, path->data, file);
1011
1012 ngx_free(file);
1013
1014 return NGX_OK;
1015 }
1016
1017
1018 static ngx_int_t
1019 ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from, u_char *to)
1020 {
1021 off_t size;
1022 ssize_t n;
1023 ngx_fd_t fd, cfd;
1024 ngx_int_t rc;
1025 u_char buf[NGX_HTTP_DAV_COPY_BLOCK];
1026
1027 fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
1001 1028
1002 if (fd == NGX_INVALID_FILE) { 1029 if (fd == NGX_INVALID_FILE) {
1003 (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, 1030 (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n,
1004 path->data); 1031 from);
1032 return NGX_ERROR;
1033 }
1034
1035 cfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN,
1036 ctx->access);
1037
1038 rc = NGX_ERROR;
1039
1040 if (cfd == NGX_INVALID_FILE) {
1041 (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, to);
1005 goto failed; 1042 goto failed;
1006 }
1007
1008 copy_fd = ngx_open_file(file, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN,
1009 ctx->access);
1010
1011 if (copy_fd == NGX_INVALID_FILE) {
1012 (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n,
1013 file);
1014 goto copy_failed;
1015 } 1043 }
1016 1044
1017 for (size = ctx->size; size > 0; size -= n) { 1045 for (size = ctx->size; size > 0; size -= n) {
1018 1046
1019 n = ngx_read_fd(fd, buf, NGX_HTTP_DAV_COPY_BLOCK); 1047 n = ngx_read_fd(fd, buf, NGX_HTTP_DAV_COPY_BLOCK);
1020 1048
1021 if (n == NGX_FILE_ERROR) { 1049 if (n == NGX_FILE_ERROR) {
1022 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, 1050 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
1023 ngx_read_fd_n " \"%s\" failed", path->data); 1051 ngx_read_fd_n " \"%s\" failed", from);
1024 break; 1052 goto failed;
1025 } 1053 }
1026 1054
1027 if (ngx_write_fd(copy_fd, buf, n) == NGX_FILE_ERROR) { 1055 if (ngx_write_fd(cfd, buf, n) == NGX_FILE_ERROR) {
1028 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, 1056 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
1029 ngx_write_fd_n " \"%s\" failed", file); 1057 ngx_write_fd_n " \"%s\" failed", to);
1030 } 1058 goto failed;
1031 } 1059 }
1032 1060 }
1033 if (ngx_set_file_time(file, copy_fd, ctx->mtime) != NGX_OK) { 1061
1062 if (ngx_set_file_time(to, cfd, ctx->mtime) != NGX_OK) {
1034 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, 1063 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
1035 ngx_set_file_time_n " \"%s\" failed", file); 1064 ngx_set_file_time_n " \"%s\" failed", to);
1036 } 1065 goto failed;
1037 1066 }
1038 if (ngx_close_file(copy_fd) == NGX_FILE_ERROR) { 1067
1068 if (ngx_close_file(cfd) == NGX_FILE_ERROR) {
1039 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, 1069 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
1040 ngx_close_file_n " \"%s\" failed", file); 1070 ngx_close_file_n " \"%s\" failed", to);
1041 } 1071 goto failed;
1042 1072 }
1043 copy_failed: 1073
1074 rc = NGX_OK;
1075
1076 failed:
1044 1077
1045 if (ngx_close_file(fd) == NGX_FILE_ERROR) { 1078 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
1046 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, 1079 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
1047 ngx_close_file_n " \"%s\" failed", path->data); 1080 ngx_close_file_n " \"%s\" failed", from);
1048 } 1081 }
1049 1082
1050 failed: 1083 return rc;
1051
1052 ngx_free(file);
1053
1054 return NGX_OK;
1055 } 1084 }
1056 1085
1057 1086
1058 static ngx_int_t 1087 static ngx_int_t
1059 ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt) 1088 ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt)