Mercurial > hg > nginx
annotate src/core/ngx_open_file_cache.c @ 9180:782535848b3e
Updated OpenSSL and zlib used for win32 builds.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 23 Oct 2023 21:50:26 +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 } |