00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "ngx_http_filesync.h"
00023
00024 static ngx_buf_t*
00025 ngx_http_filesync_get_buf(ngx_http_request_t *r, ngx_int_t max_size);
00026 static ngx_int_t
00027 ngx_http_filesync_read(ngx_http_request_t *r, ngx_buf_t *src, ngx_buf_t *dst);
00028
00037 ngx_int_t
00038 ngx_http_filesync_get(ngx_http_request_t *r, ngx_str_t *uri, ngx_chain_t **res)
00039 {
00040 u_char *last;
00041 size_t root;
00042 ngx_str_t r_path;
00043 ngx_str_t path;
00044 ngx_int_t rc;
00045 ngx_log_t *log;
00046 ngx_buf_t *b;
00047 ngx_chain_t out, *cl, *cl_end;
00048 ngx_open_file_info_t of;
00049 ngx_http_core_loc_conf_t *clcf;
00050 ngx_file_t *file;
00051 u_char *tmp;
00052
00053
00054 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->pool->log, 0,
00055 "[filesynch_get]");
00056
00057 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->pool->log, 0,
00058 "[filesynch_get] get URI: %s", uri->data);
00059
00060 if (uri->data[uri->len - 1] == '/') {
00061 return NGX_DECLINED;
00062 }
00063
00064 log = r->connection->log;
00065
00066
00067
00068
00069
00070
00071 last = ngx_http_map_uri_to_path(r, &r_path, &root, 0);
00072 if (last == NULL) {
00073 return NGX_HTTP_INTERNAL_SERVER_ERROR;
00074 }
00075
00076 r_path.len = last - r_path.data;
00077
00078 last--;
00079 while(*last != '/')
00080 last--;
00081
00082 r_path.len = last - r_path.data + 1;
00083
00084 path.data = ngx_pcalloc(r->pool, sizeof(u_char)*(r_path.len + uri->len + 1));
00085 path.len = r_path.len + uri->len + 1;
00086
00087 tmp = ngx_cpystrn(path.data, r_path.data, r_path.len + 1);
00088 tmp = ngx_cpystrn(tmp, uri->data, uri->len + 1);
00089
00090 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
00091 "[filesynch_get] http filename \"%s\"", path.data);
00092
00093 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
00094
00095 ngx_memzero(&of, sizeof(ngx_open_file_info_t));
00096
00097 of.directio = clcf->directio;
00098 of.valid = clcf->open_file_cache_valid;
00099 of.min_uses = clcf->open_file_cache_min_uses;
00100 of.errors = clcf->open_file_cache_errors;
00101 of.events = clcf->open_file_cache_events;
00102
00103 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
00104 != NGX_OK)
00105 {
00106 switch (of.err) {
00107 case 0:
00108 return NGX_HTTP_INTERNAL_SERVER_ERROR;
00109 case NGX_ENOENT:
00110 case NGX_ENOTDIR:
00111 case NGX_ENAMETOOLONG:
00112
00113 rc = NGX_HTTP_NOT_FOUND;
00114 break;
00115 case NGX_EACCES:
00116
00117 rc = NGX_HTTP_FORBIDDEN;
00118 break;
00119
00120 default:
00121
00122 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
00123 break;
00124 }
00125
00126 if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
00127 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, of.err,
00128 "[filesynch_get] %s \"%s\" failed", of.failed, path.data);
00129 }
00130
00131 return rc;
00132 }
00133
00134 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
00135 "[filesynch_get] http static fd: %d", of.fd);
00136
00137 if (of.is_dir) {
00138 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0,
00139 "[filesynch_get] http dir");
00140
00141 return NGX_HTTP_MOVED_PERMANENTLY;
00142 }
00143
00144 #if !(NGX_WIN32)
00145
00146 if (!of.is_file) {
00147 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, ngx_errno,
00148 "[filesynch_get] \"%s\" is not a regular file", path.data);
00149
00150 return NGX_HTTP_NOT_FOUND;
00151 }
00152
00153 #endif
00154
00155
00156
00157 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
00158 if (b == NULL) {
00159 return NGX_HTTP_INTERNAL_SERVER_ERROR;
00160 }
00161
00162 file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
00163 if( file == NULL ) {
00164 return NGX_HTTP_INTERNAL_SERVER_ERROR;
00165 }
00166
00167 b->file = file;
00168 b->file_pos = 0;
00169 b->file_last = of.size;
00170
00171 b->in_file = b->file_last ? 1: 0;
00172 b->last_buf = (r == r->main) ? 1: 0;
00173 b->last_in_chain = 1;
00174
00175 b->file->fd = of.fd;
00176 b->file->name = path;
00177 b->file->log = log;
00178 b->file->directio = of.is_directio;
00179
00180 out.buf = b;
00181 out.next = NULL;
00182
00183 cl = cl_end = NULL;
00184 *res = NULL;
00185 while( ngx_buf_size(out.buf) > 0 ) {
00186
00187 b = ngx_http_filesync_get_buf(r, ngx_buf_size(out.buf));
00188 if( b == NULL ) {
00189 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0,
00190 "[filesynch_get] ngx_http_filesync_get_buf fail");
00191 return NGX_HTTP_INTERNAL_SERVER_ERROR;
00192 }
00193
00194
00195 rc = ngx_http_filesync_read(r, out.buf, b);
00196
00197 if( rc != NGX_OK ) {
00198 return rc;
00199 }
00200
00201 if( cl == NULL ) {
00202 cl = cl_end = ngx_alloc_chain_link(r->pool);
00203 }
00204 else {
00205 cl_end->next = ngx_alloc_chain_link(r->pool);
00206 cl_end = cl_end->next;
00207 }
00208 cl_end->buf = b;
00209 cl_end->next = NULL;
00210 }
00211 *res = cl;
00212
00213
00214
00215 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0,
00216 "[filesynch_get] done");
00217
00218 return NGX_OK;
00219 }
00220
00229 static ngx_int_t
00230 ngx_http_filesync_read(ngx_http_request_t *r, ngx_buf_t *src, ngx_buf_t *dst)
00231 {
00232 off_t size;
00233 ssize_t n;
00234
00235 size = ngx_buf_size(src);
00236
00237 if (size > dst->end - dst->pos) {
00238 size = dst->end - dst->pos;
00239 }
00240
00241 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->pool->log, 0,
00242 "[filesync_read] reading... (%d)", size);
00243 n = ngx_read_file(src->file, dst->pos, (size_t) size, src->file_pos);
00244
00245 if (n == NGX_ERROR) {
00246 return (ngx_int_t) n;
00247 }
00248
00249 #if (NGX_FILE_AIO_READ)
00250 if (n == NGX_AGAIN) {
00251 return (ngx_int_t) n;
00252 }
00253 #endif
00254
00255 if (n != size) {
00256 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->pool->log, 0,
00257 "[filesync_read] read only %z of %O from \"%s\"", n, size, src->file->name.data);
00258 if (n == 0) {
00259 return NGX_ERROR;
00260 }
00261 }
00262
00263 dst->last += n;
00264 dst->in_file = 0;
00265 src->file_pos += n;
00266
00267 if (src->file_pos == src->file_last) {
00268 dst->flush = src->flush;
00269 dst->last_buf = src->last_buf;
00270 dst->last_in_chain = src->last_in_chain;
00271 }
00272
00273 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->pool->log, 0,
00274 "[filesync_read] ok");
00275
00276 return NGX_OK;
00277 }
00278
00285 static ngx_buf_t*
00286 ngx_http_filesync_get_buf(ngx_http_request_t *r, ngx_int_t max_size)
00287 {
00288 return ngx_create_temp_buf(r->pool,
00289 max_size > NGX_HTTP_FILESYNC_MAX_BUF ? NGX_HTTP_FILESYNC_MAX_BUF : max_size);
00290 }
00291
00292