Mercurial > hg > nginx
annotate src/core/ngx_open_file_cache.c @ 4487:a786c85e8268
Disable symlinks: don't allow creating or truncating a file via a symlink in
the last path component if "if_not_owner" parameter is used.
To prevent race condition we have to open a file before checking its owner and
there's no way to change access flags for already opened file descriptor, so
we disable symlinks for the last path component at all if flags allow creating
or truncating the file.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Tue, 21 Feb 2012 15:04:41 +0000 |
parents | a996bb40a0bb |
children | d33ce8cd0d70 |
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 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
232 #endif |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
233 )) |
1775 | 234 { |
235 if (file->err == 0) { | |
1772 | 236 |
1775 | 237 of->fd = file->fd; |
238 of->uniq = file->uniq; | |
239 of->mtime = file->mtime; | |
240 of->size = file->size; | |
1453 | 241 |
1775 | 242 of->is_dir = file->is_dir; |
243 of->is_file = file->is_file; | |
244 of->is_link = file->is_link; | |
245 of->is_exec = file->is_exec; | |
2246
987831d73bd8
cache directio flag in open file cache
Igor Sysoev <igor@sysoev.ru>
parents:
2231
diff
changeset
|
246 of->is_directio = file->is_directio; |
1453 | 247 |
1775 | 248 if (!file->is_dir) { |
249 file->count++; | |
250 ngx_open_file_add_event(cache, file, of, pool->log); | |
1453 | 251 } |
252 | |
1775 | 253 } else { |
254 of->err = file->err; | |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
255 #if (NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
256 of->failed = file->disable_symlinks ? ngx_openat_file_n |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
257 : ngx_open_file_n; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
258 #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
|
259 of->failed = ngx_open_file_n; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
260 #endif |
1775 | 261 } |
262 | |
263 goto found; | |
264 } | |
265 | |
266 ngx_log_debug4(NGX_LOG_DEBUG_CORE, pool->log, 0, | |
267 "retest open file: %s, fd:%d, c:%d, e:%d", | |
268 file->name, file->fd, file->count, file->err); | |
1453 | 269 |
1775 | 270 if (file->is_dir) { |
271 | |
272 /* | |
273 * chances that directory became file are very small | |
274 * so test_dir flag allows to use a single syscall | |
275 * in ngx_file_info() instead of three syscalls | |
276 */ | |
277 | |
278 of->test_dir = 1; | |
279 } | |
280 | |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
281 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
|
282 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
|
283 |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
284 rc = ngx_open_and_stat_file(name, of, pool->log); |
1453 | 285 |
1775 | 286 if (rc != NGX_OK && (of->err == 0 || !of->errors)) { |
287 goto failed; | |
288 } | |
289 | |
290 if (of->is_dir) { | |
291 | |
292 if (file->is_dir || file->err) { | |
293 goto update; | |
294 } | |
295 | |
296 /* file became directory */ | |
1453 | 297 |
1775 | 298 } else if (of->err == 0) { /* file */ |
299 | |
300 if (file->is_dir || file->err) { | |
301 goto add_event; | |
302 } | |
1453 | 303 |
2070 | 304 if (of->uniq == file->uniq) { |
1453 | 305 |
1775 | 306 if (file->event) { |
307 file->use_event = 1; | |
1453 | 308 } |
309 | |
4101
31cf2902de60
Fix of the previous commit: is_directio flag processing introduced in r4077
Igor Sysoev <igor@sysoev.ru>
parents:
4100
diff
changeset
|
310 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
|
311 |
4100
efeee901439a
Bugfix: open_file_cache did not update file info on retest.
Igor Sysoev <igor@sysoev.ru>
parents:
4076
diff
changeset
|
312 goto update; |
1775 | 313 } |
1453 | 314 |
1775 | 315 /* file was changed */ |
1453 | 316 |
1775 | 317 } else { /* error to cache */ |
1453 | 318 |
1775 | 319 if (file->err || file->is_dir) { |
320 goto update; | |
1453 | 321 } |
322 | |
1775 | 323 /* file was removed, etc. */ |
324 } | |
325 | |
326 if (file->count == 0) { | |
327 | |
328 ngx_open_file_del_event(file); | |
1453 | 329 |
1775 | 330 if (ngx_close_file(file->fd) == NGX_FILE_ERROR) { |
331 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
|
332 ngx_close_file_n " \"%V\" failed", name); |
1775 | 333 } |
1453 | 334 |
1775 | 335 goto add_event; |
336 } | |
337 | |
338 ngx_rbtree_delete(&cache->rbtree, &file->node); | |
339 | |
340 cache->current--; | |
341 | |
342 file->close = 1; | |
343 | |
344 goto create; | |
1453 | 345 } |
346 | |
347 /* not found */ | |
348 | |
4476
94ef9d25ec5b
Changed ngx_open_and_stat_file() to use ngx_str_t.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
349 rc = ngx_open_and_stat_file(name, of, pool->log); |
1453 | 350 |
351 if (rc != NGX_OK && (of->err == 0 || !of->errors)) { | |
352 goto failed; | |
353 } | |
354 | |
355 create: | |
356 | |
357 if (cache->current >= cache->max) { | |
358 ngx_expire_old_cached_files(cache, 0, pool->log); | |
359 } | |
360 | |
361 file = ngx_alloc(sizeof(ngx_cached_open_file_t), pool->log); | |
362 | |
363 if (file == NULL) { | |
364 goto failed; | |
365 } | |
366 | |
367 file->name = ngx_alloc(name->len + 1, pool->log); | |
368 | |
369 if (file->name == NULL) { | |
370 ngx_free(file); | |
371 file = NULL; | |
372 goto failed; | |
373 } | |
374 | |
375 ngx_cpystrn(file->name, name->data, name->len + 1); | |
376 | |
377 file->node.key = hash; | |
378 | |
379 ngx_rbtree_insert(&cache->rbtree, &file->node); | |
380 | |
381 cache->current++; | |
382 | |
1775 | 383 file->uses = 1; |
1453 | 384 file->count = 0; |
2934
b6d588fa3ee9
initialize use_event field in open file cache
Igor Sysoev <igor@sysoev.ru>
parents:
2783
diff
changeset
|
385 file->use_event = 0; |
1775 | 386 file->event = NULL; |
387 | |
388 add_event: | |
389 | |
390 ngx_open_file_add_event(cache, file, of, pool->log); | |
1453 | 391 |
392 update: | |
393 | |
394 file->fd = of->fd; | |
395 file->err = of->err; | |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
396 #if (NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
397 file->disable_symlinks = of->disable_symlinks; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
398 #endif |
1453 | 399 |
400 if (of->err == 0) { | |
401 file->uniq = of->uniq; | |
402 file->mtime = of->mtime; | |
403 file->size = of->size; | |
404 | |
405 file->close = 0; | |
406 | |
407 file->is_dir = of->is_dir; | |
408 file->is_file = of->is_file; | |
409 file->is_link = of->is_link; | |
410 file->is_exec = of->is_exec; | |
2246
987831d73bd8
cache directio flag in open file cache
Igor Sysoev <igor@sysoev.ru>
parents:
2231
diff
changeset
|
411 file->is_directio = of->is_directio; |
1453 | 412 |
413 if (!of->is_dir) { | |
414 file->count++; | |
415 } | |
416 } | |
417 | |
418 file->created = now; | |
419 | |
420 found: | |
421 | |
422 file->accessed = now; | |
423 | |
1765 | 424 ngx_queue_insert_head(&cache->expire_queue, &file->queue); |
1453 | 425 |
1772 | 426 ngx_log_debug5(NGX_LOG_DEBUG_CORE, pool->log, 0, |
427 "cached open file: %s, fd:%d, c:%d, e:%d, u:%d", | |
428 file->name, file->fd, file->count, file->err, file->uses); | |
1453 | 429 |
430 if (of->err == 0) { | |
431 | |
432 if (!of->is_dir) { | |
433 cln->handler = ngx_open_file_cleanup; | |
434 ofcln = cln->data; | |
435 | |
436 ofcln->cache = cache; | |
437 ofcln->file = file; | |
1772 | 438 ofcln->min_uses = of->min_uses; |
1453 | 439 ofcln->log = pool->log; |
440 } | |
441 | |
442 return NGX_OK; | |
443 } | |
444 | |
445 return NGX_ERROR; | |
446 | |
447 failed: | |
448 | |
1988
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
449 if (file) { |
1453 | 450 ngx_rbtree_delete(&cache->rbtree, &file->node); |
451 | |
452 cache->current--; | |
453 | |
1988
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
454 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
|
455 |
2006
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1988
diff
changeset
|
456 if (file->fd != NGX_INVALID_FILE) { |
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1988
diff
changeset
|
457 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
|
458 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
|
459 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
|
460 file->name); |
2006
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1988
diff
changeset
|
461 } |
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1988
diff
changeset
|
462 } |
1988
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
463 |
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
464 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
|
465 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
|
466 |
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
467 } else { |
34051c712e41
fix segfault when file is deleted and open_file_cache_errors is off
Igor Sysoev <igor@sysoev.ru>
parents:
1987
diff
changeset
|
468 file->close = 1; |
1453 | 469 } |
470 } | |
471 | |
472 if (of->fd != NGX_INVALID_FILE) { | |
473 if (ngx_close_file(of->fd) == NGX_FILE_ERROR) { | |
474 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
|
475 ngx_close_file_n " \"%V\" failed", name); |
1453 | 476 } |
477 } | |
478 | |
479 return NGX_ERROR; | |
480 } | |
481 | |
482 | |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
483 #if (NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
484 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
485 static ngx_fd_t |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
486 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
|
487 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
|
488 { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
489 ngx_fd_t fd; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
490 ngx_err_t err; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
491 ngx_file_info_t fi, atfi; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
492 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
493 /* |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
494 * To allow symlinks with the same owner, use openat() (followed |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
495 * by fstat()) and fstatat(AT_SYMLINK_NOFOLLOW), and then compare |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
496 * uids between fstat() and fstatat(). |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
497 * |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
498 * 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
|
499 * know if openat() in fact opened symlink or not. Therefore, |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
500 * 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
|
501 * 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
|
502 * symlink during openat() or not). |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
503 */ |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
504 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
505 fd = ngx_openat_file(at_fd, name, mode, create, access); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
506 |
4486
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
507 if (fd == NGX_INVALID_FILE) { |
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
508 return NGX_INVALID_FILE; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
509 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
510 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
511 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
|
512 == NGX_FILE_ERROR) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
513 { |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
514 err = ngx_errno; |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
515 goto failed; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
516 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
517 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
518 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
|
519 err = ngx_errno; |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
520 goto failed; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
521 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
522 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
523 if (fi.st_uid != atfi.st_uid) { |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
524 err = NGX_ELOOP; |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
525 goto failed; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
526 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
527 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
528 return fd; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
529 |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
530 failed: |
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 if (ngx_close_file(fd) == NGX_FILE_ERROR) { |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
533 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
534 ngx_close_file_n " \"%V\" failed", name); |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
535 } |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
536 |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
537 ngx_set_errno(err); |
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 return NGX_INVALID_FILE; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
540 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
541 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
542 #endif |
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 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
545 static ngx_fd_t |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
546 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
|
547 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
|
548 { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
549 ngx_fd_t fd; |
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 #if !(NGX_HAVE_OPENAT) |
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 fd = ngx_open_file(name->data, mode, create, access); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
554 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
555 if (fd == NGX_INVALID_FILE) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
556 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
557 of->failed = ngx_open_file_n; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
558 return NGX_INVALID_FILE; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
559 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
560 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
561 return fd; |
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 #else |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
564 |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
565 u_char *p, *cp, *end; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
566 ngx_fd_t at_fd; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
567 ngx_str_t at_name; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
568 ngx_file_info_t fi; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
569 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
570 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
571 fd = ngx_open_file(name->data, mode, create, access); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
572 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
573 if (fd == NGX_INVALID_FILE) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
574 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
575 of->failed = ngx_open_file_n; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
576 return NGX_INVALID_FILE; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
577 } |
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 return fd; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
580 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
581 |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
582 p = name->data; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
583 end = p + name->len; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
584 |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
585 at_name = *name; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
586 |
4486
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
587 if (*p == '/') { |
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
588 at_fd = ngx_open_file("/", |
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
589 NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, |
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
590 NGX_FILE_OPEN, 0); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
591 |
4484
f78a29a2f9e6
Disable symlinks: error handling cleanup again.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4480
diff
changeset
|
592 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
|
593 of->err = ngx_errno; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
594 of->failed = ngx_openat_file_n; |
4484
f78a29a2f9e6
Disable symlinks: error handling cleanup again.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4480
diff
changeset
|
595 return NGX_INVALID_FILE; |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
596 } |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
597 |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
598 at_name.len = 1; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
599 p++; |
4486
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
600 |
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
601 } else { |
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
602 at_fd = NGX_AT_FDCWD; |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
603 } |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
604 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
605 for ( ;; ) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
606 cp = ngx_strlchr(p, end, '/'); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
607 if (cp == NULL) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
608 break; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
609 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
610 |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
611 if (cp == p) { |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
612 p++; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
613 continue; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
614 } |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
615 |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
616 *cp = '\0'; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
617 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
618 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
619 fd = ngx_openat_file_owner(at_fd, p, |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
620 NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
621 NGX_FILE_OPEN, 0, log); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
622 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
623 } else { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
624 fd = ngx_openat_file(at_fd, p, |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
625 NGX_FILE_RDONLY|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW, |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
626 NGX_FILE_OPEN, 0); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
627 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
628 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
629 *cp = '/'; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
630 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
631 if (fd == NGX_INVALID_FILE) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
632 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
633 of->failed = ngx_openat_file_n; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
634 goto failed; |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
635 } |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
636 |
4485
f7d131008e9c
Disable symlinks: added explicit cast of AT_FDCWD (ticket #111).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4484
diff
changeset
|
637 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
|
638 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
|
639 ngx_close_file_n " \"%V\" failed", &at_name); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
640 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
641 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
642 p = cp + 1; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
643 at_fd = fd; |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
644 at_name.len = cp - at_name.data; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
645 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
646 |
4486
a996bb40a0bb
Disable symlinks: cleanups once again.
Valentin Bartenev <vbart@nginx.com>
parents:
4485
diff
changeset
|
647 if (p == end) { |
4480
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
648 |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
649 /* |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
650 * If pathname ends with a trailing slash, check if last path |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
651 * component is a directory; if not, fail with ENOTDIR as per |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
652 * POSIX. |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
653 * |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
654 * We use separate check instead of O_DIRECTORY in the loop above, |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
655 * as O_DIRECTORY doesn't work on FreeBSD 8. |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
656 * |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
657 * Note this returns already opened file descriptor, with different |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
658 * mode/create/access. This is believed to be safe as we don't |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
659 * use this codepath to create directories. |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
660 */ |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
661 |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
662 if (ngx_fd_info(at_fd, &fi) == NGX_FILE_ERROR) { |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
663 of->err = ngx_errno; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
664 of->failed = ngx_fd_info_n; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
665 fd = NGX_INVALID_FILE; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
666 |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
667 goto failed; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
668 } |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
669 |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
670 if (ngx_is_dir(&fi)) { |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
671 return at_fd; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
672 } |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
673 |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
674 of->err = ENOTDIR; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
675 of->failed = ngx_openat_file_n; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
676 fd = NGX_INVALID_FILE; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
677 |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
678 goto failed; |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
679 } |
5a3cb84545e5
Disable symlinks: fixed edge cases of path handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4479
diff
changeset
|
680 |
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
|
681 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
|
682 && !(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
|
683 { |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
684 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
|
685 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
686 } else { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
687 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
|
688 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
689 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
690 if (fd == NGX_INVALID_FILE) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
691 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
692 of->failed = ngx_openat_file_n; |
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 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
695 failed: |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
696 |
4485
f7d131008e9c
Disable symlinks: added explicit cast of AT_FDCWD (ticket #111).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4484
diff
changeset
|
697 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
|
698 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
|
699 ngx_close_file_n " \"%V\" failed", &at_name); |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
700 } |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
701 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
702 return fd; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
703 #endif |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
704 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
705 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
706 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
707 static ngx_int_t |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
708 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
|
709 ngx_file_info_t *fi, ngx_log_t *log) |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
710 { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
711 ngx_int_t rc; |
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 #if !(NGX_HAVE_OPENAT) |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
714 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
715 rc = ngx_file_info(name->data, fi); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
716 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
717 if (rc == NGX_FILE_ERROR) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
718 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
719 of->failed = ngx_file_info_n; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
720 return NGX_FILE_ERROR; |
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 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
723 return rc; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
724 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
725 #else |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
726 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
727 ngx_fd_t fd; |
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 if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
730 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
731 rc = ngx_file_info(name->data, fi); |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
732 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
733 if (rc == NGX_FILE_ERROR) { |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
734 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
735 of->failed = ngx_file_info_n; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
736 return NGX_FILE_ERROR; |
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 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
739 return rc; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
740 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
741 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
742 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
|
743 NGX_FILE_OPEN, 0, log); |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
744 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
745 if (fd == NGX_INVALID_FILE) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
746 return NGX_FILE_ERROR; |
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 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
749 rc = ngx_fd_info(fd, fi); |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
750 |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
751 if (rc == NGX_FILE_ERROR) { |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
752 of->err = ngx_errno; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
753 of->failed = ngx_fd_info_n; |
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 if (ngx_close_file(fd) == NGX_FILE_ERROR) { |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
757 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
758 ngx_close_file_n " \"%V\" failed", name); |
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
759 } |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
760 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
761 return rc; |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
762 #endif |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
763 } |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
764 |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
765 |
1453 | 766 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
|
767 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
|
768 ngx_log_t *log) |
1453 | 769 { |
770 ngx_fd_t fd; | |
771 ngx_file_info_t fi; | |
772 | |
2070 | 773 if (of->fd != NGX_INVALID_FILE) { |
1453 | 774 |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
775 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
|
776 of->fd = NGX_INVALID_FILE; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
777 return NGX_ERROR; |
1453 | 778 } |
779 | |
2070 | 780 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
|
781 goto done; |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
782 } |
1453 | 783 |
2070 | 784 } else if (of->test_dir) { |
785 | |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
786 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
|
787 of->fd = NGX_INVALID_FILE; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
788 return NGX_ERROR; |
2070 | 789 } |
790 | |
2460
225fa4abd76f
test ngx_file_info() result, the bug has been introduced in r2070
Igor Sysoev <igor@sysoev.ru>
parents:
2246
diff
changeset
|
791 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
|
792 goto done; |
1453 | 793 } |
794 } | |
795 | |
2072 | 796 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
|
797 |
ac281bc4c187
use non-blocking open() not to hang on FIFO files, etc.
Igor Sysoev <igor@sysoev.ru>
parents:
3178
diff
changeset
|
798 /* |
ac281bc4c187
use non-blocking open() not to hang on FIFO files, etc.
Igor Sysoev <igor@sysoev.ru>
parents:
3178
diff
changeset
|
799 * 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
|
800 * 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
|
801 */ |
ac281bc4c187
use non-blocking open() not to hang on FIFO files, etc.
Igor Sysoev <igor@sysoev.ru>
parents:
3178
diff
changeset
|
802 |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
803 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
|
804 NGX_FILE_OPEN, 0, log); |
2072 | 805 |
806 } else { | |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
807 fd = ngx_open_file_wrapper(name, of, NGX_FILE_APPEND, |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
808 NGX_FILE_CREATE_OR_OPEN, |
4479
5e6436812c9a
Disable symlinks: cleanup error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4477
diff
changeset
|
809 NGX_FILE_DEFAULT_ACCESS, log); |
2072 | 810 } |
1453 | 811 |
812 if (fd == NGX_INVALID_FILE) { | |
4477
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
813 of->fd = NGX_INVALID_FILE; |
7033faf6dc3c
Added disable_symlinks directive.
Andrey Belov <defan@nginx.com>
parents:
4476
diff
changeset
|
814 return NGX_ERROR; |
1453 | 815 } |
816 | |
817 if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { | |
818 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
|
819 ngx_fd_info_n " \"%V\" failed", name); |
1453 | 820 |
821 if (ngx_close_file(fd) == NGX_FILE_ERROR) { | |
822 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
|
823 ngx_close_file_n " \"%V\" failed", name); |
1453 | 824 } |
825 | |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
826 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
|
827 |
1453 | 828 return NGX_ERROR; |
829 } | |
830 | |
831 if (ngx_is_dir(&fi)) { | |
832 if (ngx_close_file(fd) == NGX_FILE_ERROR) { | |
833 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
|
834 ngx_close_file_n " \"%V\" failed", name); |
1453 | 835 } |
836 | |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
837 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
|
838 |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
839 } else { |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
840 of->fd = fd; |
2129 | 841 |
3178 | 842 if (of->read_ahead && ngx_file_size(&fi) > NGX_MIN_READ_AHEAD) { |
843 if (ngx_read_ahead(fd, of->read_ahead) == NGX_ERROR) { | |
844 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
|
845 ngx_read_ahead_n " \"%V\" failed", name); |
3178 | 846 } |
847 } | |
848 | |
2129 | 849 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
|
850 if (ngx_directio_on(fd) == NGX_FILE_ERROR) { |
2129 | 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_directio_on_n " \"%V\" failed", name); |
2231
8564129d49b6
*) handle unaligned file part for directio
Igor Sysoev <igor@sysoev.ru>
parents:
2129
diff
changeset
|
853 |
8564129d49b6
*) handle unaligned file part for directio
Igor Sysoev <igor@sysoev.ru>
parents:
2129
diff
changeset
|
854 } else { |
8564129d49b6
*) handle unaligned file part for directio
Igor Sysoev <igor@sysoev.ru>
parents:
2129
diff
changeset
|
855 of->is_directio = 1; |
2129 | 856 } |
857 } | |
1453 | 858 } |
859 | |
2069
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
860 done: |
23930ccd2642
use ngx_file_info() and test uniq if file is already open
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
861 |
1453 | 862 of->uniq = ngx_file_uniq(&fi); |
863 of->mtime = ngx_file_mtime(&fi); | |
864 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
|
865 of->fs_size = ngx_file_fs_size(&fi); |
1453 | 866 of->is_dir = ngx_is_dir(&fi); |
867 of->is_file = ngx_is_file(&fi); | |
868 of->is_link = ngx_is_link(&fi); | |
869 of->is_exec = ngx_is_exec(&fi); | |
870 | |
871 return NGX_OK; | |
872 } | |
873 | |
874 | |
1775 | 875 /* |
876 * we ignore any possible event setting error and | |
877 * fallback to usual periodic file retests | |
878 */ | |
879 | |
880 static void | |
881 ngx_open_file_add_event(ngx_open_file_cache_t *cache, | |
882 ngx_cached_open_file_t *file, ngx_open_file_info_t *of, ngx_log_t *log) | |
883 { | |
884 ngx_open_file_cache_event_t *fev; | |
885 | |
886 if (!(ngx_event_flags & NGX_USE_VNODE_EVENT) | |
887 || !of->events | |
888 || file->event | |
889 || of->fd == NGX_INVALID_FILE | |
890 || file->uses < of->min_uses) | |
891 { | |
892 return; | |
893 } | |
894 | |
2070 | 895 file->use_event = 0; |
896 | |
1775 | 897 file->event = ngx_calloc(sizeof(ngx_event_t), log); |
898 if (file->event== NULL) { | |
899 return; | |
900 } | |
901 | |
902 fev = ngx_alloc(sizeof(ngx_open_file_cache_event_t), log); | |
903 if (fev == NULL) { | |
904 ngx_free(file->event); | |
905 file->event = NULL; | |
906 return; | |
907 } | |
908 | |
909 fev->fd = of->fd; | |
910 fev->file = file; | |
911 fev->cache = cache; | |
912 | |
913 file->event->handler = ngx_open_file_cache_remove; | |
914 file->event->data = fev; | |
915 | |
916 /* | |
917 * although vnode event may be called while ngx_cycle->poll | |
918 * destruction, however, cleanup procedures are run before any | |
919 * memory freeing and events will be canceled. | |
920 */ | |
921 | |
922 file->event->log = ngx_cycle->log; | |
923 | |
924 if (ngx_add_event(file->event, NGX_VNODE_EVENT, NGX_ONESHOT_EVENT) | |
925 != NGX_OK) | |
926 { | |
927 ngx_free(file->event->data); | |
928 ngx_free(file->event); | |
929 file->event = NULL; | |
930 return; | |
931 } | |
932 | |
933 /* | |
2071 | 934 * we do not set file->use_event here because there may be a race |
935 * condition: a file may be deleted between opening the file and | |
936 * adding event, so we rely upon event notification only after | |
937 * one file revalidation on next file access | |
1775 | 938 */ |
939 | |
940 return; | |
941 } | |
942 | |
943 | |
1453 | 944 static void |
945 ngx_open_file_cleanup(void *data) | |
946 { | |
947 ngx_open_file_cache_cleanup_t *c = data; | |
948 | |
949 c->file->count--; | |
950 | |
1772 | 951 ngx_close_cached_file(c->cache, c->file, c->min_uses, c->log); |
1453 | 952 |
953 /* drop one or two expired open files */ | |
954 ngx_expire_old_cached_files(c->cache, 1, c->log); | |
955 } | |
956 | |
957 | |
958 static void | |
959 ngx_close_cached_file(ngx_open_file_cache_t *cache, | |
1772 | 960 ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_log_t *log) |
1453 | 961 { |
1772 | 962 ngx_log_debug5(NGX_LOG_DEBUG_CORE, log, 0, |
963 "close cached open file: %s, fd:%d, c:%d, u:%d, %d", | |
964 file->name, file->fd, file->count, file->uses, file->close); | |
1453 | 965 |
966 if (!file->close) { | |
967 | |
968 file->accessed = ngx_time(); | |
969 | |
1765 | 970 ngx_queue_remove(&file->queue); |
1453 | 971 |
1765 | 972 ngx_queue_insert_head(&cache->expire_queue, &file->queue); |
1453 | 973 |
1772 | 974 if (file->uses >= min_uses || file->count) { |
975 return; | |
976 } | |
1453 | 977 } |
978 | |
1775 | 979 ngx_open_file_del_event(file); |
1453 | 980 |
981 if (file->count) { | |
982 return; | |
983 } | |
984 | |
1772 | 985 if (file->fd != NGX_INVALID_FILE) { |
986 | |
987 if (ngx_close_file(file->fd) == NGX_FILE_ERROR) { | |
988 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
989 ngx_close_file_n " \"%s\" failed", file->name); | |
990 } | |
991 | |
992 file->fd = NGX_INVALID_FILE; | |
993 } | |
994 | |
995 if (!file->close) { | |
996 return; | |
1453 | 997 } |
998 | |
999 ngx_free(file->name); | |
1000 ngx_free(file); | |
1001 } | |
1002 | |
1003 | |
1004 static void | |
1775 | 1005 ngx_open_file_del_event(ngx_cached_open_file_t *file) |
1006 { | |
1007 if (file->event == NULL) { | |
1008 return; | |
1009 } | |
1010 | |
1011 (void) ngx_del_event(file->event, NGX_VNODE_EVENT, | |
1012 file->count ? NGX_FLUSH_EVENT : NGX_CLOSE_EVENT); | |
1013 | |
1014 ngx_free(file->event->data); | |
1015 ngx_free(file->event); | |
1016 file->event = NULL; | |
1017 file->use_event = 0; | |
1018 } | |
1019 | |
1020 | |
1021 static void | |
1453 | 1022 ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, ngx_uint_t n, |
1023 ngx_log_t *log) | |
1024 { | |
1025 time_t now; | |
1765 | 1026 ngx_queue_t *q; |
1453 | 1027 ngx_cached_open_file_t *file; |
1028 | |
1029 now = ngx_time(); | |
1030 | |
1031 /* | |
1032 * n == 1 deletes one or two inactive files | |
1033 * n == 0 deletes least recently used file by force | |
1034 * and one or two inactive files | |
1035 */ | |
1036 | |
1037 while (n < 3) { | |
1038 | |
1765 | 1039 if (ngx_queue_empty(&cache->expire_queue)) { |
1453 | 1040 return; |
1041 } | |
1042 | |
1765 | 1043 q = ngx_queue_last(&cache->expire_queue); |
1044 | |
1045 file = ngx_queue_data(q, ngx_cached_open_file_t, queue); | |
1046 | |
1453 | 1047 if (n++ != 0 && now - file->accessed <= cache->inactive) { |
1048 return; | |
1049 } | |
1050 | |
1765 | 1051 ngx_queue_remove(q); |
1453 | 1052 |
1053 ngx_rbtree_delete(&cache->rbtree, &file->node); | |
1054 | |
1055 cache->current--; | |
1056 | |
1057 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, | |
1058 "expire cached open file: %s", file->name); | |
1059 | |
1060 if (!file->err && !file->is_dir) { | |
1061 file->close = 1; | |
1772 | 1062 ngx_close_cached_file(cache, file, 0, log); |
1453 | 1063 |
1064 } else { | |
1065 ngx_free(file->name); | |
1066 ngx_free(file); | |
1067 } | |
1068 } | |
1069 } | |
1070 | |
1071 | |
1072 static void | |
1073 ngx_open_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp, | |
1074 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) | |
1075 { | |
1076 ngx_rbtree_node_t **p; | |
1077 ngx_cached_open_file_t *file, *file_temp; | |
1078 | |
1079 for ( ;; ) { | |
1080 | |
1081 if (node->key < temp->key) { | |
1082 | |
1083 p = &temp->left; | |
1084 | |
1085 } else if (node->key > temp->key) { | |
1086 | |
1087 p = &temp->right; | |
1088 | |
1089 } else { /* node->key == temp->key */ | |
1090 | |
1091 file = (ngx_cached_open_file_t *) node; | |
1092 file_temp = (ngx_cached_open_file_t *) temp; | |
1093 | |
1094 p = (ngx_strcmp(file->name, file_temp->name) < 0) | |
1095 ? &temp->left : &temp->right; | |
1096 } | |
1097 | |
1098 if (*p == sentinel) { | |
1099 break; | |
1100 } | |
1101 | |
1102 temp = *p; | |
1103 } | |
1104 | |
1105 *p = node; | |
1106 node->parent = temp; | |
1107 node->left = sentinel; | |
1108 node->right = sentinel; | |
1109 ngx_rbt_red(node); | |
1110 } | |
1111 | |
1112 | |
1775 | 1113 static ngx_cached_open_file_t * |
1114 ngx_open_file_lookup(ngx_open_file_cache_t *cache, ngx_str_t *name, | |
1115 uint32_t hash) | |
1116 { | |
1117 ngx_int_t rc; | |
1118 ngx_rbtree_node_t *node, *sentinel; | |
1119 ngx_cached_open_file_t *file; | |
1120 | |
1121 node = cache->rbtree.root; | |
1122 sentinel = cache->rbtree.sentinel; | |
1123 | |
1124 while (node != sentinel) { | |
1125 | |
1126 if (hash < node->key) { | |
1127 node = node->left; | |
1128 continue; | |
1129 } | |
1130 | |
1131 if (hash > node->key) { | |
1132 node = node->right; | |
1133 continue; | |
1134 } | |
1135 | |
1136 /* hash == node->key */ | |
1137 | |
1138 do { | |
1139 file = (ngx_cached_open_file_t *) node; | |
1140 | |
1141 rc = ngx_strcmp(name->data, file->name); | |
1142 | |
1143 if (rc == 0) { | |
1144 return file; | |
1145 } | |
1146 | |
1147 node = (rc < 0) ? node->left : node->right; | |
1148 | |
1149 } while (node != sentinel && hash == node->key); | |
1150 | |
1151 break; | |
1152 } | |
1153 | |
1154 return NULL; | |
1155 } | |
1156 | |
1157 | |
1453 | 1158 static void |
1159 ngx_open_file_cache_remove(ngx_event_t *ev) | |
1160 { | |
1161 ngx_cached_open_file_t *file; | |
1162 ngx_open_file_cache_event_t *fev; | |
1163 | |
1164 fev = ev->data; | |
1165 file = fev->file; | |
1166 | |
1765 | 1167 ngx_queue_remove(&file->queue); |
1453 | 1168 |
1169 ngx_rbtree_delete(&fev->cache->rbtree, &file->node); | |
1170 | |
1171 fev->cache->current--; | |
1172 | |
1173 /* NGX_ONESHOT_EVENT was already deleted */ | |
1174 file->event = NULL; | |
2070 | 1175 file->use_event = 0; |
1453 | 1176 |
1177 file->close = 1; | |
1178 | |
1772 | 1179 ngx_close_cached_file(fev->cache, file, 0, ev->log); |
1453 | 1180 |
1181 /* free memory only when fev->cache and fev->file are already not needed */ | |
1182 | |
1183 ngx_free(ev->data); | |
1184 ngx_free(ev); | |
1185 } |