Mercurial > hg > nginx
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, ©.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, ©.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 = © | 835 tree.data = © |
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 = © | 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) |