Mercurial > hg > nginx
comparison src/http/modules/ngx_http_dav_module.c @ 3024:8101d9101ed8
allow cross device temporary files atomic copying:
*) ngx_copy_file()
*) delete ngx_ext_rename_file_t.log_rename_error and .rename_error fields
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Wed, 12 Aug 2009 12:05:33 +0000 |
parents | c7d57b539248 |
children | 524ba56ba9f7 |
comparison
equal
deleted
inserted
replaced
3023:7d5501988fe3 | 3024:8101d9101ed8 |
---|---|
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); |
247 ext.access = dlcf->access; | 245 ext.access = dlcf->access; |
248 ext.path_access = dlcf->access; | 246 ext.path_access = dlcf->access; |
249 ext.time = -1; | 247 ext.time = -1; |
250 ext.create_path = dlcf->create_full_put_path; | 248 ext.create_path = dlcf->create_full_put_path; |
251 ext.delete_file = 1; | 249 ext.delete_file = 1; |
252 ext.log_rename_error = 1; | |
253 ext.log = r->connection->log; | 250 ext.log = r->connection->log; |
254 | 251 |
255 if (r->headers_in.date) { | 252 if (r->headers_in.date) { |
256 date = ngx_http_parse_time(r->headers_in.date->value.data, | 253 date = ngx_http_parse_time(r->headers_in.date->value.data, |
257 r->headers_in.date->value.len); | 254 r->headers_in.date->value.len); |
518 ngx_err_t err; | 515 ngx_err_t err; |
519 ngx_int_t rc, depth; | 516 ngx_int_t rc, depth; |
520 ngx_uint_t overwrite, slash, dir; | 517 ngx_uint_t overwrite, slash, dir; |
521 ngx_str_t path, uri; | 518 ngx_str_t path, uri; |
522 ngx_tree_ctx_t tree; | 519 ngx_tree_ctx_t tree; |
520 ngx_copy_file_t cf; | |
523 ngx_file_info_t fi; | 521 ngx_file_info_t fi; |
524 ngx_table_elt_t *dest, *over; | 522 ngx_table_elt_t *dest, *over; |
525 ngx_ext_rename_file_t ext; | 523 ngx_ext_rename_file_t ext; |
526 ngx_http_dav_copy_ctx_t copy; | 524 ngx_http_dav_copy_ctx_t copy; |
527 ngx_http_dav_loc_conf_t *dlcf; | 525 ngx_http_dav_loc_conf_t *dlcf; |
789 ext.access = 0; | 787 ext.access = 0; |
790 ext.path_access = dlcf->access; | 788 ext.path_access = dlcf->access; |
791 ext.time = -1; | 789 ext.time = -1; |
792 ext.create_path = 1; | 790 ext.create_path = 1; |
793 ext.delete_file = 0; | 791 ext.delete_file = 0; |
794 ext.log_rename_error = 0; | |
795 ext.log = r->connection->log; | 792 ext.log = r->connection->log; |
796 | 793 |
797 if (ngx_ext_rename_file(&path, ©.path, &ext) == NGX_OK) { | 794 if (ngx_ext_rename_file(&path, ©.path, &ext) == NGX_OK) { |
798 return NGX_HTTP_NO_CONTENT; | 795 return NGX_HTTP_NO_CONTENT; |
799 } | 796 } |
800 | 797 |
801 if (ext.rename_error != NGX_EXDEV) { | 798 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 } | 799 } |
813 | 800 |
814 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); | 801 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); |
815 | 802 |
816 tree.size = ngx_file_size(&fi); | 803 cf.size = ngx_file_size(&fi); |
817 tree.mtime = ngx_file_mtime(&fi); | 804 cf.buf_size = 0; |
818 tree.access = dlcf->access; | 805 cf.access = dlcf->access; |
819 tree.log = r->connection->log; | 806 cf.time = ngx_file_mtime(&fi); |
820 | 807 cf.log = r->connection->log; |
821 if (ngx_http_dav_copy_file(&tree, path.data, copy.path.data) == NGX_OK) | 808 |
822 { | 809 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; | 810 return NGX_HTTP_NO_CONTENT; |
832 } | 811 } |
833 } | 812 } |
834 | 813 |
835 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 814 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
939 static ngx_int_t | 918 static ngx_int_t |
940 ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) | 919 ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) |
941 { | 920 { |
942 u_char *p, *file; | 921 u_char *p, *file; |
943 size_t len; | 922 size_t len; |
923 ngx_copy_file_t cf; | |
944 ngx_http_dav_copy_ctx_t *copy; | 924 ngx_http_dav_copy_ctx_t *copy; |
945 | 925 |
946 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | 926 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, |
947 "http copy file: \"%s\"", path->data); | 927 "http copy file: \"%s\"", path->data); |
948 | 928 |
959 (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1); | 939 (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1); |
960 | 940 |
961 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | 941 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, |
962 "http copy file to: \"%s\"", file); | 942 "http copy file to: \"%s\"", file); |
963 | 943 |
964 (void) ngx_http_dav_copy_file(ctx, path->data, file); | 944 cf.size = ctx->size; |
945 cf.buf_size = 0; | |
946 cf.access = ctx->access; | |
947 cf.time = ctx->mtime; | |
948 cf.log = ctx->log; | |
949 | |
950 (void) ngx_copy_file(path->data, file, &cf); | |
965 | 951 |
966 ngx_free(file); | 952 ngx_free(file); |
967 | 953 |
968 return NGX_OK; | 954 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 } | 955 } |
1039 | 956 |
1040 | 957 |
1041 static ngx_int_t | 958 static ngx_int_t |
1042 ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt) | 959 ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt) |