Mercurial > hg > nginx-quic
annotate src/core/ngx_open_file_cache.c @ 4964:2464ccebdb52
Upstream: fixed SIGSEGV with the "if" directive.
Configuration like
location / {
set $true 1;
if ($true) {
proxy_pass http://backend;
}
if ($true) {
# nothing
}
}
resulted in segmentation fault due to NULL pointer dereference as the
upstream configuration wasn't initialized in an implicit location created
by the last if(), but the r->content_handler was set due to first if().
Instead of committing a suicide by dereferencing a NULL pointer, return
500 (Internal Server Error) in such cases, i.e. if uscf is NULL. Better
fix would be to avoid such cases by fixing the "if" directive handling,
but it's out of scope of this patch.
Prodded by Piotr Sikora.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 13 Dec 2012 16:05:59 +0000 |
parents | 95ab6658654a |
children | 6b479db5b52b |
rev | line source |
---|---|
1453 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
1453 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_event.h> | |
11 | |
12 | |
13 /* | |
14 * open file cache caches | |
15 * open file handles with stat() info; | |
16 * directories stat() info; | |
17 * files and directories errors: not found, access denied, etc. | |
18 */ | |
19 | |
20 | |
3178 | 21 #define NGX_MIN_READ_AHEAD (128 * 1024) |
22 | |
23 | |
1453 | 24 static void ngx_open_file_cache_cleanup(void *data); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
25 #if (NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
26 static ngx_fd_t ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
27 ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
28 #endif |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
29 static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name, |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
30 ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
31 ngx_int_t access, ngx_log_t *log); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
32 static ngx_int_t ngx_file_info_wrapper(ngx_str_t *name, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
33 ngx_open_file_info_t *of, ngx_file_info_t *fi, ngx_log_t *log); |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
34 static ngx_int_t ngx_open_and_stat_file(ngx_str_t *name, |
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
35 ngx_open_file_info_t *of, ngx_log_t *log); |
1775 | 36 static void ngx_open_file_add_event(ngx_open_file_cache_t *cache, |
37 ngx_cached_open_file_t *file, ngx_open_file_info_t *of, ngx_log_t *log); | |
1453 | 38 static void ngx_open_file_cleanup(void *data); |
39 static void ngx_close_cached_file(ngx_open_file_cache_t *cache, | |
1772 | 40 ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_log_t *log); |
1775 | 41 static void ngx_open_file_del_event(ngx_cached_open_file_t *file); |
1453 | 42 static void ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, |
43 ngx_uint_t n, ngx_log_t *log); | |
44 static void ngx_open_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp, | |
45 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); | |
1775 | 46 static ngx_cached_open_file_t * |
47 ngx_open_file_lookup(ngx_open_file_cache_t *cache, ngx_str_t *name, | |
48 uint32_t hash); | |
1453 | 49 static void ngx_open_file_cache_remove(ngx_event_t *ev); |
50 | |
51 | |
52 ngx_open_file_cache_t * | |
53 ngx_open_file_cache_init(ngx_pool_t *pool, ngx_uint_t max, time_t inactive) | |
54 { | |
55 ngx_pool_cleanup_t *cln; | |
56 ngx_open_file_cache_t *cache; | |
57 | |
58 cache = ngx_palloc(pool, sizeof(ngx_open_file_cache_t)); | |
59 if (cache == NULL) { | |
60 return NULL; | |
61 } | |
62 | |
1761 | 63 ngx_rbtree_init(&cache->rbtree, &cache->sentinel, |
1743
4fc402c3ec73
optimize rbtree initialization and insert
Igor Sysoev <igor@sysoev.ru>
parents:
1458
diff
changeset
|
64 ngx_open_file_cache_rbtree_insert_value); |
1453 | 65 |
1765 | 66 ngx_queue_init(&cache->expire_queue); |
67 | |
1453 | 68 cache->current = 0; |
69 cache->max = max; | |
70 cache->inactive = inactive; | |
71 | |
72 cln = ngx_pool_cleanup_add(pool, 0); | |
73 if (cln == NULL) { | |
74 return NULL; | |
75 } | |
76 | |
77 cln->handler = ngx_open_file_cache_cleanup; | |
78 cln->data = cache; | |
79 | |
80 return cache; | |
81 } | |
82 | |
83 | |
84 static void | |
85 ngx_open_file_cache_cleanup(void *data) | |
86 { | |
87 ngx_open_file_cache_t *cache = data; | |
88 | |
1765 | 89 ngx_queue_t *q; |
1453 | 90 ngx_cached_open_file_t *file; |
91 | |
92 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, | |
93 "open file cache cleanup"); | |
94 | |
95 for ( ;; ) { | |
96 | |
1765 | 97 if (ngx_queue_empty(&cache->expire_queue)) { |
1766 | 98 break; |
1453 | 99 } |
100 | |
1765 | 101 q = ngx_queue_last(&cache->expire_queue); |
102 | |
103 file = ngx_queue_data(q, ngx_cached_open_file_t, queue); | |
104 | |
105 ngx_queue_remove(q); | |
1453 | 106 |
107 ngx_rbtree_delete(&cache->rbtree, &file->node); | |
108 | |
109 cache->current--; | |
110 | |
111 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, | |
112 "delete cached open file: %s", file->name); | |
113 | |
114 if (!file->err && !file->is_dir) { | |
115 file->close = 1; | |
116 file->count = 0; | |
1772 | 117 ngx_close_cached_file(cache, file, 0, ngx_cycle->log); |
1453 | 118 |
119 } else { | |
120 ngx_free(file->name); | |
121 ngx_free(file); | |
122 } | |
123 } | |
124 | |
125 if (cache->current) { | |
126 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, | |
127 "%d items still leave in open file cache", | |
128 cache->current); | |
129 } | |
130 | |
131 if (cache->rbtree.root != cache->rbtree.sentinel) { | |
132 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, | |
133 "rbtree still is not empty in open file cache"); | |
134 | |
135 } | |
136 } | |
137 | |
138 | |
139 ngx_int_t | |
140 ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name, | |
141 ngx_open_file_info_t *of, ngx_pool_t *pool) | |
142 { | |
143 time_t now; | |
144 uint32_t hash; | |
145 ngx_int_t rc; | |
2756
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
146 ngx_file_info_t fi; |
1453 | 147 ngx_pool_cleanup_t *cln; |
148 ngx_cached_open_file_t *file; | |
149 ngx_pool_cleanup_file_t *clnf; | |
150 ngx_open_file_cache_cleanup_t *ofcln; | |
151 | |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
152 of->fd = NGX_INVALID_FILE; |
1453 | 153 of->err = 0; |
154 | |
155 if (cache == NULL) { | |
156 | |
2756
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
157 if (of->test_only) { |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
158 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
159 if (ngx_file_info_wrapper(name, of, &fi, pool->log) |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
160 == NGX_FILE_ERROR) |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
161 { |
2756
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
162 return NGX_ERROR; |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
163 } |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
164 |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
165 of->uniq = ngx_file_uniq(&fi); |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
166 of->mtime = ngx_file_mtime(&fi); |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
167 of->size = ngx_file_size(&fi); |
3899
e7cd13b7f759
Use more precise stat.st_blocks to account cache size on Unix
Igor Sysoev <igor@sysoev.ru>
parents:
3497
diff
changeset
|
168 of->fs_size = ngx_file_fs_size(&fi); |
2756
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
169 of->is_dir = ngx_is_dir(&fi); |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
170 of->is_file = ngx_is_file(&fi); |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
171 of->is_link = ngx_is_link(&fi); |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
172 of->is_exec = ngx_is_exec(&fi); |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
173 |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
174 return NGX_OK; |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
175 } |
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2629
diff
changeset
|
176 |
1453 | 177 cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t)); |
178 if (cln == NULL) { | |
179 return NGX_ERROR; | |
180 } | |
181 | |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
182 rc = ngx_open_and_stat_file(name, of, pool->log); |
1453 | 183 |
184 if (rc == NGX_OK && !of->is_dir) { | |
185 cln->handler = ngx_pool_cleanup_file; | |
186 clnf = cln->data; | |
187 | |
188 clnf->fd = of->fd; | |
189 clnf->name = name->data; | |
190 clnf->log = pool->log; | |
191 } | |
192 | |
193 return rc; | |
194 } | |
195 | |
196 cln = ngx_pool_cleanup_add(pool, sizeof(ngx_open_file_cache_cleanup_t)); | |
197 if (cln == NULL) { | |
198 return NGX_ERROR; | |
199 } | |
200 | |
201 now = ngx_time(); | |
202 | |
1775 | 203 hash = ngx_crc32_long(name->data, name->len); |
204 | |
205 file = ngx_open_file_lookup(cache, name, hash); | |
206 | |
207 if (file) { | |
208 | |
209 file->uses++; | |
210 | |
1987 | 211 ngx_queue_remove(&file->queue); |
212 | |
1775 | 213 if (file->fd == NGX_INVALID_FILE && file->err == 0 && !file->is_dir) { |
214 | |
215 /* file was not used often enough to keep open */ | |
216 | |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
217 rc = ngx_open_and_stat_file(name, of, pool->log); |
1453 | 218 |
1775 | 219 if (rc != NGX_OK && (of->err == 0 || !of->errors)) { |
220 goto failed; | |
221 } | |
222 | |
223 goto add_event; | |
1453 | 224 } |
225 | |
2070 | 226 if (file->use_event |
2063
67a29af877ed
initialize of.uniq in ngx_open_cached_file()
Igor Sysoev <igor@sysoev.ru>
parents:
2006
diff
changeset
|
227 || (file->event == NULL |
67a29af877ed
initialize of.uniq in ngx_open_cached_file()
Igor Sysoev <igor@sysoev.ru>
parents:
2006
diff
changeset
|
228 && (of->uniq == 0 || of->uniq == file->uniq) |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
229 && now - file->created < of->valid |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
230 #if (NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
231 && of->disable_symlinks == file->disable_symlinks |
4493
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
232 && of->disable_symlinks_from == file->disable_symlinks_from |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
233 #endif |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
234 )) |
1775 | 235 { |
236 if (file->err == 0) { | |
1772 | 237 |
1775 | 238 of->fd = file->fd; |
239 of->uniq = file->uniq; | |
240 of->mtime = file->mtime; | |
241 of->size = file->size; | |
1453 | 242 |
1775 | 243 of->is_dir = file->is_dir; |
244 of->is_file = file->is_file; | |
245 of->is_link = file->is_link; | |
246 of->is_exec = file->is_exec; | |
2246
987831d73bd8
cache directio flag in open file cache
Igor Sysoev <igor@sysoev.ru>
parents:
2231
diff
changeset
|
247 of->is_directio = file->is_directio; |
1453 | 248 |
1775 | 249 if (!file->is_dir) { |
250 file->count++; | |
251 ngx_open_file_add_event(cache, file, of, pool->log); | |
1453 | 252 } |
253 | |
1775 | 254 } else { |
255 of->err = file->err; | |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
256 #if (NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
257 of->failed = file->disable_symlinks ? ngx_openat_file_n |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
258 : ngx_open_file_n; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
259 #else |
2783
87c088e6956a
set of.failed for cached error, the bug has been introduced in r2757
Igor Sysoev <igor@sysoev.ru>
parents:
2782
diff
changeset
|
260 of->failed = ngx_open_file_n; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
261 #endif |
1775 | 262 } |
263 | |
264 goto found; | |
265 } | |
266 | |
267 ngx_log_debug4(NGX_LOG_DEBUG_CORE, pool->log, 0, | |
268 "retest open file: %s, fd:%d, c:%d, e:%d", | |
269 file->name, file->fd, file->count, file->err); | |
1453 | 270 |
1775 | 271 if (file->is_dir) { |
272 | |
273 /* | |
274 * chances that directory became file are very small | |
275 * so test_dir flag allows to use a single syscall | |
276 * in ngx_file_info() instead of three syscalls | |
277 */ | |
278 | |
279 of->test_dir = 1; | |
280 } | |
281 | |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
282 of->fd = file->fd; |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
283 of->uniq = file->uniq; |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
284 |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
285 rc = ngx_open_and_stat_file(name, of, pool->log); |
1453 | 286 |
1775 | 287 if (rc != NGX_OK && (of->err == 0 || !of->errors)) { |
288 goto failed; | |
289 } | |
290 | |
291 if (of->is_dir) { | |
292 | |
293 if (file->is_dir || file->err) { | |
294 goto update; | |
295 } | |
296 | |
297 /* file became directory */ | |
1453 | 298 |
1775 | 299 } else if (of->err == 0) { /* file */ |
300 | |
301 if (file->is_dir || file->err) { | |
302 goto add_event; | |
303 } | |
1453 | 304 |
2070 | 305 if (of->uniq == file->uniq) { |
1453 | 306 |
1775 | 307 if (file->event) { |
308 file->use_event = 1; | |
1453 | 309 } |
310 | |
4101
31cf2902de60
Fix of the previous commit: is_directio flag processing introduced in r4077
Igor Sysoev <igor@sysoev.ru>
parents:
4100
diff
changeset
|
311 of->is_directio = file->is_directio; |
31cf2902de60
Fix of the previous commit: is_directio flag processing introduced in r4077
Igor Sysoev <igor@sysoev.ru>
parents:
4100
diff
changeset
|
312 |
4100
efeee901439a
Bugfix: open_file_cache did not update file info on retest.
Igor Sysoev <igor@sysoev.ru>
parents:
4076
diff
changeset
|
313 goto update; |
1775 | 314 } |
1453 | 315 |
1775 | 316 /* file was changed */ |
1453 | 317 |
1775 | 318 } else { /* error to cache */ |
1453 | 319 |
1775 | 320 if (file->err || file->is_dir) { |
321 goto update; | |
1453 | 322 } |
323 | |
1775 | 324 /* file was removed, etc. */ |
325 } | |
326 | |
327 if (file->count == 0) { | |
328 | |
329 ngx_open_file_del_event(file); | |
1453 | 330 |
1775 | 331 if (ngx_close_file(file->fd) == NGX_FILE_ERROR) { |
332 ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno, | |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
333 ngx_close_file_n " \"%V\" failed", name); |
1775 | 334 } |
1453 | 335 |
1775 | 336 goto add_event; |
337 } | |
338 | |
339 ngx_rbtree_delete(&cache->rbtree, &file->node); | |
340 | |
341 cache->current--; | |
342 | |
343 file->close = 1; | |
344 | |
345 goto create; | |
1453 | 346 } |
347 | |
348 /* not found */ | |
349 | |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
350 rc = ngx_open_and_stat_file(name, of, pool->log); |
1453 | 351 |
352 if (rc != NGX_OK && (of->err == 0 || !of->errors)) { | |
353 goto failed; | |
354 } | |
355 | |
356 create: | |
357 | |
358 if (cache->current >= cache->max) { | |
359 ngx_expire_old_cached_files(cache, 0, pool->log); | |
360 } | |
361 | |
362 file = ngx_alloc(sizeof(ngx_cached_open_file_t), pool->log); | |
363 | |
364 if (file == NULL) { | |
365 goto failed; | |
366 } | |
367 | |
368 file->name = ngx_alloc(name->len + 1, pool->log); | |
369 | |
370 if (file->name == NULL) { | |
371 ngx_free(file); | |
372 file = NULL; | |
373 goto failed; | |
374 } | |
375 | |
376 ngx_cpystrn(file->name, name->data, name->len + 1); | |
377 | |
378 file->node.key = hash; | |
379 | |
380 ngx_rbtree_insert(&cache->rbtree, &file->node); | |
381 | |
382 cache->current++; | |
383 | |
1775 | 384 file->uses = 1; |
1453 | 385 file->count = 0; |
2934
b6d588fa3ee9
initialize use_event field in open file cache
Igor Sysoev <igor@sysoev.ru>
parents:
2783
diff
changeset
|
386 file->use_event = 0; |
1775 | 387 file->event = NULL; |
388 | |
389 add_event: | |
390 | |
391 ngx_open_file_add_event(cache, file, of, pool->log); | |
1453 | 392 |
393 update: | |
394 | |
395 file->fd = of->fd; | |
396 file->err = of->err; | |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
397 #if (NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
398 file->disable_symlinks = of->disable_symlinks; |
4493
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
399 file->disable_symlinks_from = of->disable_symlinks_from; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
400 #endif |
1453 | 401 |
402 if (of->err == 0) { | |
403 file->uniq = of->uniq; | |
404 file->mtime = of->mtime; | |
405 file->size = of->size; | |
406 | |
407 file->close = 0; | |
408 | |
409 file->is_dir = of->is_dir; | |
410 file->is_file = of->is_file; | |
411 file->is_link = of->is_link; | |
412 file->is_exec = of->is_exec; | |
2246
987831d73bd8
cache directio flag in open file cache
Igor Sysoev <igor@sysoev.ru>
parents:
2231
diff
changeset
|
413 file->is_directio = of->is_directio; |
1453 | 414 |
415 if (!of->is_dir) { | |
416 file->count++; | |
417 } | |
418 } | |
419 | |
420 file->created = now; | |
421 | |
422 found: | |
423 | |
424 file->accessed = now; | |
425 | |
1765 | 426 ngx_queue_insert_head(&cache->expire_queue, &file->queue); |
1453 | 427 |
1772 | 428 ngx_log_debug5(NGX_LOG_DEBUG_CORE, pool->log, 0, |
429 "cached open file: %s, fd:%d, c:%d, e:%d, u:%d", | |
430 file->name, file->fd, file->count, file->err, file->uses); | |
1453 | 431 |
432 if (of->err == 0) { | |
433 | |
434 if (!of->is_dir) { | |
435 cln->handler = ngx_open_file_cleanup; | |
436 ofcln = cln->data; | |
437 | |
438 ofcln->cache = cache; | |
439 ofcln->file = file; | |
1772 | 440 ofcln->min_uses = of->min_uses; |
1453 | 441 ofcln->log = pool->log; |
442 } | |
443 | |
444 return NGX_OK; | |
445 } | |
446 | |
447 return NGX_ERROR; | |
448 | |
449 failed: | |
450 | |
1988
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
451 if (file) { |
1453 | 452 ngx_rbtree_delete(&cache->rbtree, &file->node); |
453 | |
454 cache->current--; | |
455 | |
1988
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
456 if (file->count == 0) { |
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
457 |
2006
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1988
diff
changeset
|
458 if (file->fd != NGX_INVALID_FILE) { |
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1988
diff
changeset
|
459 if (ngx_close_file(file->fd) == NGX_FILE_ERROR) { |
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1988
diff
changeset
|
460 ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno, |
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1988
diff
changeset
|
461 ngx_close_file_n " \"%s\" failed", |
1988
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
462 file->name); |
2006
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1988
diff
changeset
|
463 } |
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1988
diff
changeset
|
464 } |
1988
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
465 |
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
466 ngx_free(file->name); |
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
467 ngx_free(file); |
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
468 |
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
469 } else { |
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
470 file->close = 1; |
1453 | 471 } |
472 } | |
473 | |
474 if (of->fd != NGX_INVALID_FILE) { | |
475 if (ngx_close_file(of->fd) == NGX_FILE_ERROR) { | |
476 ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno, | |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
477 ngx_close_file_n " \"%V\" failed", name); |
1453 | 478 } |
479 } | |
480 | |
481 return NGX_ERROR; | |
482 } | |
483 | |
484 | |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
485 #if (NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
486 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
487 static ngx_fd_t |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
488 ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
489 ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log) |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
490 { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
491 ngx_fd_t fd; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
492 ngx_err_t err; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
493 ngx_file_info_t fi, atfi; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
494 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
495 /* |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
496 * To allow symlinks with the same owner, use openat() (followed |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
497 * by fstat()) and fstatat(AT_SYMLINK_NOFOLLOW), and then compare |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
498 * uids between fstat() and fstatat(). |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
499 * |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
500 * As there is a race between openat() and fstatat() we don't |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
501 * know if openat() in fact opened symlink or not. Therefore, |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
502 * we have to compare uids even if fstatat() reports the opened |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
503 * component isn't a symlink (as we don't know whether it was |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
504 * symlink during openat() or not). |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
505 */ |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
506 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
507 fd = ngx_openat_file(at_fd, name, mode, create, access); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
508 |
4486
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
509 if (fd == NGX_INVALID_FILE) { |
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
510 return NGX_INVALID_FILE; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
511 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
512 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
513 if (ngx_file_at_info(at_fd, name, &atfi, AT_SYMLINK_NOFOLLOW) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
514 == NGX_FILE_ERROR) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
515 { |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
516 err = ngx_errno; |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
517 goto failed; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
518 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
519 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
520 if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
521 err = ngx_errno; |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
522 goto failed; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
523 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
524 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
525 if (fi.st_uid != atfi.st_uid) { |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
526 err = NGX_ELOOP; |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
527 goto failed; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
528 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
529 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
530 return fd; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
531 |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
532 failed: |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
533 |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
534 if (ngx_close_file(fd) == NGX_FILE_ERROR) { |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
535 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
536 ngx_close_file_n " \"%V\" failed", name); |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
537 } |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
538 |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
539 ngx_set_errno(err); |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
540 |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
541 return NGX_INVALID_FILE; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
542 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
543 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
544 #endif |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
545 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
546 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
547 static ngx_fd_t |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
548 ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
549 ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log) |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
550 { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
551 ngx_fd_t fd; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
552 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
553 #if !(NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
554 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
555 fd = ngx_open_file(name->data, mode, create, access); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
556 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
557 if (fd == NGX_INVALID_FILE) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
558 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
559 of->failed = ngx_open_file_n; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
560 return NGX_INVALID_FILE; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
561 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
562 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
563 return fd; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
564 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
565 #else |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
566 |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
567 u_char *p, *cp, *end; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
568 ngx_fd_t at_fd; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
569 ngx_str_t at_name; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
570 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
571 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
572 fd = ngx_open_file(name->data, mode, create, access); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
573 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
574 if (fd == NGX_INVALID_FILE) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
575 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
576 of->failed = ngx_open_file_n; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
577 return NGX_INVALID_FILE; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
578 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
579 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
580 return fd; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
581 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
582 |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
583 p = name->data; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
584 end = p + name->len; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
585 |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
586 at_name = *name; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
587 |
4493
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
588 if (of->disable_symlinks_from) { |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
589 |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
590 cp = p + of->disable_symlinks_from; |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
591 |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
592 *cp = '\0'; |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
593 |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
594 at_fd = ngx_open_file(p, NGX_FILE_SEARCH|NGX_FILE_NONBLOCK, |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
595 NGX_FILE_OPEN, 0); |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
596 |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
597 *cp = '/'; |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
598 |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
599 if (at_fd == NGX_INVALID_FILE) { |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
600 of->err = ngx_errno; |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
601 of->failed = ngx_open_file_n; |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
602 return NGX_INVALID_FILE; |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
603 } |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
604 |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
605 at_name.len = of->disable_symlinks_from; |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
606 p = cp + 1; |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
607 |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
608 } else if (*p == '/') { |
47ece8818978
Disable symlinks: added the "from" parameter support to the open file cache.
Valentin Bartenev <vbart@nginx.com>
parents:
4488
diff
changeset
|
609 |
4486
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
610 at_fd = ngx_open_file("/", |
4488
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
611 NGX_FILE_SEARCH|NGX_FILE_NONBLOCK, |
4486
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
612 NGX_FILE_OPEN, 0); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
613 |
4484
f78a29a2f9e6
Disable symlinks: error handling cleanup again.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4480
diff
changeset
|
614 if (at_fd == NGX_INVALID_FILE) { |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
615 of->err = ngx_errno; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
616 of->failed = ngx_openat_file_n; |
4484
f78a29a2f9e6
Disable symlinks: error handling cleanup again.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4480
diff
changeset
|
617 return NGX_INVALID_FILE; |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
618 } |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
619 |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
620 at_name.len = 1; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
621 p++; |
4486
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
622 |
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
623 } else { |
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
624 at_fd = NGX_AT_FDCWD; |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
625 } |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
626 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
627 for ( ;; ) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
628 cp = ngx_strlchr(p, end, '/'); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
629 if (cp == NULL) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
630 break; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
631 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
632 |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
633 if (cp == p) { |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
634 p++; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
635 continue; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
636 } |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
637 |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
638 *cp = '\0'; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
639 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
640 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
641 fd = ngx_openat_file_owner(at_fd, p, |
4488
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
642 NGX_FILE_SEARCH|NGX_FILE_NONBLOCK, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
643 NGX_FILE_OPEN, 0, log); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
644 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
645 } else { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
646 fd = ngx_openat_file(at_fd, p, |
4488
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
647 NGX_FILE_SEARCH|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW, |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
648 NGX_FILE_OPEN, 0); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
649 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
650 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
651 *cp = '/'; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
652 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
653 if (fd == NGX_INVALID_FILE) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
654 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
655 of->failed = ngx_openat_file_n; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
656 goto failed; |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
657 } |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
658 |
4485
f7d131008e9c
Disable symlinks: added explicit cast of AT_FDCWD (ticket #111).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4484
diff
changeset
|
659 if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) { |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
660 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
4484
f78a29a2f9e6
Disable symlinks: error handling cleanup again.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4480
diff
changeset
|
661 ngx_close_file_n " \"%V\" failed", &at_name); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
662 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
663 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
664 p = cp + 1; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
665 at_fd = fd; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
666 at_name.len = cp - at_name.data; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
667 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
668 |
4486
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
669 if (p == end) { |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
670 |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
671 /* |
4488
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
672 * If pathname ends with a trailing slash, assume the last path |
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
673 * component is a directory and reopen it with requested flags; |
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
674 * if not, fail with ENOTDIR as per POSIX. |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
675 * |
4488
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
676 * We cannot rely on O_DIRECTORY in the loop above to check |
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
677 * that the last path component is a directory because |
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
678 * O_DIRECTORY doesn't work on FreeBSD 8. Fortunately, by |
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
679 * reopening a directory, we don't depend on it at all. |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
680 */ |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
681 |
4488
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
682 fd = ngx_openat_file(at_fd, ".", mode, create, access); |
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
683 goto done; |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
684 } |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
685 |
4487
a786c85e8268
Disable symlinks: don't allow creating or truncating a file via a symlink in
Valentin Bartenev <vbart@nginx.com>
parents:
4486
diff
changeset
|
686 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER |
a786c85e8268
Disable symlinks: don't allow creating or truncating a file via a symlink in
Valentin Bartenev <vbart@nginx.com>
parents:
4486
diff
changeset
|
687 && !(create & (NGX_FILE_CREATE_OR_OPEN|NGX_FILE_TRUNCATE))) |
a786c85e8268
Disable symlinks: don't allow creating or truncating a file via a symlink in
Valentin Bartenev <vbart@nginx.com>
parents:
4486
diff
changeset
|
688 { |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
689 fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
690 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
691 } else { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
692 fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
693 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
694 |
4488
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
695 done: |
d33ce8cd0d70
Disable symlinks: use O_SEARCH|O_DIRECTORY to open path components.
Valentin Bartenev <vbart@nginx.com>
parents:
4487
diff
changeset
|
696 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
697 if (fd == NGX_INVALID_FILE) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
698 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
699 of->failed = ngx_openat_file_n; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
700 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
701 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
702 failed: |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
703 |
4485
f7d131008e9c
Disable symlinks: added explicit cast of AT_FDCWD (ticket #111).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4484
diff
changeset
|
704 if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) { |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
705 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
4484
f78a29a2f9e6
Disable symlinks: error handling cleanup again.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4480
diff
changeset
|
706 ngx_close_file_n " \"%V\" failed", &at_name); |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
707 } |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
708 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
709 return fd; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
710 #endif |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
711 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
712 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
713 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
714 static ngx_int_t |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
715 ngx_file_info_wrapper(ngx_str_t *name, ngx_open_file_info_t *of, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
716 ngx_file_info_t *fi, ngx_log_t *log) |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
717 { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
718 ngx_int_t rc; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
719 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
720 #if !(NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
721 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
722 rc = ngx_file_info(name->data, fi); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
723 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
724 if (rc == NGX_FILE_ERROR) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
725 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
726 of->failed = ngx_file_info_n; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
727 return NGX_FILE_ERROR; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
728 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
729 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
730 return rc; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
731 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
732 #else |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
733 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
734 ngx_fd_t fd; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
735 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
736 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
737 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
738 rc = ngx_file_info(name->data, fi); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
739 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
740 if (rc == NGX_FILE_ERROR) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
741 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
742 of->failed = ngx_file_info_n; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
743 return NGX_FILE_ERROR; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
744 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
745 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
746 return rc; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
747 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
748 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
749 fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
750 NGX_FILE_OPEN, 0, log); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
751 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
752 if (fd == NGX_INVALID_FILE) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
753 return NGX_FILE_ERROR; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
754 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
755 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
756 rc = ngx_fd_info(fd, fi); |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
757 |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
758 if (rc == NGX_FILE_ERROR) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
759 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
760 of->failed = ngx_fd_info_n; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
761 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
762 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
763 if (ngx_close_file(fd) == NGX_FILE_ERROR) { |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
764 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
765 ngx_close_file_n " \"%V\" failed", name); |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
766 } |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
767 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
768 return rc; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
769 #endif |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
770 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
771 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
772 |
1453 | 773 static ngx_int_t |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
774 ngx_open_and_stat_file(ngx_str_t *name, ngx_open_file_info_t *of, |
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
775 ngx_log_t *log) |
1453 | 776 { |
777 ngx_fd_t fd; | |
778 ngx_file_info_t fi; | |
779 | |
2070 | 780 if (of->fd != NGX_INVALID_FILE) { |
1453 | 781 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
782 if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
783 of->fd = NGX_INVALID_FILE; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
784 return NGX_ERROR; |
1453 | 785 } |
786 | |
2070 | 787 if (of->uniq == ngx_file_uniq(&fi)) { |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
788 goto done; |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
789 } |
1453 | 790 |
2070 | 791 } else if (of->test_dir) { |
792 | |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
793 if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
794 of->fd = NGX_INVALID_FILE; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
795 return NGX_ERROR; |
2070 | 796 } |
797 | |
2460
225fa4abd76f
test ngx_file_info() result, the bug has been introduced in r2070
Igor Sysoev <igor@sysoev.ru>
parents:
2246
diff
changeset
|
798 if (ngx_is_dir(&fi)) { |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
799 goto done; |
1453 | 800 } |
801 } | |
802 | |
2072 | 803 if (!of->log) { |
3497
ac281bc4c187
use non-blocking open() not to hang on FIFO files, etc.
Igor Sysoev <igor@sysoev.ru>
parents:
3178
diff
changeset
|
804 |
ac281bc4c187
use non-blocking open() not to hang on FIFO files, etc.
Igor Sysoev <igor@sysoev.ru>
parents:
3178
diff
changeset
|
805 /* |
ac281bc4c187
use non-blocking open() not to hang on FIFO files, etc.
Igor Sysoev <igor@sysoev.ru>
parents:
3178
diff
changeset
|
806 * Use non-blocking open() not to hang on FIFO files, etc. |
ac281bc4c187
use non-blocking open() not to hang on FIFO files, etc.
Igor Sysoev <igor@sysoev.ru>
parents:
3178
diff
changeset
|
807 * This flag has no effect on a regular files. |
ac281bc4c187
use non-blocking open() not to hang on FIFO files, etc.
Igor Sysoev <igor@sysoev.ru>
parents:
3178
diff
changeset
|
808 */ |
ac281bc4c187
use non-blocking open() not to hang on FIFO files, etc.
Igor Sysoev <igor@sysoev.ru>
parents:
3178
diff
changeset
|
809 |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
810 fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
811 NGX_FILE_OPEN, 0, log); |
2072 | 812 |
813 } else { | |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
814 fd = ngx_open_file_wrapper(name, of, NGX_FILE_APPEND, |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
815 NGX_FILE_CREATE_OR_OPEN, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
816 NGX_FILE_DEFAULT_ACCESS, log); |
2072 | 817 } |
1453 | 818 |
819 if (fd == NGX_INVALID_FILE) { | |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
820 of->fd = NGX_INVALID_FILE; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
821 return NGX_ERROR; |
1453 | 822 } |
823 | |
824 if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { | |
825 ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, | |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
826 ngx_fd_info_n " \"%V\" failed", name); |
1453 | 827 |
828 if (ngx_close_file(fd) == NGX_FILE_ERROR) { | |
829 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
830 ngx_close_file_n " \"%V\" failed", name); |
1453 | 831 } |
832 | |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
833 of->fd = NGX_INVALID_FILE; |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
834 |
1453 | 835 return NGX_ERROR; |
836 } | |
837 | |
838 if (ngx_is_dir(&fi)) { | |
839 if (ngx_close_file(fd) == NGX_FILE_ERROR) { | |
840 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
841 ngx_close_file_n " \"%V\" failed", name); |
1453 | 842 } |
843 | |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
844 of->fd = NGX_INVALID_FILE; |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
845 |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
846 } else { |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
847 of->fd = fd; |
2129 | 848 |
3178 | 849 if (of->read_ahead && ngx_file_size(&fi) > NGX_MIN_READ_AHEAD) { |
850 if (ngx_read_ahead(fd, of->read_ahead) == NGX_ERROR) { | |
851 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
852 ngx_read_ahead_n " \"%V\" failed", name); |
3178 | 853 } |
854 } | |
855 | |
2129 | 856 if (of->directio <= ngx_file_size(&fi)) { |
3164
b1b1775698d5
uniform ngx_directio_on/off() interface with other file functions
Igor Sysoev <igor@sysoev.ru>
parents:
2934
diff
changeset
|
857 if (ngx_directio_on(fd) == NGX_FILE_ERROR) { |
2129 | 858 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
859 ngx_directio_on_n " \"%V\" failed", name); |
2231
8564129d49b6
*) handle unaligned file part for directio
Igor Sysoev <igor@sysoev.ru>
parents:
2129
diff
changeset
|
860 |
8564129d49b6
*) handle unaligned file part for directio
Igor Sysoev <igor@sysoev.ru>
parents:
2129
diff
changeset
|
861 } else { |
8564129d49b6
*) handle unaligned file part for directio
Igor Sysoev <igor@sysoev.ru>
parents:
2129
diff
changeset
|
862 of->is_directio = 1; |
2129 | 863 } |
864 } | |
1453 | 865 } |
866 | |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
867 done: |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
868 |
1453 | 869 of->uniq = ngx_file_uniq(&fi); |
870 of->mtime = ngx_file_mtime(&fi); | |
871 of->size = ngx_file_size(&fi); | |
3899
e7cd13b7f759
Use more precise stat.st_blocks to account cache size on Unix
Igor Sysoev <igor@sysoev.ru>
parents:
3497
diff
changeset
|
872 of->fs_size = ngx_file_fs_size(&fi); |
1453 | 873 of->is_dir = ngx_is_dir(&fi); |
874 of->is_file = ngx_is_file(&fi); | |
875 of->is_link = ngx_is_link(&fi); | |
876 of->is_exec = ngx_is_exec(&fi); | |
877 | |
878 return NGX_OK; | |
879 } | |
880 | |
881 | |
1775 | 882 /* |
883 * we ignore any possible event setting error and | |
884 * fallback to usual periodic file retests | |
885 */ | |
886 | |
887 static void | |
888 ngx_open_file_add_event(ngx_open_file_cache_t *cache, | |
889 ngx_cached_open_file_t *file, ngx_open_file_info_t *of, ngx_log_t *log) | |
890 { | |
891 ngx_open_file_cache_event_t *fev; | |
892 | |
893 if (!(ngx_event_flags & NGX_USE_VNODE_EVENT) | |
894 || !of->events | |
895 || file->event | |
896 || of->fd == NGX_INVALID_FILE | |
897 || file->uses < of->min_uses) | |
898 { | |
899 return; | |
900 } | |
901 | |
2070 | 902 file->use_event = 0; |
903 | |
1775 | 904 file->event = ngx_calloc(sizeof(ngx_event_t), log); |
905 if (file->event== NULL) { | |
906 return; | |
907 } | |
908 | |
909 fev = ngx_alloc(sizeof(ngx_open_file_cache_event_t), log); | |
910 if (fev == NULL) { | |
911 ngx_free(file->event); | |
912 file->event = NULL; | |
913 return; | |
914 } | |
915 | |
916 fev->fd = of->fd; | |
917 fev->file = file; | |
918 fev->cache = cache; | |
919 | |
920 file->event->handler = ngx_open_file_cache_remove; | |
921 file->event->data = fev; | |
922 | |
923 /* | |
924 * although vnode event may be called while ngx_cycle->poll | |
925 * destruction, however, cleanup procedures are run before any | |
926 * memory freeing and events will be canceled. | |
927 */ | |
928 | |
929 file->event->log = ngx_cycle->log; | |
930 | |
931 if (ngx_add_event(file->event, NGX_VNODE_EVENT, NGX_ONESHOT_EVENT) | |
932 != NGX_OK) | |
933 { | |
934 ngx_free(file->event->data); | |
935 ngx_free(file->event); | |
936 file->event = NULL; | |
937 return; | |
938 } | |
939 | |
940 /* | |
2071 | 941 * we do not set file->use_event here because there may be a race |
942 * condition: a file may be deleted between opening the file and | |
943 * adding event, so we rely upon event notification only after | |
944 * one file revalidation on next file access | |
1775 | 945 */ |
946 | |
947 return; | |
948 } | |
949 | |
950 | |
1453 | 951 static void |
952 ngx_open_file_cleanup(void *data) | |
953 { | |
954 ngx_open_file_cache_cleanup_t *c = data; | |
955 | |
956 c->file->count--; | |
957 | |
1772 | 958 ngx_close_cached_file(c->cache, c->file, c->min_uses, c->log); |
1453 | 959 |
960 /* drop one or two expired open files */ | |
961 ngx_expire_old_cached_files(c->cache, 1, c->log); | |
962 } | |
963 | |
964 | |
965 static void | |
966 ngx_close_cached_file(ngx_open_file_cache_t *cache, | |
1772 | 967 ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_log_t *log) |
1453 | 968 { |
1772 | 969 ngx_log_debug5(NGX_LOG_DEBUG_CORE, log, 0, |
970 "close cached open file: %s, fd:%d, c:%d, u:%d, %d", | |
971 file->name, file->fd, file->count, file->uses, file->close); | |
1453 | 972 |
973 if (!file->close) { | |
974 | |
975 file->accessed = ngx_time(); | |
976 | |
1765 | 977 ngx_queue_remove(&file->queue); |
1453 | 978 |
1765 | 979 ngx_queue_insert_head(&cache->expire_queue, &file->queue); |
1453 | 980 |
1772 | 981 if (file->uses >= min_uses || file->count) { |
982 return; | |
983 } | |
1453 | 984 } |
985 | |
1775 | 986 ngx_open_file_del_event(file); |
1453 | 987 |
988 if (file->count) { | |
989 return; | |
990 } | |
991 | |
1772 | 992 if (file->fd != NGX_INVALID_FILE) { |
993 | |
994 if (ngx_close_file(file->fd) == NGX_FILE_ERROR) { | |
995 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
996 ngx_close_file_n " \"%s\" failed", file->name); | |
997 } | |
998 | |
999 file->fd = NGX_INVALID_FILE; | |
1000 } | |
1001 | |
1002 if (!file->close) { | |
1003 return; | |
1453 | 1004 } |
1005 | |
1006 ngx_free(file->name); | |
1007 ngx_free(file); | |
1008 } | |
1009 | |
1010 | |
1011 static void | |
1775 | 1012 ngx_open_file_del_event(ngx_cached_open_file_t *file) |
1013 { | |
1014 if (file->event == NULL) { | |
1015 return; | |
1016 } | |
1017 | |
1018 (void) ngx_del_event(file->event, NGX_VNODE_EVENT, | |
1019 file->count ? NGX_FLUSH_EVENT : NGX_CLOSE_EVENT); | |
1020 | |
1021 ngx_free(file->event->data); | |
1022 ngx_free(file->event); | |
1023 file->event = NULL; | |
1024 file->use_event = 0; | |
1025 } | |
1026 | |
1027 | |
1028 static void | |
1453 | 1029 ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, ngx_uint_t n, |
1030 ngx_log_t *log) | |
1031 { | |
1032 time_t now; | |
1765 | 1033 ngx_queue_t *q; |
1453 | 1034 ngx_cached_open_file_t *file; |
1035 | |
1036 now = ngx_time(); | |
1037 | |
1038 /* | |
1039 * n == 1 deletes one or two inactive files | |
1040 * n == 0 deletes least recently used file by force | |
1041 * and one or two inactive files | |
1042 */ | |
1043 | |
1044 while (n < 3) { | |
1045 | |
1765 | 1046 if (ngx_queue_empty(&cache->expire_queue)) { |
1453 | 1047 return; |
1048 } | |
1049 | |
1765 | 1050 q = ngx_queue_last(&cache->expire_queue); |
1051 | |
1052 file = ngx_queue_data(q, ngx_cached_open_file_t, queue); | |
1053 | |
1453 | 1054 if (n++ != 0 && now - file->accessed <= cache->inactive) { |
1055 return; | |
1056 } | |
1057 | |
1765 | 1058 ngx_queue_remove(q); |
1453 | 1059 |
1060 ngx_rbtree_delete(&cache->rbtree, &file->node); | |
1061 | |
1062 cache->current--; | |
1063 | |
1064 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, | |
1065 "expire cached open file: %s", file->name); | |
1066 | |
1067 if (!file->err && !file->is_dir) { | |
1068 file->close = 1; | |
1772 | 1069 ngx_close_cached_file(cache, file, 0, log); |
1453 | 1070 |
1071 } else { | |
1072 ngx_free(file->name); | |
1073 ngx_free(file); | |
1074 } | |
1075 } | |
1076 } | |
1077 | |
1078 | |
1079 static void | |
1080 ngx_open_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp, | |
1081 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) | |
1082 { | |
1083 ngx_rbtree_node_t **p; | |
1084 ngx_cached_open_file_t *file, *file_temp; | |
1085 | |
1086 for ( ;; ) { | |
1087 | |
1088 if (node->key < temp->key) { | |
1089 | |
1090 p = &temp->left; | |
1091 | |
1092 } else if (node->key > temp->key) { | |
1093 | |
1094 p = &temp->right; | |
1095 | |
1096 } else { /* node->key == temp->key */ | |
1097 | |
1098 file = (ngx_cached_open_file_t *) node; | |
1099 file_temp = (ngx_cached_open_file_t *) temp; | |
1100 | |
1101 p = (ngx_strcmp(file->name, file_temp->name) < 0) | |
1102 ? &temp->left : &temp->right; | |
1103 } | |
1104 | |
1105 if (*p == sentinel) { | |
1106 break; | |
1107 } | |
1108 | |
1109 temp = *p; | |
1110 } | |
1111 | |
1112 *p = node; | |
1113 node->parent = temp; | |
1114 node->left = sentinel; | |
1115 node->right = sentinel; | |
1116 ngx_rbt_red(node); | |
1117 } | |
1118 | |
1119 | |
1775 | 1120 static ngx_cached_open_file_t * |
1121 ngx_open_file_lookup(ngx_open_file_cache_t *cache, ngx_str_t *name, | |
1122 uint32_t hash) | |
1123 { | |
1124 ngx_int_t rc; | |
1125 ngx_rbtree_node_t *node, *sentinel; | |
1126 ngx_cached_open_file_t *file; | |
1127 | |
1128 node = cache->rbtree.root; | |
1129 sentinel = cache->rbtree.sentinel; | |
1130 | |
1131 while (node != sentinel) { | |
1132 | |
1133 if (hash < node->key) { | |
1134 node = node->left; | |
1135 continue; | |
1136 } | |
1137 | |
1138 if (hash > node->key) { | |
1139 node = node->right; | |
1140 continue; | |
1141 } | |
1142 | |
1143 /* hash == node->key */ | |
1144 | |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4493
diff
changeset
|
1145 file = (ngx_cached_open_file_t *) node; |
1775 | 1146 |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4493
diff
changeset
|
1147 rc = ngx_strcmp(name->data, file->name); |
1775 | 1148 |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4493
diff
changeset
|
1149 if (rc == 0) { |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4493
diff
changeset
|
1150 return file; |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4493
diff
changeset
|
1151 } |
1775 | 1152 |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4493
diff
changeset
|
1153 node = (rc < 0) ? node->left : node->right; |
1775 | 1154 } |
1155 | |
1156 return NULL; | |
1157 } | |
1158 | |
1159 | |
1453 | 1160 static void |
1161 ngx_open_file_cache_remove(ngx_event_t *ev) | |
1162 { | |
1163 ngx_cached_open_file_t *file; | |
1164 ngx_open_file_cache_event_t *fev; | |
1165 | |
1166 fev = ev->data; | |
1167 file = fev->file; | |
1168 | |
1765 | 1169 ngx_queue_remove(&file->queue); |
1453 | 1170 |
1171 ngx_rbtree_delete(&fev->cache->rbtree, &file->node); | |
1172 | |
1173 fev->cache->current--; | |
1174 | |
1175 /* NGX_ONESHOT_EVENT was already deleted */ | |
1176 file->event = NULL; | |
2070 | 1177 file->use_event = 0; |
1453 | 1178 |
1179 file->close = 1; | |
1180 | |
1772 | 1181 ngx_close_cached_file(fev->cache, file, 0, ev->log); |
1453 | 1182 |
1183 /* free memory only when fev->cache and fev->file are already not needed */ | |
1184 | |
1185 ngx_free(ev->data); | |
1186 ngx_free(ev); | |
1187 } |