Mercurial > hg > nginx
comparison src/http/modules/ngx_http_dav_module.c @ 3248:8c76116820f3 stable-0.7
merge r3024, r3025, r3028, r3033, r3034, r3035, r3036:
allow cross device temporary files atomic copying
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 26 Oct 2009 17:32:17 +0000 |
parents | 2efa8d2fcde1 |
children | ef8cfb09a50b |
comparison
equal
deleted
inserted
replaced
3247:1f3cd08ebb82 | 3248:8c76116820f3 |
---|---|
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_tree_file(ngx_tree_ctx_t *ctx, | 54 static ngx_int_t ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, |
55 ngx_str_t *path); | 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); | |
58 | 56 |
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_depth(ngx_http_request_t *r, ngx_int_t dflt); |
60 static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, | 58 static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, |
61 ngx_int_t not_found, char *failed, u_char *path); | 59 ngx_int_t not_found, char *failed, u_char *path); |
62 static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r, u_char *path); | 60 static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r, u_char *path); |
214 ngx_ext_rename_file_t ext; | 212 ngx_ext_rename_file_t ext; |
215 ngx_http_dav_loc_conf_t *dlcf; | 213 ngx_http_dav_loc_conf_t *dlcf; |
216 | 214 |
217 ngx_http_map_uri_to_path(r, &path, &root, 0); | 215 ngx_http_map_uri_to_path(r, &path, &root, 0); |
218 | 216 |
217 path.len--; | |
218 | |
219 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 219 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
220 "http put filename: \"%s\"", path.data); | 220 "http put filename: \"%s\"", path.data); |
221 | 221 |
222 temp = &r->request_body->temp_file->file.name; | 222 temp = &r->request_body->temp_file->file.name; |
223 | 223 |
247 ext.access = dlcf->access; | 247 ext.access = dlcf->access; |
248 ext.path_access = dlcf->access; | 248 ext.path_access = dlcf->access; |
249 ext.time = -1; | 249 ext.time = -1; |
250 ext.create_path = dlcf->create_full_put_path; | 250 ext.create_path = dlcf->create_full_put_path; |
251 ext.delete_file = 1; | 251 ext.delete_file = 1; |
252 ext.log_rename_error = 1; | |
253 ext.log = r->connection->log; | 252 ext.log = r->connection->log; |
254 | 253 |
255 if (r->headers_in.date) { | 254 if (r->headers_in.date) { |
256 date = ngx_http_parse_time(r->headers_in.date->value.data, | 255 date = ngx_http_parse_time(r->headers_in.date->value.data, |
257 r->headers_in.date->value.len); | 256 r->headers_in.date->value.len); |
518 ngx_err_t err; | 517 ngx_err_t err; |
519 ngx_int_t rc, depth; | 518 ngx_int_t rc, depth; |
520 ngx_uint_t overwrite, slash, dir; | 519 ngx_uint_t overwrite, slash, dir; |
521 ngx_str_t path, uri; | 520 ngx_str_t path, uri; |
522 ngx_tree_ctx_t tree; | 521 ngx_tree_ctx_t tree; |
522 ngx_copy_file_t cf; | |
523 ngx_file_info_t fi; | 523 ngx_file_info_t fi; |
524 ngx_table_elt_t *dest, *over; | 524 ngx_table_elt_t *dest, *over; |
525 ngx_ext_rename_file_t ext; | 525 ngx_ext_rename_file_t ext; |
526 ngx_http_dav_copy_ctx_t copy; | 526 ngx_http_dav_copy_ctx_t copy; |
527 ngx_http_dav_loc_conf_t *dlcf; | 527 ngx_http_dav_loc_conf_t *dlcf; |
789 ext.access = 0; | 789 ext.access = 0; |
790 ext.path_access = dlcf->access; | 790 ext.path_access = dlcf->access; |
791 ext.time = -1; | 791 ext.time = -1; |
792 ext.create_path = 1; | 792 ext.create_path = 1; |
793 ext.delete_file = 0; | 793 ext.delete_file = 0; |
794 ext.log_rename_error = 0; | |
795 ext.log = r->connection->log; | 794 ext.log = r->connection->log; |
796 | 795 |
797 if (ngx_ext_rename_file(&path, ©.path, &ext) == NGX_OK) { | 796 if (ngx_ext_rename_file(&path, ©.path, &ext) == NGX_OK) { |
798 return NGX_HTTP_NO_CONTENT; | 797 return NGX_HTTP_NO_CONTENT; |
799 } | 798 } |
800 | 799 |
801 if (ext.rename_error != NGX_EXDEV) { | 800 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
802 | |
803 if (ext.rename_error) { | |
804 ngx_log_error(NGX_LOG_CRIT, r->connection->log, | |
805 ext.rename_error, | |
806 ngx_rename_file_n " \"%s\" to \"%s\" failed", | |
807 path.data, copy.path.data); | |
808 } | |
809 | |
810 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
811 } | |
812 } | 801 } |
813 | 802 |
814 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); | 803 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); |
815 | 804 |
816 tree.size = ngx_file_size(&fi); | 805 cf.size = ngx_file_size(&fi); |
817 tree.mtime = ngx_file_mtime(&fi); | 806 cf.buf_size = 0; |
818 tree.access = dlcf->access; | 807 cf.access = dlcf->access; |
819 tree.log = r->connection->log; | 808 cf.time = ngx_file_mtime(&fi); |
820 | 809 cf.log = r->connection->log; |
821 if (ngx_http_dav_copy_file(&tree, path.data, copy.path.data) == NGX_OK) | 810 |
822 { | 811 if (ngx_copy_file(path.data, copy.path.data, &cf) == NGX_OK) { |
823 if (r->method == NGX_HTTP_MOVE) { | |
824 rc = ngx_http_dav_delete_path(r, &path, 0); | |
825 | |
826 if (rc != NGX_OK) { | |
827 return rc; | |
828 } | |
829 } | |
830 | |
831 return NGX_HTTP_NO_CONTENT; | 812 return NGX_HTTP_NO_CONTENT; |
832 } | 813 } |
833 } | 814 } |
834 | 815 |
835 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 816 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
939 static ngx_int_t | 920 static ngx_int_t |
940 ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) | 921 ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) |
941 { | 922 { |
942 u_char *p, *file; | 923 u_char *p, *file; |
943 size_t len; | 924 size_t len; |
925 ngx_copy_file_t cf; | |
944 ngx_http_dav_copy_ctx_t *copy; | 926 ngx_http_dav_copy_ctx_t *copy; |
945 | 927 |
946 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | 928 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, |
947 "http copy file: \"%s\"", path->data); | 929 "http copy file: \"%s\"", path->data); |
948 | 930 |
959 (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1); | 941 (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1); |
960 | 942 |
961 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | 943 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, |
962 "http copy file to: \"%s\"", file); | 944 "http copy file to: \"%s\"", file); |
963 | 945 |
964 (void) ngx_http_dav_copy_file(ctx, path->data, file); | 946 cf.size = ctx->size; |
947 cf.buf_size = 0; | |
948 cf.access = ctx->access; | |
949 cf.time = ctx->mtime; | |
950 cf.log = ctx->log; | |
951 | |
952 (void) ngx_copy_file(path->data, file, &cf); | |
965 | 953 |
966 ngx_free(file); | 954 ngx_free(file); |
967 | 955 |
968 return NGX_OK; | 956 return NGX_OK; |
969 } | |
970 | |
971 | |
972 static ngx_int_t | |
973 ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from, u_char *to) | |
974 { | |
975 off_t size; | |
976 ssize_t n; | |
977 ngx_fd_t fd, cfd; | |
978 ngx_int_t rc; | |
979 u_char buf[NGX_HTTP_DAV_COPY_BLOCK]; | |
980 | |
981 fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); | |
982 | |
983 if (fd == NGX_INVALID_FILE) { | |
984 (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, | |
985 from); | |
986 return NGX_ERROR; | |
987 } | |
988 | |
989 cfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN, | |
990 ctx->access); | |
991 | |
992 rc = NGX_ERROR; | |
993 | |
994 if (cfd == NGX_INVALID_FILE) { | |
995 (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, to); | |
996 goto failed; | |
997 } | |
998 | |
999 for (size = ctx->size; size > 0; size -= n) { | |
1000 | |
1001 n = ngx_read_fd(fd, buf, NGX_HTTP_DAV_COPY_BLOCK); | |
1002 | |
1003 if (n == NGX_FILE_ERROR) { | |
1004 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, | |
1005 ngx_read_fd_n " \"%s\" failed", from); | |
1006 goto failed; | |
1007 } | |
1008 | |
1009 if (ngx_write_fd(cfd, buf, n) == NGX_FILE_ERROR) { | |
1010 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, | |
1011 ngx_write_fd_n " \"%s\" failed", to); | |
1012 goto failed; | |
1013 } | |
1014 } | |
1015 | |
1016 if (ngx_set_file_time(to, cfd, ctx->mtime) != NGX_OK) { | |
1017 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, | |
1018 ngx_set_file_time_n " \"%s\" failed", to); | |
1019 goto failed; | |
1020 } | |
1021 | |
1022 if (ngx_close_file(cfd) == NGX_FILE_ERROR) { | |
1023 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, | |
1024 ngx_close_file_n " \"%s\" failed", to); | |
1025 goto failed; | |
1026 } | |
1027 | |
1028 rc = NGX_OK; | |
1029 | |
1030 failed: | |
1031 | |
1032 if (ngx_close_file(fd) == NGX_FILE_ERROR) { | |
1033 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, | |
1034 ngx_close_file_n " \"%s\" failed", from); | |
1035 } | |
1036 | |
1037 return rc; | |
1038 } | 957 } |
1039 | 958 |
1040 | 959 |
1041 static ngx_int_t | 960 static ngx_int_t |
1042 ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt) | 961 ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt) |