blob: fdefacf50b0d9a794ebb96957f77dd7153dc32ae [file] [log] [blame]
Igor Sysoevfd675862003-04-11 16:01:14 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoevfd675862003-04-11 16:01:14 +00007#include <ngx_config.h>
8#include <ngx_core.h>
Igor Sysoevfd675862003-04-11 16:01:14 +00009
10
Igor Sysoev4a715592005-02-24 12:29:09 +000011static ngx_atomic_uint_t ngx_temp_number;
Igor Sysoevabeb1222006-10-23 13:10:10 +000012static ngx_atomic_uint_t ngx_random_number;
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +000013
14
Igor Sysoevd039a2e2005-02-22 14:40:13 +000015ssize_t
16ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain)
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000017{
Igor Sysoevd43bee82004-11-20 19:52:20 +000018 ngx_int_t rc;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000019
20 if (tf->file.fd == NGX_INVALID_FILE) {
Igor Sysoev65977492003-11-02 22:56:18 +000021 rc = ngx_create_temp_file(&tf->file, tf->path, tf->pool,
Igor Sysoevcd5b99a2007-01-25 08:45:04 +000022 tf->persistent, tf->clean, tf->access);
Igor Sysoev5f800782003-12-08 20:48:12 +000023
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000024 if (rc == NGX_ERROR || rc == NGX_AGAIN) {
25 return rc;
26 }
27
Igor Sysoev8f125582006-07-28 15:16:17 +000028 if (tf->log_level) {
29 ngx_log_error(tf->log_level, tf->file.log, 0, "%s %V",
Igor Sysoev7bdb7202006-04-19 15:30:56 +000030 tf->warn, &tf->file.name);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000031 }
32 }
33
Igor Sysoev65977492003-11-02 22:56:18 +000034 return ngx_write_chain_to_file(&tf->file, chain, tf->offset, tf->pool);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000035}
36
37
Igor Sysoevd039a2e2005-02-22 14:40:13 +000038ngx_int_t
39ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool,
Igor Sysoevcd5b99a2007-01-25 08:45:04 +000040 ngx_uint_t persistent, ngx_uint_t clean, ngx_uint_t access)
Igor Sysoevfd675862003-04-11 16:01:14 +000041{
Igor Sysoevb8bfa202007-01-29 20:28:00 +000042 uint32_t n;
Igor Sysoev899b44e2005-05-12 14:58:06 +000043 ngx_err_t err;
Igor Sysoevc2068d02005-10-19 12:33:58 +000044 ngx_pool_cleanup_t *cln;
45 ngx_pool_cleanup_file_t *clnf;
Igor Sysoevfd675862003-04-11 16:01:14 +000046
Igor Sysoevd1a0ee72007-01-29 20:33:51 +000047 file->name.len = path->name.len + 1 + path->len + 10;
Igor Sysoevfd675862003-04-11 16:01:14 +000048
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +000049 file->name.data = ngx_pnalloc(pool, file->name.len + 1);
Igor Sysoevc1571722005-03-19 12:38:37 +000050 if (file->name.data == NULL) {
Igor Sysoevd43bee82004-11-20 19:52:20 +000051 return NGX_ERROR;
52 }
Igor Sysoevfd675862003-04-11 16:01:14 +000053
54#if 0
55 for (i = 0; i < file->name.len; i++) {
56 file->name.data[i] = 'X';
57 }
58#endif
59
60 ngx_memcpy(file->name.data, path->name.data, path->name.len);
61
Igor Sysoevb8bfa202007-01-29 20:28:00 +000062 n = (uint32_t) ngx_next_temp_number(0);
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +000063
Igor Sysoev3b112b82007-12-17 21:23:05 +000064 cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t));
65 if (cln == NULL) {
66 return NGX_ERROR;
67 }
68
Igor Sysoevfd675862003-04-11 16:01:14 +000069 for ( ;; ) {
Igor Sysoev4959ec42005-05-23 12:07:45 +000070 (void) ngx_sprintf(file->name.data + path->name.len + 1 + path->len,
Igor Sysoevb8bfa202007-01-29 20:28:00 +000071 "%010uD%Z", n);
Igor Sysoevfd675862003-04-11 16:01:14 +000072
Igor Sysoev00cbb8a2007-12-17 21:29:34 +000073 ngx_create_hashed_filename(path, file->name.data, file->name.len);
74
75 ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0,
76 "hashed path: %s", file->name.data);
Igor Sysoevfd675862003-04-11 16:01:14 +000077
Igor Sysoevfe1cb8c2007-01-18 19:52:18 +000078 file->fd = ngx_open_tempfile(file->name.data, persistent, access);
Igor Sysoevfd675862003-04-11 16:01:14 +000079
Igor Sysoev54498db2004-02-11 17:08:49 +000080 ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0,
81 "temp fd:%d", file->fd);
Igor Sysoev9e4920b2003-04-14 17:04:58 +000082
Igor Sysoevfd675862003-04-11 16:01:14 +000083 if (file->fd != NGX_INVALID_FILE) {
Igor Sysoev899b44e2005-05-12 14:58:06 +000084
Igor Sysoevcd5b99a2007-01-25 08:45:04 +000085 cln->handler = clean ? ngx_pool_delete_file : ngx_pool_cleanup_file;
Igor Sysoevc2068d02005-10-19 12:33:58 +000086 clnf = cln->data;
Igor Sysoev899b44e2005-05-12 14:58:06 +000087
Igor Sysoevc2068d02005-10-19 12:33:58 +000088 clnf->fd = file->fd;
89 clnf->name = file->name.data;
90 clnf->log = pool->log;
Igor Sysoev899b44e2005-05-12 14:58:06 +000091
Igor Sysoevfd675862003-04-11 16:01:14 +000092 return NGX_OK;
93 }
94
95 err = ngx_errno;
96
97 if (err == NGX_EEXIST) {
Igor Sysoevb8bfa202007-01-29 20:28:00 +000098 n = (uint32_t) ngx_next_temp_number(1);
Igor Sysoevfd675862003-04-11 16:01:14 +000099 continue;
100 }
101
Igor Sysoev3f4685f2004-04-25 20:13:21 +0000102 if ((path->level[0] == 0)
103 || (err != NGX_ENOENT
Igor Sysoev1b735832004-11-11 14:07:14 +0000104#if (NGX_WIN32)
Igor Sysoev3f4685f2004-04-25 20:13:21 +0000105 && err != NGX_ENOTDIR
Igor Sysoevfd675862003-04-11 16:01:14 +0000106#endif
Igor Sysoevd43bee82004-11-20 19:52:20 +0000107 ))
108 {
Igor Sysoevfd675862003-04-11 16:01:14 +0000109 ngx_log_error(NGX_LOG_CRIT, file->log, err,
110 ngx_open_tempfile_n " \"%s\" failed",
111 file->name.data);
112 return NGX_ERROR;
113 }
114
115 if (ngx_create_path(file, path) == NGX_ERROR) {
116 return NGX_ERROR;
Igor Sysoevfa73aac2003-05-21 13:28:21 +0000117 }
Igor Sysoevfd675862003-04-11 16:01:14 +0000118 }
119}
120
121
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000122void
Igor Sysoev00cbb8a2007-12-17 21:29:34 +0000123ngx_create_hashed_filename(ngx_path_t *path, u_char *file, size_t len)
Igor Sysoevfd675862003-04-11 16:01:14 +0000124{
Igor Sysoev00cbb8a2007-12-17 21:29:34 +0000125 size_t i, level;
126 ngx_uint_t n;
Igor Sysoevfd675862003-04-11 16:01:14 +0000127
Igor Sysoev00cbb8a2007-12-17 21:29:34 +0000128 i = path->name.len + 1;
Igor Sysoevfd675862003-04-11 16:01:14 +0000129
Igor Sysoev00cbb8a2007-12-17 21:29:34 +0000130 file[path->name.len + path->len] = '/';
Igor Sysoevfd675862003-04-11 16:01:14 +0000131
Igor Sysoev00cbb8a2007-12-17 21:29:34 +0000132 for (n = 0; n < 3; n++) {
133 level = path->level[n];
Igor Sysoevfd675862003-04-11 16:01:14 +0000134
135 if (level == 0) {
136 break;
137 }
138
Igor Sysoev00cbb8a2007-12-17 21:29:34 +0000139 len -= level;
140 file[i - 1] = '/';
141 ngx_memcpy(&file[i], &file[len], level);
142 i += level + 1;
Igor Sysoevfd675862003-04-11 16:01:14 +0000143 }
Igor Sysoevfd675862003-04-11 16:01:14 +0000144}
145
146
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000147ngx_int_t
148ngx_create_path(ngx_file_t *file, ngx_path_t *path)
Igor Sysoevfd675862003-04-11 16:01:14 +0000149{
Igor Sysoev4959ec42005-05-23 12:07:45 +0000150 size_t pos;
151 ngx_err_t err;
152 ngx_uint_t i;
Igor Sysoevfd675862003-04-11 16:01:14 +0000153
154 pos = path->name.len;
155
156 for (i = 0; i < 3; i++) {
157 if (path->level[i] == 0) {
158 break;
159 }
160
161 pos += path->level[i] + 1;
162
163 file->name.data[pos] = '\0';
164
Igor Sysoev54498db2004-02-11 17:08:49 +0000165 ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0,
166 "temp file: \"%s\"", file->name.data);
Igor Sysoevfd675862003-04-11 16:01:14 +0000167
Igor Sysoevb71c6902006-08-04 16:04:04 +0000168 if (ngx_create_dir(file->name.data, 0700) == NGX_FILE_ERROR) {
Igor Sysoevfd675862003-04-11 16:01:14 +0000169 err = ngx_errno;
170 if (err != NGX_EEXIST) {
171 ngx_log_error(NGX_LOG_CRIT, file->log, err,
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000172 ngx_create_dir_n " \"%s\" failed",
173 file->name.data);
Igor Sysoevfd675862003-04-11 16:01:14 +0000174 return NGX_ERROR;
175 }
176 }
177
178 file->name.data[pos] = '/';
179 }
180
181 return NGX_OK;
182}
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000183
184
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000185ngx_err_t
Igor Sysoevb71c6902006-08-04 16:04:04 +0000186ngx_create_full_path(u_char *dir, ngx_uint_t access)
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000187{
188 u_char *p, ch;
189 ngx_err_t err;
190
191 for (p = dir + 1; *p; p++) {
192 ch = *p;
193
194 if (ch != '/') {
195 continue;
196 }
197
198 *p = '\0';
199
Igor Sysoevb71c6902006-08-04 16:04:04 +0000200 if (ngx_create_dir(dir, access) == NGX_FILE_ERROR) {
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000201 err = ngx_errno;
202 if (err != NGX_EEXIST) {
203 return err;
204 }
205 }
206
207 *p = '/';
208 }
209
210 return 0;
211}
212
213
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000214void
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000215ngx_init_temp_number(void)
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000216{
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000217 ngx_temp_number = 0;
Igor Sysoevabeb1222006-10-23 13:10:10 +0000218 ngx_random_number = 123456;
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000219}
220
221
Igor Sysoev4a715592005-02-24 12:29:09 +0000222ngx_atomic_uint_t
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000223ngx_next_temp_number(ngx_uint_t collision)
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000224{
225 if (collision) {
Igor Sysoevabeb1222006-10-23 13:10:10 +0000226 ngx_temp_number += ngx_random_number;
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000227 }
228
229 return ngx_temp_number++;
230}
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000231
232
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000233char *
234ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000235{
236 char *p = conf;
237
Igor Sysoevd43bee82004-11-20 19:52:20 +0000238 ssize_t level;
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000239 ngx_str_t *value;
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000240 ngx_uint_t i, n;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000241 ngx_path_t *path, **slot;
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000242
Igor Sysoevd43bee82004-11-20 19:52:20 +0000243 slot = (ngx_path_t **) (p + cmd->offset);
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000244
Igor Sysoevd43bee82004-11-20 19:52:20 +0000245 if (*slot) {
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000246 return "is duplicate";
247 }
248
Igor Sysoevc1571722005-03-19 12:38:37 +0000249 path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t));
250 if (path == NULL) {
Igor Sysoevd43bee82004-11-20 19:52:20 +0000251 return NGX_CONF_ERROR;
252 }
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000253
Igor Sysoevd43bee82004-11-20 19:52:20 +0000254 value = cf->args->elts;
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000255
256 path->name = value[1];
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000257
Igor Sysoev3186bf52006-07-03 16:49:20 +0000258 if (path->name.data[path->name.len - 1] == '/') {
259 path->name.len--;
260 }
261
Igor Sysoeva1df4162007-07-29 18:05:45 +0000262 if (ngx_conf_full_name(cf->cycle, &path->name, 0) == NGX_ERROR) {
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000263 return NULL;
264 }
265
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000266 path->len = 0;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000267 path->cleaner = (ngx_gc_handler_pt) cmd->post;
Igor Sysoevd43bee82004-11-20 19:52:20 +0000268 path->conf_file = cf->conf_file->file.name.data;
269 path->line = cf->conf_file->line;
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000270
271 for (i = 0, n = 2; n < cf->args->nelts; i++, n++) {
Igor Sysoevd9d0ca12003-11-21 06:30:49 +0000272 level = ngx_atoi(value[n].data, value[n].len);
273 if (level == NGX_ERROR || level == 0) {
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000274 return "invalid value";
275 }
276
Igor Sysoeva8fa0a62003-11-25 20:44:56 +0000277 path->level[i] = level;
278 path->len += level + 1;
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000279 }
280
281 while (i < 3) {
282 path->level[i++] = 0;
283 }
284
Igor Sysoev02025fd2005-01-18 13:03:58 +0000285 *slot = path;
Igor Sysoevd43bee82004-11-20 19:52:20 +0000286
Igor Sysoev02025fd2005-01-18 13:03:58 +0000287 if (ngx_add_path(cf, slot) == NGX_ERROR) {
288 return NGX_CONF_ERROR;
289 }
290
291 return NGX_CONF_OK;
292}
293
294
Igor Sysoev58feb532007-07-12 11:19:05 +0000295char *
296ngx_conf_set_access_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
297{
298 char *confp = conf;
299
300 u_char *p;
301 ngx_str_t *value;
302 ngx_uint_t i, right, shift, *access;
303
304 access = (ngx_uint_t *) (confp + cmd->offset);
Igor Sysoevfbd9b432007-07-13 08:30:34 +0000305
Igor Sysoev58feb532007-07-12 11:19:05 +0000306 if (*access != NGX_CONF_UNSET_UINT) {
307 return "is duplicate";
308 }
Igor Sysoevfbd9b432007-07-13 08:30:34 +0000309
Igor Sysoev58feb532007-07-12 11:19:05 +0000310 value = cf->args->elts;
311
312 *access = 0600;
313
314 for (i = 1; i < cf->args->nelts; i++) {
315
316 p = value[i].data;
317
318 if (ngx_strncmp(p, "user:", sizeof("user:") - 1) == 0) {
319 shift = 6;
320 p += sizeof("user:") - 1;
321
322 } else if (ngx_strncmp(p, "group:", sizeof("group:") - 1) == 0) {
323 shift = 3;
324 p += sizeof("group:") - 1;
325
326 } else if (ngx_strncmp(p, "all:", sizeof("all:") - 1) == 0) {
327 shift = 0;
328 p += sizeof("all:") - 1;
329
Igor Sysoev58feb532007-07-12 11:19:05 +0000330 } else {
331 goto invalid;
332 }
333
334 if (ngx_strcmp(p, "rw") == 0) {
335 right = 6;
336
337 } else if (ngx_strcmp(p, "r") == 0) {
338 right = 4;
339
340 } else {
341 goto invalid;
342 }
343
344 *access |= right << shift;
345 }
Igor Sysoevfbd9b432007-07-13 08:30:34 +0000346
Igor Sysoev58feb532007-07-12 11:19:05 +0000347 return NGX_CONF_OK;
348
349invalid:
350
351 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid value \"%V\"", &value[i]);
352
353 return NGX_CONF_ERROR;
354}
355
356
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000357ngx_int_t
358ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot)
Igor Sysoev02025fd2005-01-18 13:03:58 +0000359{
360 ngx_uint_t i, n;
361 ngx_path_t *path, **p;
362
363 path = *slot;
364
365 p = cf->cycle->pathes.elts;
Igor Sysoevd43bee82004-11-20 19:52:20 +0000366 for (i = 0; i < cf->cycle->pathes.nelts; i++) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000367 if (p[i]->name.len == path->name.len
368 && ngx_strcmp(p[i]->name.data, path->name.data) == 0)
Igor Sysoevd43bee82004-11-20 19:52:20 +0000369 {
370 for (n = 0; n < 3; n++) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000371 if (p[i]->level[n] != path->level[n]) {
372 if (path->conf_file == NULL) {
Igor Sysoev3259e852005-01-19 13:10:56 +0000373 if (p[i]->conf_file == NULL) {
374 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
375 "the default path name \"%V\" has "
376 "the same name as another default path, "
377 "but the different levels, you need to "
378 "redefine one of them in http section",
379 &p[i]->name);
380 return NGX_ERROR;
381 }
382
Igor Sysoev02025fd2005-01-18 13:03:58 +0000383 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
384 "the path name \"%V\" in %s:%ui has "
Igor Sysoev3259e852005-01-19 13:10:56 +0000385 "the same name as default path, but "
Igor Sysoev02025fd2005-01-18 13:03:58 +0000386 "the different levels, you need to "
387 "define default path in http section",
388 &p[i]->name, p[i]->conf_file, p[i]->line);
389 return NGX_ERROR;
390 }
391
Igor Sysoevd43bee82004-11-20 19:52:20 +0000392 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Igor Sysoev02025fd2005-01-18 13:03:58 +0000393 "the same path name \"%V\" in %s:%ui "
394 "has the different levels than",
395 &p[i]->name, p[i]->conf_file, p[i]->line);
396 return NGX_ERROR;
Igor Sysoevd43bee82004-11-20 19:52:20 +0000397 }
398
Igor Sysoev02025fd2005-01-18 13:03:58 +0000399 if (p[i]->level[n] == 0) {
Igor Sysoevd43bee82004-11-20 19:52:20 +0000400 break;
401 }
402 }
403
Igor Sysoev02025fd2005-01-18 13:03:58 +0000404 *slot = p[i];
Igor Sysoevd43bee82004-11-20 19:52:20 +0000405
Igor Sysoev02025fd2005-01-18 13:03:58 +0000406 return NGX_OK;
Igor Sysoevd43bee82004-11-20 19:52:20 +0000407 }
408 }
409
Igor Sysoevc1571722005-03-19 12:38:37 +0000410 p = ngx_array_push(&cf->cycle->pathes);
411 if (p == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000412 return NGX_ERROR;
Igor Sysoevd43bee82004-11-20 19:52:20 +0000413 }
414
Igor Sysoev02025fd2005-01-18 13:03:58 +0000415 *p = path;
Igor Sysoev1b138ed2003-11-18 21:34:08 +0000416
Igor Sysoev02025fd2005-01-18 13:03:58 +0000417 return NGX_OK;
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000418}
Igor Sysoevd43bee82004-11-20 19:52:20 +0000419
420
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000421ngx_int_t
422ngx_create_pathes(ngx_cycle_t *cycle, ngx_uid_t user)
Igor Sysoevd43bee82004-11-20 19:52:20 +0000423{
424 ngx_err_t err;
425 ngx_uint_t i;
426 ngx_path_t **path;
Igor Sysoevd43bee82004-11-20 19:52:20 +0000427
428 path = cycle->pathes.elts;
429 for (i = 0; i < cycle->pathes.nelts; i++) {
430
Igor Sysoevb71c6902006-08-04 16:04:04 +0000431 if (ngx_create_dir(path[i]->name.data, 0700) == NGX_FILE_ERROR) {
Igor Sysoevd43bee82004-11-20 19:52:20 +0000432 err = ngx_errno;
433 if (err != NGX_EEXIST) {
434 ngx_log_error(NGX_LOG_EMERG, cycle->log, err,
435 ngx_create_dir_n " \"%s\" failed",
436 path[i]->name.data);
437 return NGX_ERROR;
438 }
439 }
440
Igor Sysoev4959ec42005-05-23 12:07:45 +0000441 if (user == (ngx_uid_t) NGX_CONF_UNSET_UINT) {
Igor Sysoevd43bee82004-11-20 19:52:20 +0000442 continue;
443 }
444
445#if !(NGX_WIN32)
Igor Sysoev86ef6aa2007-12-10 12:09:51 +0000446 {
447 ngx_file_info_t fi;
Igor Sysoevd43bee82004-11-20 19:52:20 +0000448
449 if (ngx_file_info((const char *) path[i]->name.data, &fi) == -1) {
450 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
451 ngx_file_info_n " \"%s\" failed", path[i]->name.data);
452 return NGX_ERROR;
453 }
454
455 if (fi.st_uid != user) {
456 if (chown((const char *) path[i]->name.data, user, -1) == -1) {
457 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
458 "chown(\"%s\", %d) failed",
459 path[i]->name.data, user);
460 return NGX_ERROR;
461 }
462 }
463
464 if ((fi.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR))
465 != (S_IRUSR|S_IWUSR|S_IXUSR))
466 {
467 fi.st_mode |= (S_IRUSR|S_IWUSR|S_IXUSR);
468
469 if (chmod((const char *) path[i]->name.data, fi.st_mode) == -1) {
470 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
471 "chmod() \"%s\" failed", path[i]->name.data);
472 return NGX_ERROR;
473 }
474 }
Igor Sysoev86ef6aa2007-12-10 12:09:51 +0000475 }
Igor Sysoevd43bee82004-11-20 19:52:20 +0000476#endif
477 }
478
479 return NGX_OK;
480}
Igor Sysoev60d30e62006-12-25 12:38:00 +0000481
482
483ngx_int_t
Igor Sysoev501fc742008-01-03 22:16:37 +0000484ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext)
Igor Sysoeve9af6902007-12-07 20:22:03 +0000485{
486 ngx_err_t err;
487
488#if !(NGX_WIN32)
489
Igor Sysoev524f54f2008-12-10 14:53:45 +0000490 if (ext->access) {
491 if (ngx_change_file_access(src->data, ext->access) == NGX_FILE_ERROR) {
492 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno,
493 ngx_change_file_access_n " \"%s\" failed", src->data);
494 err = 0;
495 goto failed;
496 }
Igor Sysoeve9af6902007-12-07 20:22:03 +0000497 }
498
499#endif
500
Igor Sysoev501fc742008-01-03 22:16:37 +0000501 if (ext->time != -1) {
502 if (ngx_set_file_time(src->data, ext->fd, ext->time) != NGX_OK) {
503 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno,
504 ngx_set_file_time_n " \"%s\" failed", src->data);
505 err = 0;
506 goto failed;
507 }
508 }
509
Igor Sysoeve9af6902007-12-07 20:22:03 +0000510 if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) {
511 return NGX_OK;
512 }
513
514 err = ngx_errno;
515
516 if (err == NGX_ENOENT) {
517
Igor Sysoev501fc742008-01-03 22:16:37 +0000518 if (!ext->create_path) {
Igor Sysoeve9af6902007-12-07 20:22:03 +0000519 goto failed;
520 }
521
Igor Sysoev524f54f2008-12-10 14:53:45 +0000522 err = ngx_create_full_path(to->data, ngx_dir_access(ext->path_access));
Igor Sysoeve9af6902007-12-07 20:22:03 +0000523
524 if (err) {
Igor Sysoev501fc742008-01-03 22:16:37 +0000525 ngx_log_error(NGX_LOG_CRIT, ext->log, err,
Igor Sysoeve9af6902007-12-07 20:22:03 +0000526 ngx_create_dir_n " \"%s\" failed", to->data);
527 err = 0;
528 goto failed;
529 }
530
531 if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) {
532 return NGX_OK;
533 }
534
535 err = ngx_errno;
536 goto failed;
537 }
538
539#if (NGX_WIN32)
540
541 if (err == NGX_EEXIST) {
Igor Sysoev501fc742008-01-03 22:16:37 +0000542 if (ngx_win32_rename_file(src, to, ext->log) == NGX_OK) {
Igor Sysoeve9af6902007-12-07 20:22:03 +0000543
544 if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) {
545 return NGX_OK;
546 }
547
548 err = ngx_errno;
549
550 } else {
551 err = 0;
552 }
553 }
554
555#endif
556
557failed:
558
Igor Sysoev34cec292008-03-03 16:32:16 +0000559 if (ext->delete_file) {
Igor Sysoeve9af6902007-12-07 20:22:03 +0000560 if (ngx_delete_file(src->data) == NGX_FILE_ERROR) {
Igor Sysoev501fc742008-01-03 22:16:37 +0000561 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno,
Igor Sysoeve9af6902007-12-07 20:22:03 +0000562 ngx_delete_file_n " \"%s\" failed", src->data);
563 }
564 }
565
Igor Sysoev524f54f2008-12-10 14:53:45 +0000566 if (err && ext->log_rename_error) {
Igor Sysoev501fc742008-01-03 22:16:37 +0000567 ngx_log_error(NGX_LOG_CRIT, ext->log, err,
Igor Sysoeve9af6902007-12-07 20:22:03 +0000568 ngx_rename_file_n " \"%s\" to \"%s\" failed",
569 src->data, to->data);
570 }
571
Igor Sysoev524f54f2008-12-10 14:53:45 +0000572 ext->rename_error = err;
573
Igor Sysoeve9af6902007-12-07 20:22:03 +0000574 return NGX_ERROR;
575}
576
577
Igor Sysoev9461d6e2007-12-18 18:04:37 +0000578/*
579 * ctx->init_handler() - see ctx->alloc
580 * ctx->file_handler() - file handler
581 * ctx->pre_tree_handler() - handler is called before entering directory
582 * ctx->post_tree_handler() - handler is called after leaving directory
583 * ctx->spec_handler() - special (socket, FIFO, etc.) file handler
584 *
585 * ctx->data - some data structure, it may be the same on all levels, or
586 * reallocated if ctx->alloc is nonzero
587 *
588 * ctx->alloc - a size of data structure that is allocated at every level
589 * and is initilialized by ctx->init_handler()
590 *
591 * ctx->log - a log
592 *
593 * on fatal (memory) error handler must return NGX_ABORT to stop walking tree
594 */
595
Igor Sysoeve9af6902007-12-07 20:22:03 +0000596ngx_int_t
Igor Sysoev60d30e62006-12-25 12:38:00 +0000597ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_str_t *tree)
598{
599 void *data, *prev;
600 u_char *p, *name;
601 size_t len;
602 ngx_int_t rc;
603 ngx_err_t err;
Igor Sysoev5f0b82a2007-01-03 18:12:32 +0000604 ngx_str_t file, buf;
Igor Sysoev60d30e62006-12-25 12:38:00 +0000605 ngx_dir_t dir;
606
607 buf.len = 0;
608 buf.data = NULL;
609
610 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
611 "walk tree \"%V\"", tree);
612
613 if (ngx_open_dir(tree, &dir) == NGX_ERROR) {
614 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
615 ngx_open_dir_n " \"%s\" failed", tree->data);
616 return NGX_ERROR;
617 }
618
619 prev = ctx->data;
620
Igor Sysoevf5a359b2007-01-18 21:04:31 +0000621 if (ctx->alloc) {
622 data = ngx_alloc(ctx->alloc, ctx->log);
Igor Sysoev60d30e62006-12-25 12:38:00 +0000623 if (data == NULL) {
624 goto failed;
625 }
626
627 if (ctx->init_handler(data, prev) == NGX_ABORT) {
628 goto failed;
629 }
630
631 ctx->data = data;
Igor Sysoevb1ccbda2007-07-19 19:11:57 +0000632
633 } else {
634 data = NULL;
Igor Sysoev60d30e62006-12-25 12:38:00 +0000635 }
636
637 for ( ;; ) {
638
639 ngx_set_errno(0);
640
641 if (ngx_read_dir(&dir) == NGX_ERROR) {
642 err = ngx_errno;
643
644 if (err == NGX_ENOMOREFILES) {
645 rc = NGX_OK;
646
647 } else {
648 ngx_log_error(NGX_LOG_CRIT, ctx->log, err,
649 ngx_read_dir_n " \"%s\" failed", tree->data);
650 rc = NGX_ERROR;
651 }
652
653 goto done;
654 }
655
656 len = ngx_de_namelen(&dir);
657 name = ngx_de_name(&dir);
658
659 ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->log, 0,
660 "tree name %uz:\"%s\"", len, name);
661
662 if (len == 1 && name[0] == '.') {
663 continue;
664 }
665
666 if (len == 2 && name[0] == '.' && name[1] == '.') {
667 continue;
668 }
669
670 file.len = tree->len + 1 + len;
671
672 if (file.len + NGX_DIR_MASK_LEN > buf.len) {
673
674 if (buf.len) {
675 ngx_free(buf.data);
676 }
677
678 buf.len = tree->len + 1 + len + NGX_DIR_MASK_LEN;
679
680 buf.data = ngx_alloc(buf.len + 1, ctx->log);
681 if (buf.data == NULL) {
682 goto failed;
683 }
684 }
685
686 p = ngx_cpymem(buf.data, tree->data, tree->len);
687 *p++ = '/';
688 ngx_memcpy(p, name, len + 1);
689
690 file.data = buf.data;
691
692 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
693 "tree path \"%s\"", file.data);
694
695 if (!dir.valid_info) {
696 if (ngx_de_info(file.data, &dir) == NGX_FILE_ERROR) {
697 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
698 ngx_de_info_n " \"%s\" failed", file.data);
699 continue;
700 }
701 }
702
703 if (ngx_de_is_file(&dir)) {
704
705 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
706 "tree file \"%s\"", file.data);
707
Igor Sysoevf5a359b2007-01-18 21:04:31 +0000708 ctx->size = ngx_de_size(&dir);
709 ctx->access = ngx_de_access(&dir);
710 ctx->mtime = ngx_de_mtime(&dir);
711
Igor Sysoev60d30e62006-12-25 12:38:00 +0000712 if (ctx->file_handler(ctx, &file) == NGX_ABORT) {
713 goto failed;
714 }
715
716 } else if (ngx_de_is_dir(&dir)) {
717
718 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
719 "tree enter dir \"%s\"", file.data);
720
Igor Sysoevf5a359b2007-01-18 21:04:31 +0000721 ctx->access = ngx_de_access(&dir);
722 ctx->mtime = ngx_de_mtime(&dir);
723
Igor Sysoev60d30e62006-12-25 12:38:00 +0000724 if (ctx->pre_tree_handler(ctx, &file) == NGX_ABORT) {
725 goto failed;
726 }
727
728 if (ngx_walk_tree(ctx, &file) == NGX_ABORT) {
729 goto failed;
730 }
731
Igor Sysoevf5a359b2007-01-18 21:04:31 +0000732 ctx->access = ngx_de_access(&dir);
733 ctx->mtime = ngx_de_mtime(&dir);
734
Igor Sysoev60d30e62006-12-25 12:38:00 +0000735 if (ctx->post_tree_handler(ctx, &file) == NGX_ABORT) {
736 goto failed;
737 }
738
739 } else {
740
741 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
742 "tree special \"%s\"", file.data);
743
744 if (ctx->spec_handler(ctx, &file) == NGX_ABORT) {
745 goto failed;
746 }
747 }
748 }
749
750failed:
751
752 rc = NGX_ABORT;
753
754done:
755
756 if (buf.len) {
757 ngx_free(buf.data);
758 }
759
Igor Sysoevb1ccbda2007-07-19 19:11:57 +0000760 if (data) {
761 ngx_free(data);
Igor Sysoev60d30e62006-12-25 12:38:00 +0000762 ctx->data = prev;
763 }
764
765 if (ngx_close_dir(&dir) == NGX_ERROR) {
766 ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
767 ngx_close_dir_n " \"%s\" failed", tree->data);
768 }
769
770 return rc;
771}