diff options
author | Igor Sysoev <igor@sysoev.ru> | 2003-04-11 16:01:14 +0000 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2003-04-11 16:01:14 +0000 |
commit | fd67586ef670a2ed181bb19d60619714f404aacc (patch) | |
tree | f13d1535caa6ff13d512d71ba8d1003c75f47cb8 /src | |
parent | cde2478a8540b19d4c9f5077fae23803889ed393 (diff) | |
download | nginx-fd67586ef670a2ed181bb19d60619714f404aacc.tar.gz nginx-fd67586ef670a2ed181bb19d60619714f404aacc.zip |
nginx-0.0.1-2003-04-11-20:01:14 import
Diffstat (limited to 'src')
-rw-r--r-- | src/core/ngx_file.c | 140 | ||||
-rw-r--r-- | src/core/ngx_file.h | 15 | ||||
-rw-r--r-- | src/core/ngx_hunk.h | 14 | ||||
-rw-r--r-- | src/http/modules/ngx_http_index_handler.c | 9 | ||||
-rw-r--r-- | src/http/modules/ngx_http_static_handler.c | 11 | ||||
-rw-r--r-- | src/http/modules/proxy/ngx_http_event_proxy_handler.c | 247 | ||||
-rw-r--r-- | src/http/modules/proxy/ngx_http_event_proxy_handler.h | 28 | ||||
-rw-r--r-- | src/http/ngx_http.h | 1 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 28 | ||||
-rw-r--r-- | src/os/unix/ngx_errno.h | 1 | ||||
-rw-r--r-- | src/os/unix/ngx_files.c | 65 | ||||
-rw-r--r-- | src/os/unix/ngx_files.h | 15 | ||||
-rw-r--r-- | src/os/unix/ngx_freebsd_write_chain.c | 2 | ||||
-rw-r--r-- | src/os/unix/ngx_recv_chain.c | 8 | ||||
-rw-r--r-- | src/os/win32/ngx_errno.h | 2 | ||||
-rw-r--r-- | src/os/win32/ngx_files.h | 14 |
16 files changed, 497 insertions, 103 deletions
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c new file mode 100644 index 000000000..b05372232 --- /dev/null +++ b/src/core/ngx_file.c @@ -0,0 +1,140 @@ + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_hunk.h> +#include <ngx_array.h> +#include <ngx_file.h> +#include <ngx_files.h> + + +int ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, + ngx_pool_t *pool, int num, int step, int persistent) +{ + int i; + ngx_err_t err; + + file->name.len = path->name.len + 1 + path->len + 10; + + ngx_test_null(file->name.data, ngx_palloc(pool, file->name.len + 1), + NGX_ERROR); + +#if 0 + for (i = 0; i < file->name.len; i++) { + file->name.data[i] = 'X'; + } +#endif + + ngx_memcpy(file->name.data, path->name.data, path->name.len); + + for ( ;; ) { + snprintf(file->name.data + path->name.len + 1 + path->len, 11, + "%010d", num); + + ngx_create_hashed_filename(file, path); + +#if 0 +#if (WIN32) + file->fd = CreateFile(file->name.data, + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + NULL, + CREATE_NEW, + persistent ? 0: + FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE, + NULL); +#else + file->fd = open(file->name.data, O_CREAT|O_EXCL|O_WRONLY, 0600); +#endif +#endif + + file->fd = ngx_open_tempfile(file->name.data, persistent); + + if (file->fd != NGX_INVALID_FILE) { + return NGX_OK; + } + + err = ngx_errno; + + if (err == NGX_EEXIST) { + num *= step; + continue; + } + + if (err != NGX_ENOENT +#if (WIN32_NEED_TEST) + && err != NGX_ENOTDIR +#endif + ) { + ngx_log_error(NGX_LOG_CRIT, file->log, err, + ngx_open_tempfile_n " \"%s\" failed", + file->name.data); + return NGX_ERROR; + } + + if (ngx_create_path(file, path) == NGX_ERROR) { + return NGX_ERROR; + } + } +} + + +void ngx_create_hashed_filename(ngx_file_t *file, ngx_path_t *path) +{ + int i, name, pos, level; + + name = file->name.len; + pos = path->name.len + 1; + + file->name.data[path->name.len + path->len] = '/'; + + for (i = 0; i < 3; i++) { + level = path->level[i]; + + if (level == 0) { + break; + } + + ngx_log_debug(file->log, "temp: %s" _ file->name.data); + + name -= level; + file->name.data[pos - 1] = '/'; + ngx_memcpy(&file->name.data[pos], &file->name.data[name], level); + pos += level + 1; + } + + ngx_log_debug(file->log, "temp: %s" _ file->name.data); +} + + +int ngx_create_path(ngx_file_t *file, ngx_path_t *path) +{ + int i, pos; + ngx_err_t err; + + pos = path->name.len; + + for (i = 0; i < 3; i++) { + if (path->level[i] == 0) { + break; + } + + pos += path->level[i] + 1; + + file->name.data[pos] = '\0'; + + ngx_log_debug(file->log, "temp: %s" _ file->name.data); + + if (ngx_mkdir(file->name.data) == NGX_FILE_ERROR) { + err = ngx_errno; + if (err != NGX_EEXIST) { + ngx_log_error(NGX_LOG_CRIT, file->log, err, + ngx_mkdir_n " \"%s\" failed", file->name.data); + return NGX_ERROR; + } + } + + file->name.data[pos] = '/'; + } + + return NGX_OK; +} diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h index d0151ad5a..d07384810 100644 --- a/src/core/ngx_file.h +++ b/src/core/ngx_file.h @@ -4,6 +4,7 @@ #include <ngx_file.h> #include <ngx_log.h> +#include <ngx_alloc.h> #include <ngx_string.h> typedef struct ngx_file_s ngx_file_t; @@ -21,4 +22,18 @@ struct ngx_file_s { }; +typedef struct { + ngx_str_t name; + int len; + int level[3]; +} ngx_path_t; + + +int ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, + ngx_pool_t *pool, int num, int step, int persistent); +void ngx_create_hashed_filename(ngx_file_t *file, ngx_path_t *path); +int ngx_create_path(ngx_file_t *file, ngx_path_t *path); + + + #endif /* _NGX_FILE_H_INCLUDED_ */ diff --git a/src/core/ngx_hunk.h b/src/core/ngx_hunk.h index 32e5c405e..de691f84d 100644 --- a/src/core/ngx_hunk.h +++ b/src/core/ngx_hunk.h @@ -34,20 +34,8 @@ - typedef struct ngx_hunk_s ngx_hunk_t; struct ngx_hunk_s { -#if 0 - union { - char *mem; /* start of current data */ - off_t file; - } pos; - union { - char *mem; /* end of current data */ - off_t file; - } last; -#endif - char *pos; char *last; off_t file_pos; @@ -60,10 +48,10 @@ struct ngx_hunk_s { char *post_end; /* end of post-allocated hunk */ int tag; ngx_file_t *file; + ngx_hunk_t *shadow; }; - typedef struct ngx_chain_s ngx_chain_t; struct ngx_chain_s { ngx_hunk_t *hunk; diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c index 2dbd6aa09..38683f7db 100644 --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -58,8 +58,9 @@ ngx_module_t ngx_http_index_module = { Try to open first index file before the test of the directory existence because the valid requests should be many more then invalid ones. If open() failed then stat() should be more quickly because some data - is already cached in the kernel. Besides Win32 has ERROR_PATH_NOT_FOUND - and Unix has ENOTDIR error (although it less helpfull). + is already cached in the kernel. + Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR) and + Unix has ENOTDIR error (although it less helpfull). */ int ngx_http_index_handler(ngx_http_request_t *r) @@ -110,11 +111,7 @@ int ngx_http_index_handler(ngx_http_request_t *r) ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err, "DEBUG: " ngx_open_file_n " %s failed", name); -#if (WIN32) - if (err == ERROR_PATH_NOT_FOUND) { -#else if (err == NGX_ENOTDIR) { -#endif r->path_not_found = 1; } else if (err == NGX_EACCES) { diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c index c8a014164..480e641a3 100644 --- a/src/http/modules/ngx_http_static_handler.c +++ b/src/http/modules/ngx_http_static_handler.c @@ -40,14 +40,15 @@ int ngx_http_static_handler(ngx_http_request_t *r) "ngx_http_static_handler: " ngx_open_file_n " %s failed", r->file.name.data); - if (err == NGX_ENOENT) + if (err == NGX_ENOENT) { return NGX_HTTP_NOT_FOUND; -#if (WIN32) - else if (err == ERROR_PATH_NOT_FOUND) + + } else if (err == NGX_ENOTDIR) { return NGX_HTTP_NOT_FOUND; -#endif - else + + } else { return NGX_HTTP_INTERNAL_SERVER_ERROR; + } } if (!r->file.info_valid) { diff --git a/src/http/modules/proxy/ngx_http_event_proxy_handler.c b/src/http/modules/proxy/ngx_http_event_proxy_handler.c index 1ffd21562..6977503ab 100644 --- a/src/http/modules/proxy/ngx_http_event_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_event_proxy_handler.c @@ -31,6 +31,9 @@ static int ngx_http_proxy_process_upstream_headers(ngx_http_proxy_ctx_t *p); static int ngx_http_proxy_process_upstream_header_line(ngx_http_proxy_ctx_t *p); +static int ngx_http_proxy_write_upstream_body(ngx_event_t *wev); + + static int ngx_http_proxy_read_response_body(ngx_event_t *ev); static int ngx_http_proxy_write_to_client(ngx_event_t *ev); @@ -39,6 +42,7 @@ static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx); static int ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int error); static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len); +static int ngx_http_proxy_init(ngx_pool_t *pool); static void *ngx_http_proxy_create_loc_conf(ngx_pool_t *pool); static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, @@ -82,7 +86,7 @@ ngx_module_t ngx_http_proxy_module = { &ngx_http_proxy_module_ctx, /* module context */ ngx_http_proxy_commands, /* module directives */ NGX_HTTP_MODULE_TYPE, /* module type */ - NULL /* init module */ + ngx_http_proxy_init /* init module */ }; @@ -179,7 +183,7 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r) } /* TODO: duplicate the hunks and chain if there is backend farm */ - p->out = chain; + p->request_hunks = chain; p->last_error = NGX_HTTP_BAD_GATEWAY; ngx_http_proxy_process_upstream(p, NULL); @@ -679,12 +683,12 @@ static int ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p) ngx_chain_t *chain; ngx_event_t *wev; - chain = ngx_write_chain(p->connection, p->out, 0); + chain = ngx_write_chain(p->connection, p->request_hunks, 0); if (chain == (ngx_chain_t *) -1) { return NGX_ERROR; } - p->out = chain; + p->request_hunks = chain; wev = p->connection->write; @@ -1026,12 +1030,11 @@ static int ngx_http_proxy_process_upstream_header_line(ngx_http_proxy_ctx_t *p) } -#if 0 - static int ngx_http_proxy_read_upstream_body(ngx_event_t *rev) { + int rc, n, size; ngx_hunk_t *h; - ngx_chain_t *chain, ce; + ngx_chain_t *chain, chain_entry, *ce, *te; ngx_connection_t *c; ngx_http_request_t *r; ngx_http_proxy_ctx_t *p; @@ -1041,9 +1044,9 @@ static int ngx_http_proxy_read_upstream_body(ngx_event_t *rev) p = (ngx_http_proxy_ctx_t *) ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); - ce.next = NULL; + chain_entry.next = NULL; - do { + for ( ;; ) { #if (USE_KQUEUE) @@ -1051,7 +1054,7 @@ static int ngx_http_proxy_read_upstream_body(ngx_event_t *rev) break; } -#elif (HAVE_KQUEUE) +#elif (HAVE_KQUEUE0) if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT && ev->eof && ev->available == 0) @@ -1063,6 +1066,7 @@ static int ngx_http_proxy_read_upstream_body(ngx_event_t *rev) if (p->free_hunks) { chain = p->free_hunks; + p->free_hunks = NULL; } else if (p->allocated < p->lcf->max_block_size) { ngx_test_null(h, @@ -1070,12 +1074,13 @@ static int ngx_http_proxy_read_upstream_body(ngx_event_t *rev) NGX_ERROR); p->allocated += p->block_size; - ce.hunk = h; - chain = &ce; + chain_entry.hunk = h; + chain = &chain_entry; } else { - if (p->temp_fd == NGX_INVALID_FILE) { - rc = ngx_create_temp_file(p->temp_file, r->cachable); + if (p->temp_file->fd == NGX_INVALID_FILE) { + rc = ngx_create_temp_file(p->temp_file, p->lcf->temp_path, + r->pool, 0, 2, r->cachable); if (rc != NGX_OK) { return rc; @@ -1089,69 +1094,168 @@ static int ngx_http_proxy_read_upstream_body(ngx_event_t *rev) } n = ngx_write_chain_to_file(p->temp_file, p->in_hunks, - p->temp_offset); + p->temp_offset, r->pool); if (n == NGX_ERROR) { return NGX_ERROR; } - ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), - NGX_ERROR); + for (ce = p->in_hunks; ce; ce = ce->next) { + ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), + NGX_ERROR); + + h->type = NGX_HUNK_FILE + |NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY|NGX_HUNK_RECYCLED; - h->type = NGX_HUNK_FILE - |NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP|NGX_HUNK_RECYCLED; + ce->hunk->shadow = h; + h->shadow = ce->hunk; - h->file_pos = p->temp_offset; - p->temp_offset += n; - h->file_last = p->temp_offset; + h->file_pos = p->temp_offset; + p->temp_offset += ce->hunk->last - ce->hunk->pos; + h->file_last = p->temp_offset; - h->file->fd = p->temp_file.fd; - h->file->log = p->log; + h->file->fd = p->temp_file->fd; + h->file->log = p->log; - h->pos = p->in_hunks->hunk->pos; - h->last = p->in_hunks->hunk->last; - h->start = p->in_hunks->hunk->start; - h->end = p->in_hunks->hunk->end; - h->pre_start = p->in_hunks->hunk->pre_start; - h->post_end = p->in_hunks->hunk->post_end; + h->pos = ce->hunk->pos; + h->last = ce->hunk->last; + h->start = ce->hunk->start; + h->end = ce->hunk->end; + h->pre_start = ce->hunk->pre_start; + h->post_end = ce->hunk->post_end; - ngx_add_hunk_to_chain(p->last_out_hunk, h, r->pool, NGX_ERROR); + ngx_test_null(te, ngx_create_chain_entry(r->pool), NGX_ERROR); + te->hunk = h; + te->next = NULL; - ce.hunk = p->in_hunks->next; - p->in_hunks = p->in_hunks->next; - chain = &ce; + if (p->last_out_hunk) { + p->last_out_hunk->next = te; + p->last_out_hunk = te; + + } else { + p->last_out_hunk = te; + } + } } n = ngx_recv_chain(c, chain); - h->last += n; - left = hunk->end - hunk->last; + if (n == NGX_ERROR) { + return NGX_ERROR; + } - } while (n > 0 && left == 0); + if (n == NGX_AGAIN) { + return NGX_AGAIN; + } + + if (n == 0) { + break; + } + + for (ce = chain; ce && n > 0; ce = ce->next) { + ngx_test_null(te, ngx_create_chain_entry(r->pool), NGX_ERROR); + te->hunk = ce->hunk; + te->next = NULL; + + if (p->last_in_hunk) { + p->last_in_hunk->next = te; + p->last_in_hunk = te; + + } else { + p->last_in_hunk = te; + } + + size = ce->hunk->end - ce->hunk->last; + + if (n >= size) { + n -= size; + ce->hunk->last = ce->hunk->end; + if (ce->hunk->shadow) { + ce->hunk->shadow->type &= ~(NGX_HUNK_TEMP + |NGX_HUNK_IN_MEMORY + |NGX_HUNK_RECYCLED); + ce->hunk->shadow->shadow = NULL; + + } + + continue; + } + + ce->hunk->last += n; + if (ce->hunk->shadow) { + ce->hunk->shadow->type &= ~(NGX_HUNK_TEMP + |NGX_HUNK_IN_MEMORY + |NGX_HUNK_RECYCLED); + ce->hunk->shadow->shadow = NULL; + } + + break; + } + + if (ce) { + ce->next = p->free_hunks; + p->free_hunks = ce; + break; + + return NGX_OK; + } + } if (p->out_hunks && p->request->connection->write->ready) { - ngx_http_proxy_write_upstream_body(p->request->connection->write); + return + ngx_http_proxy_write_upstream_body(p->request->connection->write); } + + return NGX_OK; } static int ngx_http_proxy_write_upstream_body(ngx_event_t *wev) { - while (out) { - output_filter(r, hunk); - if (again) - return - - if (hunk done) - remove from out - if (hunk is memory) - add it to free + int rc; + ngx_hunk_t *h, *sh; + ngx_chain_t *ce; + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_proxy_ctx_t *p; + + c = (ngx_connection_t *) wev->data; + r = (ngx_http_request_t *) c->data; + p = (ngx_http_proxy_ctx_t *) + ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); + + while (p->out_hunks) { + h = p->out_hunks->hunk; + rc = ngx_http_output_filter(r, h); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (rc == NGX_AGAIN || h->pos < h->last) { + return NGX_AGAIN; + } + + p->out_hunks = p->out_hunks->next; + + /* if the complete hunk has a shadow hunk + then add a shadow hunk to p->free_hunks chain */ + + sh = h->shadow; + + if (sh) { + sh->pos = sh->last = sh->start; + ngx_test_null(ce, ngx_create_chain_entry(r->pool), NGX_ERROR); + ce->hunk = sh; + ce->next = p->free_hunks; + p->free_hunks = ce; + } } -} + return NGX_OK; +} -#endif @@ -1482,9 +1586,36 @@ static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx) } +static int ngx_http_proxy_init(ngx_pool_t *pool) +{ + int i; + ngx_file_t file; + ngx_path_t path; + + file.log = pool->log; + + path.name.data = "temp"; + path.name.len = 4; + path.level[0] = 1; + path.level[1] = 2; + path.level[2] = 3; + path.len = 0; + + for (i = 0; i < 3; i++) { + if (path.level[i] == 0) { + break; + } + path.len += path.level[i] + 1; + } + + return ngx_create_temp_file(&file, &path, pool, 123456789, 2, 0); +} + + static void *ngx_http_proxy_create_loc_conf(ngx_pool_t *pool) { - ngx_http_proxy_loc_conf_t *conf; + int i; + ngx_http_proxy_loc_conf_t *conf; ngx_test_null(conf, ngx_pcalloc(pool, sizeof(ngx_http_proxy_loc_conf_t)), @@ -1498,6 +1629,22 @@ static void *ngx_http_proxy_create_loc_conf(ngx_pool_t *pool) conf->header_size = 1024; conf->block_size = 4096; conf->max_block_size = 32768; + + ngx_test_null(conf->temp_path, ngx_pcalloc(pool, sizeof(ngx_path_t)), NULL); + + conf->temp_path->name.data = "temp"; + conf->temp_path->name.len = 4; + conf->temp_path->level[0] = 1; + conf->temp_path->level[1] = 2; + conf->temp_path->level[2] = 3; + conf->temp_path->len = 0; + + for (i = 0; i < 3; i++) { + if (conf->temp_path->level[i] == 0) { + break; + } + conf->temp_path->len += conf->temp_path->level[i] + 1; + } /**/ return conf; diff --git a/src/http/modules/proxy/ngx_http_event_proxy_handler.h b/src/http/modules/proxy/ngx_http_event_proxy_handler.h index e1fb15412..92840d013 100644 --- a/src/http/modules/proxy/ngx_http_event_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_event_proxy_handler.h @@ -71,6 +71,9 @@ typedef struct { int block_size; int max_block_size; + ngx_path_t *temp_path; + int temp_file_warn; + int retry_500_error; } ngx_http_proxy_loc_conf_t; @@ -91,18 +94,33 @@ typedef struct { typedef struct ngx_http_proxy_ctx_s ngx_http_proxy_ctx_t; struct ngx_http_proxy_ctx_s { - ngx_chain_t *out; + ngx_chain_t *in_hunks; + ngx_chain_t *last_in_hunk; - int last_hunk; - ngx_array_t hunks; - int nhunks; + ngx_chain_t *out_hunks; + ngx_chain_t *last_out_hunk; - int hunk_n; + ngx_chain_t *free_hunks; + + ngx_chain_t *request_hunks; ngx_connection_t *connection; ngx_http_request_t *request; ngx_http_proxy_headers_in_t headers_in; + + int block_size; + int allocated; + + ngx_file_t *temp_file; + off_t temp_offset; + + int last_hunk; + ngx_array_t hunks; + int nhunks; + + int hunk_n; + ngx_http_proxy_upstream_url_t *upstream_url; ngx_http_proxy_upstreams_t *upstreams; int cur_upstream; diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h index 031d99064..6ae1e94ec 100644 --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -148,6 +148,7 @@ struct ngx_http_request_s { int path_err; unsigned proxy:1; + unsigned cachable:1; unsigned pipeline:1; unsigned keepalive:1; unsigned lingering_close:1; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 9acc866fb..4953971a8 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -370,12 +370,12 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data); err = ngx_errno; ngx_log_error(NGX_LOG_ERR, r->connection->log, err, "ngx_http_core_translate_handler: " - ngx_file_type_n " %s failed", r->file.name.data); + ngx_file_type_n " \"%s\" failed", r->file.name.data); if (err == NGX_ENOENT) { return NGX_HTTP_NOT_FOUND; - } else if (err == ERROR_PATH_NOT_FOUND) { + } else if (err == NGX_ENOTDIR) { return NGX_HTTP_NOT_FOUND; } else if (err == NGX_EACCES) { @@ -396,17 +396,14 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data); err = ngx_errno; ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, "ngx_http_core_handler: " - ngx_open_file_n " %s failed", r->file.name.data); + ngx_open_file_n " \"%s\" failed", r->file.name.data); if (err == NGX_ENOENT) { return NGX_HTTP_NOT_FOUND; -#if (WIN32) - } else if (err == ERROR_PATH_NOT_FOUND) { - return NGX_HTTP_NOT_FOUND; -#else + } else if (err == NGX_ENOTDIR) { return NGX_HTTP_NOT_FOUND; -#endif + } else if (err == NGX_EACCES) { return NGX_HTTP_FORBIDDEN; @@ -419,12 +416,13 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data); if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, "ngx_http_core_handler: " - ngx_stat_fd_n " %s failed", r->file.name.data); + ngx_stat_fd_n " \"%s\" failed", r->file.name.data); if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, "ngx_http_core_handler: " - ngx_close_file_n " %s failed", r->file.name.data); + ngx_close_file_n " \"%s\" failed", + r->file.name.data); } return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -441,7 +439,7 @@ ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data); if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, "ngx_http_core_handler: " - ngx_close_file_n " %s failed", r->file.name.data); + ngx_close_file_n " \"%s\" failed", r->file.name.data); } #endif @@ -487,12 +485,12 @@ static int ngx_http_core_index_handler(ngx_http_request_t *r) if (rc == NGX_HTTP_NOT_FOUND) { ngx_log_error(NGX_LOG_ERR, r->connection->log, r->path_err, - "%s is not found", r->path.data); + "\"%s\" is not found", r->path.data); } if (rc == NGX_HTTP_FORBIDDEN) { ngx_log_error(NGX_LOG_ERR, r->connection->log, r->path_err, - "%s is forbidden", r->path.data); + "\"%s\" is forbidden", r->path.data); } return rc; @@ -501,7 +499,7 @@ static int ngx_http_core_index_handler(ngx_http_request_t *r) r->path.data[r->path.len] = '\0'; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "directory index of %s is forbidden", r->path.data); + "directory index of \"%s\" is forbidden", r->path.data); return NGX_HTTP_FORBIDDEN; } @@ -550,7 +548,7 @@ int ngx_http_close_request(ngx_http_request_t *r, int error) if (r->file.fd != NGX_INVALID_FILE) { if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, - ngx_close_file_n " failed"); + ngx_close_file_n " \"%s\" failed", r->file.name.data); } } diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h index 391865724..3f6be6cbb 100644 --- a/src/os/unix/ngx_errno.h +++ b/src/os/unix/ngx_errno.h @@ -10,6 +10,7 @@ typedef int ngx_err_t; #define NGX_ENOENT ENOENT #define NGX_EINTR EINTR #define NGX_EACCES EACCES +#define NGX_EEXIST EEXIST #define NGX_ENOTDIR ENOTDIR #define NGX_EAGAIN EWOULDBLOCK #define NGX_EINPROGRESS EINPROGRESS diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c index 8aac3e27e..732cfdf22 100644 --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -1,7 +1,11 @@ #include <ngx_config.h> #include <ngx_core.h> +#include <ngx_hunk.h> +#include <ngx_array.h> #include <ngx_file.h> +#include <ngx_files.h> + ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset) { @@ -12,7 +16,7 @@ ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset) n = pread(file->fd, buf, size, offset); if (n == -1) { - ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno, "pread() failed"); + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pread() failed"); return NGX_ERROR; } @@ -29,12 +33,12 @@ ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset) n = pwrite(file->fd, buf, size, offset); if (n == -1) { - ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno, "pwrite() failed"); + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pwrite() failed"); return NGX_ERROR; } - if (n != size) { - ngx_log_error(NGX_LOG_ERR, file->log, 0, + if ((size_t) n != size) { + ngx_log_error(NGX_LOG_CRIT, file->log, 0, "pwrite() has written only %d of %d", n, size); return NGX_ERROR; } @@ -45,6 +49,59 @@ ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset) } +ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce, + off_t offset, ngx_pool_t *pool) +{ + size_t size; + ssize_t n; + struct iovec *iov; + ngx_err_t err; + ngx_array_t io; + + /* use pwrite() if there's the only hunk in a chain */ + + if (ce->next == NULL) { + return ngx_write_file(file, ce->hunk->pos, + ce->hunk->last - ce->hunk->pos, offset); + } + + ngx_init_array(io, pool, 10, sizeof(struct iovec), NGX_ERROR); + size = 0; + + while (ce) { + ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR); + iov->iov_base = ce->hunk->pos; + iov->iov_len = ce->hunk->last - ce->hunk->pos; + size += ce->hunk->last - ce->hunk->pos; + ce = ce->next; + } + + if (lseek(file->fd, offset, SEEK_SET) == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed"); + return NGX_ERROR; + } + + n = writev(file->fd, (struct iovec *) io.elts, io.nelts); + + ngx_destroy_array(&io); + + if (n == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "writev() failed"); + return NGX_ERROR; + } + + if ((size_t) n != size) { + ngx_log_error(NGX_LOG_CRIT, file->log, 0, + "writev() has written only %d of %d", n, size); + return NGX_ERROR; + } + + file->offset += n; + + return n; +} + + #if 0 ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset) diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h index d35382f6c..92448cc0f 100644 --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -5,6 +5,8 @@ #include <ngx_config.h> #include <ngx_types.h> +#include <ngx_alloc.h> +#include <ngx_hunk.h> #include <ngx_file.h> @@ -19,11 +21,24 @@ #define ngx_close_file close #define ngx_close_file_n "close()" +#define ngx_open_tempfile(name, persistent) \ + open(name, O_CREAT|O_EXCL|O_WRONLY, 0600) +#define ngx_open_tempfile_n "open()" + ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset); #define ngx_read_file_n "read()" #define NGX_FILE_RDONLY O_RDONLY +ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset); + +ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce, + off_t offset, ngx_pool_t *pool); + + +#define ngx_mkdir(name) mkdir(name, 0700) +#define ngx_mkdir_n "mkdir()" + #define ngx_file_type(file, sb) stat(file, sb) #define ngx_file_type_n "stat()" diff --git a/src/os/unix/ngx_freebsd_write_chain.c b/src/os/unix/ngx_freebsd_write_chain.c index 1c163779d..09c0120db 100644 --- a/src/os/unix/ngx_freebsd_write_chain.c +++ b/src/os/unix/ngx_freebsd_write_chain.c @@ -140,7 +140,7 @@ ngx_chain_t *ngx_freebsd_write_chain(ngx_connection_t *c, ngx_chain_t *in) c->sent += sent; - for (ce = in; ce; ce = ce->next) { + for (ce = in; ce && sent > 0; ce = ce->next) { if (ce->hunk->type & NGX_HUNK_IN_MEMORY) { size = ce->hunk->last - ce->hunk->pos; diff --git a/src/os/unix/ngx_recv_chain.c b/src/os/unix/ngx_recv_chain.c index 221f306cd..18054e783 100644 --- a/src/os/unix/ngx_recv_chain.c +++ b/src/os/unix/ngx_recv_chain.c @@ -8,10 +8,10 @@ ssize_t ngx_recv_chain(ngx_connection_t *c, ngx_chain_t *ce) { - int n; - struct iovec *iov; - ngx_err_t err; - ngx_array_t io; + ssize_t n; + struct iovec *iov; + ngx_err_t err; + ngx_array_t io; ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_ERROR); diff --git a/src/os/win32/ngx_errno.h b/src/os/win32/ngx_errno.h index ec6c7cc4e..2378811fe 100644 --- a/src/os/win32/ngx_errno.h +++ b/src/os/win32/ngx_errno.h @@ -12,6 +12,8 @@ typedef DWORD ngx_err_t; #define NGX_ENOENT ERROR_FILE_NOT_FOUND #define NGX_EACCES ERROR_ACCESS_DENIED +#define NGX_EEXIST ERROR_FILE_EXISTS +#define NGX_ENOTDIR ERROR_PATH_NOT_FOUND #define NGX_EAGAIN WSAEWOULDBLOCK #define NGX_EINPROGRESS WSAEINPROGRESS #define NGX_EADDRINUSE WSAEADDRINUSE diff --git a/src/os/win32/ngx_files.h b/src/os/win32/ngx_files.h index a8970a2fd..1cf981089 100644 --- a/src/os/win32/ngx_files.h +++ b/src/os/win32/ngx_files.h @@ -26,6 +26,17 @@ NULL, OPEN_EXISTING, 0, NULL) */ +#define ngx_open_tempfile(name, persistent) \ + CreateFile(name, \ + GENERIC_READ|GENERIC_WRITE, \ + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, \ + NULL, \ + CREATE_NEW, \ + persistent ? 0: \ + FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE, \ + NULL); + + #define ngx_open_file_n "CreateFile()" #define NGX_FILE_RDONLY GENERIC_READ @@ -33,6 +44,9 @@ #define ngx_close_file CloseHandle #define ngx_close_file_n "CloseHandle()" +#define ngx_mkdir(name) CreateDirectory(name, NULL) +#define ngx_mkdir_n "CreateDirectory()" + int ngx_file_type(char *filename, ngx_file_info_t *fi); #define ngx_file_type_n "GetFileAttributes" |