do not delete target until all tests will be done,
fix single file COPY/MOVE
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index d94422f..33eb301 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -51,7 +51,10 @@
static ngx_int_t ngx_http_dav_copy_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path);
static ngx_int_t ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx,
ngx_str_t *path);
-static ngx_int_t ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, ngx_str_t *path);
+static ngx_int_t ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx,
+ ngx_str_t *path);
+static ngx_int_t ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from,
+ u_char *to);
static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt);
static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err,
@@ -582,12 +585,13 @@
size_t len, root;
ngx_err_t err;
ngx_int_t rc, depth;
- ngx_uint_t overwrite, slash;
+ ngx_uint_t overwrite, slash, dir;
ngx_str_t path, uri;
ngx_tree_ctx_t tree;
ngx_file_info_t fi;
ngx_table_elt_t *host, *dest, *over;
ngx_http_dav_copy_ctx_t copy;
+ ngx_http_dav_loc_conf_t *dlcf;
if (r->headers_in.content_length_n > 0) {
return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
@@ -754,6 +758,9 @@
/* destination does not exist */
+ overwrite = 0;
+ dir = 0;
+
} else {
/* destination exists */
@@ -771,14 +778,7 @@
return NGX_HTTP_PRECONDITION_FAILED;
}
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http delete: \"%s\"", copy.path.data);
-
- rc = ngx_http_dav_delete_path(r, ©.path, ngx_is_dir(&fi));
-
- if (rc != NGX_OK) {
- return rc;
- }
+ dir = ngx_is_dir(&fi);
}
if (ngx_file_info(path.data, &fi) == -1) {
@@ -787,14 +787,28 @@
path.data);
}
-
if (ngx_is_dir(&fi)) {
if (r->uri.data[r->uri.len - 1] != '/') {
- /* TODO: 301 */
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "\"%V\" is collection", &r->uri);
return NGX_HTTP_BAD_REQUEST;
}
+ if (overwrite) {
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http delete: \"%s\"", copy.path.data);
+
+ rc = ngx_http_dav_delete_path(r, ©.path, dir);
+
+ if (rc != NGX_OK) {
+ return rc;
+ }
+ }
+ }
+
+ if (ngx_is_dir(&fi)) {
+
path.len -= 2; /* omit "/\0" */
if (r->method == NGX_HTTP_MOVE) {
@@ -814,7 +828,7 @@
copy.len = path.len;
tree.init_handler = NULL;
- tree.file_handler = ngx_http_dav_copy_file;
+ tree.file_handler = ngx_http_dav_copy_tree_file;
tree.pre_tree_handler = ngx_http_dav_copy_dir;
tree.post_tree_handler = ngx_http_dav_copy_dir_time;
tree.spec_handler = ngx_http_dav_noop;
@@ -837,21 +851,21 @@
} else {
- if (dest->value.data[dest->value.len - 1] == '/') {
- return NGX_HTTP_BAD_REQUEST;
- }
-
if (r->method == NGX_HTTP_MOVE) {
if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) {
return NGX_HTTP_NO_CONTENT;
}
}
- tree.data = ©
+ dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
+
+ tree.size = ngx_file_size(&fi);
+ tree.mtime = ngx_file_mtime(&fi);
+ tree.access = dlcf->access;
tree.log = r->connection->log;
- if (ngx_http_dav_copy_file(&tree, &path) != NGX_FILE_ERROR) {
-
+ if (ngx_http_dav_copy_file(&tree, path.data, copy.path.data) == NGX_OK)
+ {
if (r->method == NGX_HTTP_MOVE) {
rc = ngx_http_dav_delete_path(r, &path, 0);
@@ -969,15 +983,11 @@
static ngx_int_t
-ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, ngx_str_t *path)
+ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path)
{
u_char *p, *file;
size_t len;
- off_t size;
- ssize_t n;
- ngx_fd_t fd, copy_fd;
ngx_http_dav_copy_ctx_t *copy;
- u_char buf[NGX_HTTP_DAV_COPY_BLOCK];
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
"http copy file: \"%s\"", path->data);
@@ -997,21 +1007,39 @@
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
"http copy file to: \"%s\"", file);
- fd = ngx_open_file(path->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
+ (void) ngx_http_dav_copy_file(ctx, path->data, file);
+
+ ngx_free(file);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from, u_char *to)
+{
+ off_t size;
+ ssize_t n;
+ ngx_fd_t fd, cfd;
+ ngx_int_t rc;
+ u_char buf[NGX_HTTP_DAV_COPY_BLOCK];
+
+ fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
if (fd == NGX_INVALID_FILE) {
(void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n,
- path->data);
- goto failed;
+ from);
+ return NGX_ERROR;
}
- copy_fd = ngx_open_file(file, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN,
- ctx->access);
+ cfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN,
+ ctx->access);
- if (copy_fd == NGX_INVALID_FILE) {
- (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n,
- file);
- goto copy_failed;
+ rc = NGX_ERROR;
+
+ if (cfd == NGX_INVALID_FILE) {
+ (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, to);
+ goto failed;
}
for (size = ctx->size; size > 0; size -= n) {
@@ -1020,38 +1048,39 @@
if (n == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_read_fd_n " \"%s\" failed", path->data);
- break;
+ ngx_read_fd_n " \"%s\" failed", from);
+ goto failed;
}
- if (ngx_write_fd(copy_fd, buf, n) == NGX_FILE_ERROR) {
+ if (ngx_write_fd(cfd, buf, n) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_write_fd_n " \"%s\" failed", file);
+ ngx_write_fd_n " \"%s\" failed", to);
+ goto failed;
}
}
- if (ngx_set_file_time(file, copy_fd, ctx->mtime) != NGX_OK) {
+ if (ngx_set_file_time(to, cfd, ctx->mtime) != NGX_OK) {
ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_set_file_time_n " \"%s\" failed", file);
+ ngx_set_file_time_n " \"%s\" failed", to);
+ goto failed;
}
- if (ngx_close_file(copy_fd) == NGX_FILE_ERROR) {
+ if (ngx_close_file(cfd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", file);
+ ngx_close_file_n " \"%s\" failed", to);
+ goto failed;
}
-copy_failed:
-
- if (ngx_close_file(fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", path->data);
- }
+ rc = NGX_OK;
failed:
- ngx_free(file);
+ if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", from);
+ }
- return NGX_OK;
+ return rc;
}