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