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, &copy.path, &ext) == NGX_OK) { 796 if (ngx_ext_rename_file(&path, &copy.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)