blob: bb30c1e16eedef5a0a279345682065ebd86e9405 [file] [log] [blame]
Igor Sysoev83661a92002-08-23 16:14:30 +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 Sysoevfcd21fe2002-12-19 17:49:51 +00007#include <ngx_config.h>
Igor Sysoeva58e3ca2002-09-02 14:48:24 +00008#include <ngx_core.h>
Igor Sysoevfd675862003-04-11 16:01:14 +00009
Igor Sysoev83661a92002-08-23 16:14:30 +000010
Igor Sysoev78452232005-10-12 13:50:36 +000011ssize_t
12ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
Igor Sysoev83661a92002-08-23 16:14:30 +000013{
Igor Sysoev78452232005-10-12 13:50:36 +000014 ssize_t n;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000015
Igor Sysoev54498db2004-02-11 17:08:49 +000016 ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +000017 "read: %d, %p, %uz, %O", file->fd, buf, size, offset);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000018
Igor Sysoevf6906042004-11-25 16:17:31 +000019#if (NGX_HAVE_PREAD)
Igor Sysoev562e53e2003-11-13 06:14:05 +000020
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000021 n = pread(file->fd, buf, size, offset);
22
Igor Sysoev96f83772002-09-07 10:14:25 +000023 if (n == -1) {
Igor Sysoev54498db2004-02-11 17:08:49 +000024 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
Igor Sysoevf4d97e22009-09-24 20:04:10 +000025 "pread() \"%s\" failed", file->name.data);
Igor Sysoev96f83772002-09-07 10:14:25 +000026 return NGX_ERROR;
27 }
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000028
Igor Sysoev562e53e2003-11-13 06:14:05 +000029#else
30
Igor Sysoev1b138ed2003-11-18 21:34:08 +000031 if (file->sys_offset != offset) {
Igor Sysoev562e53e2003-11-13 06:14:05 +000032 if (lseek(file->fd, offset, SEEK_SET) == -1) {
Igor Sysoevf4d97e22009-09-24 20:04:10 +000033 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
34 "lseek() \"%s\" failed", file->name.data);
Igor Sysoev562e53e2003-11-13 06:14:05 +000035 return NGX_ERROR;
36 }
Igor Sysoev562e53e2003-11-13 06:14:05 +000037
Igor Sysoev160d7742003-11-19 16:26:41 +000038 file->sys_offset = offset;
39 }
Igor Sysoev1b138ed2003-11-18 21:34:08 +000040
Igor Sysoev562e53e2003-11-13 06:14:05 +000041 n = read(file->fd, buf, size);
42
43 if (n == -1) {
Igor Sysoevf4d97e22009-09-24 20:04:10 +000044 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
45 "read() \"%s\" failed", file->name.data);
Igor Sysoev562e53e2003-11-13 06:14:05 +000046 return NGX_ERROR;
47 }
48
Igor Sysoev1b138ed2003-11-18 21:34:08 +000049 file->sys_offset += n;
50
Igor Sysoev562e53e2003-11-13 06:14:05 +000051#endif
52
Igor Sysoev41d5a4f2002-12-21 17:14:50 +000053 file->offset += n;
54
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000055 return n;
Igor Sysoev83661a92002-08-23 16:14:30 +000056}
57
Igor Sysoevcde24782003-04-10 15:08:54 +000058
Igor Sysoev78452232005-10-12 13:50:36 +000059ssize_t
60ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
Igor Sysoevcde24782003-04-10 15:08:54 +000061{
Igor Sysoev78452232005-10-12 13:50:36 +000062 ssize_t n;
Igor Sysoevcde24782003-04-10 15:08:54 +000063
Igor Sysoev1b735832004-11-11 14:07:14 +000064 ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
65 "write: %d, %p, %uz, %O", file->fd, buf, size, offset);
66
Igor Sysoevf6906042004-11-25 16:17:31 +000067#if (NGX_HAVE_PWRITE)
Igor Sysoev562e53e2003-11-13 06:14:05 +000068
Igor Sysoevcde24782003-04-10 15:08:54 +000069 n = pwrite(file->fd, buf, size, offset);
70
71 if (n == -1) {
Igor Sysoevf4d97e22009-09-24 20:04:10 +000072 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
73 "pwrite() \"%s\" failed", file->name.data);
Igor Sysoevcde24782003-04-10 15:08:54 +000074 return NGX_ERROR;
75 }
76
Igor Sysoevfd675862003-04-11 16:01:14 +000077 if ((size_t) n != size) {
78 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
Igor Sysoevf4d97e22009-09-24 20:04:10 +000079 "pwrite() \"%s\" has written only %z of %uz",
80 file->name.data, n, size);
Igor Sysoevcde24782003-04-10 15:08:54 +000081 return NGX_ERROR;
82 }
83
Igor Sysoev562e53e2003-11-13 06:14:05 +000084#else
85
Igor Sysoev1b138ed2003-11-18 21:34:08 +000086 if (file->sys_offset != offset) {
Igor Sysoev562e53e2003-11-13 06:14:05 +000087 if (lseek(file->fd, offset, SEEK_SET) == -1) {
Igor Sysoevf4d97e22009-09-24 20:04:10 +000088 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
89 "lseek() \"%s\" failed", file->name.data);
Igor Sysoev562e53e2003-11-13 06:14:05 +000090 return NGX_ERROR;
91 }
Igor Sysoev562e53e2003-11-13 06:14:05 +000092
Igor Sysoev160d7742003-11-19 16:26:41 +000093 file->sys_offset = offset;
94 }
Igor Sysoev1b138ed2003-11-18 21:34:08 +000095
Igor Sysoev562e53e2003-11-13 06:14:05 +000096 n = write(file->fd, buf, size);
97
98 if (n == -1) {
Igor Sysoevf4d97e22009-09-24 20:04:10 +000099 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
100 "write() \"%s\" failed", file->name.data);
Igor Sysoev562e53e2003-11-13 06:14:05 +0000101 return NGX_ERROR;
102 }
103
104 if ((size_t) n != size) {
105 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
Igor Sysoevf4d97e22009-09-24 20:04:10 +0000106 "write() \"%s\" has written only %z of %uz",
107 file->name.data, n, size);
Igor Sysoev562e53e2003-11-13 06:14:05 +0000108 return NGX_ERROR;
109 }
110
Igor Sysoev1b138ed2003-11-18 21:34:08 +0000111 file->sys_offset += n;
112
Igor Sysoev562e53e2003-11-13 06:14:05 +0000113#endif
114
Igor Sysoevcde24782003-04-10 15:08:54 +0000115 file->offset += n;
116
117 return n;
118}
119
120
Igor Sysoev78452232005-10-12 13:50:36 +0000121ngx_fd_t
Igor Sysoevfe1cb8c2007-01-18 19:52:18 +0000122ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
Igor Sysoevdbb27762004-04-01 16:20:53 +0000123{
124 ngx_fd_t fd;
125
Igor Sysoevfe1cb8c2007-01-18 19:52:18 +0000126 fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,
127 access ? access : 0600);
Igor Sysoevdbb27762004-04-01 16:20:53 +0000128
129 if (fd != -1 && !persistent) {
130 unlink((const char *) name);
131 }
132
133 return fd;
134}
135
136
Igor Sysoev1b735832004-11-11 14:07:14 +0000137#define NGX_IOVS 8
138
Igor Sysoev78452232005-10-12 13:50:36 +0000139ssize_t
140ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
141 ngx_pool_t *pool)
Igor Sysoevfd675862003-04-11 16:01:14 +0000142{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000143 u_char *prev;
Igor Sysoevfd675862003-04-11 16:01:14 +0000144 size_t size;
145 ssize_t n;
Igor Sysoev1b735832004-11-11 14:07:14 +0000146 ngx_array_t vec;
147 struct iovec *iov, iovs[NGX_IOVS];
Igor Sysoevfd675862003-04-11 16:01:14 +0000148
Igor Sysoev1b735832004-11-11 14:07:14 +0000149 /* use pwrite() if there is the only buf in a chain */
Igor Sysoevfd675862003-04-11 16:01:14 +0000150
Igor Sysoev65977492003-11-02 22:56:18 +0000151 if (cl->next == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +0000152 return ngx_write_file(file, cl->buf->pos,
153 (size_t) (cl->buf->last - cl->buf->pos),
Igor Sysoevd9d0ca12003-11-21 06:30:49 +0000154 offset);
Igor Sysoevfd675862003-04-11 16:01:14 +0000155 }
156
Igor Sysoev1b735832004-11-11 14:07:14 +0000157 vec.elts = iovs;
158 vec.size = sizeof(struct iovec);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000159 vec.nalloc = NGX_IOVS;
Igor Sysoev1b735832004-11-11 14:07:14 +0000160 vec.pool = pool;
Igor Sysoevfd675862003-04-11 16:01:14 +0000161
Igor Sysoev1b735832004-11-11 14:07:14 +0000162 do {
163 prev = NULL;
164 iov = NULL;
165 size = 0;
Igor Sysoev65977492003-11-02 22:56:18 +0000166
Igor Sysoev1b735832004-11-11 14:07:14 +0000167 vec.nelts = 0;
Igor Sysoev65977492003-11-02 22:56:18 +0000168
Igor Sysoev1b735832004-11-11 14:07:14 +0000169 /* create the iovec and coalesce the neighbouring bufs */
Igor Sysoev65977492003-11-02 22:56:18 +0000170
Igor Sysoev1b735832004-11-11 14:07:14 +0000171 while (cl && vec.nelts < IOV_MAX) {
172 if (prev == cl->buf->pos) {
173 iov->iov_len += cl->buf->last - cl->buf->pos;
174
175 } else {
Igor Sysoevc1571722005-03-19 12:38:37 +0000176 iov = ngx_array_push(&vec);
177 if (iov == NULL) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000178 return NGX_ERROR;
179 }
180
181 iov->iov_base = (void *) cl->buf->pos;
182 iov->iov_len = cl->buf->last - cl->buf->pos;
183 }
184
185 size += cl->buf->last - cl->buf->pos;
186 prev = cl->buf->last;
187 cl = cl->next;
Igor Sysoev65977492003-11-02 22:56:18 +0000188 }
189
Igor Sysoev1b735832004-11-11 14:07:14 +0000190 /* use pwrite() if there is the only iovec buffer */
Igor Sysoev65977492003-11-02 22:56:18 +0000191
Igor Sysoev1b735832004-11-11 14:07:14 +0000192 if (vec.nelts == 1) {
193 iov = vec.elts;
194 return ngx_write_file(file, (u_char *) iov[0].iov_base,
195 iov[0].iov_len, offset);
196 }
Igor Sysoev65977492003-11-02 22:56:18 +0000197
Igor Sysoev1b735832004-11-11 14:07:14 +0000198 if (file->sys_offset != offset) {
199 if (lseek(file->fd, offset, SEEK_SET) == -1) {
200 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
Igor Sysoevf4d97e22009-09-24 20:04:10 +0000201 "lseek() \"%s\" failed", file->name.data);
Igor Sysoev1b735832004-11-11 14:07:14 +0000202 return NGX_ERROR;
203 }
Igor Sysoevfd675862003-04-11 16:01:14 +0000204
Igor Sysoev1b735832004-11-11 14:07:14 +0000205 file->sys_offset = offset;
206 }
207
208 n = writev(file->fd, vec.elts, vec.nelts);
209
210 if (n == -1) {
211 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
Igor Sysoevf4d97e22009-09-24 20:04:10 +0000212 "writev() \"%s\" failed", file->name.data);
Igor Sysoev5bf3d252003-10-22 07:05:29 +0000213 return NGX_ERROR;
214 }
Igor Sysoevfd675862003-04-11 16:01:14 +0000215
Igor Sysoev1b735832004-11-11 14:07:14 +0000216 if ((size_t) n != size) {
217 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
Igor Sysoevf4d97e22009-09-24 20:04:10 +0000218 "writev() \"%s\" has written only %z of %uz",
219 file->name.data, n, size);
Igor Sysoev1b735832004-11-11 14:07:14 +0000220 return NGX_ERROR;
221 }
Igor Sysoev1b138ed2003-11-18 21:34:08 +0000222
Igor Sysoev1b735832004-11-11 14:07:14 +0000223 file->sys_offset += n;
224 file->offset += n;
Igor Sysoevfd675862003-04-11 16:01:14 +0000225
Igor Sysoev1b735832004-11-11 14:07:14 +0000226 } while (cl);
Igor Sysoevfd675862003-04-11 16:01:14 +0000227
228 return n;
229}
230
231
Igor Sysoev78452232005-10-12 13:50:36 +0000232ngx_int_t
Igor Sysoevda173ab2006-08-30 10:39:17 +0000233ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
234{
235 struct timeval tv[2];
236
237 tv[0].tv_sec = s;
238 tv[0].tv_usec = 0;
239 tv[1].tv_sec = s;
240 tv[1].tv_usec = 0;
241
242 if (utimes((char *) name, tv) != -1) {
243 return NGX_OK;
244 }
245
246 return NGX_ERROR;
247}
248
249
250ngx_int_t
Igor Sysoev78452232005-10-12 13:50:36 +0000251ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000252{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000253 dir->dir = opendir((const char *) name->data);
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000254
255 if (dir->dir == NULL) {
256 return NGX_ERROR;
257 }
258
Igor Sysoev723e6cc2004-10-25 15:29:23 +0000259 dir->valid_info = 0;
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000260
261 return NGX_OK;
262}
Igor Sysoev78452232005-10-12 13:50:36 +0000263
264
Igor Sysoev97c2f462006-10-02 08:46:45 +0000265ngx_int_t
Igor Sysoevdfc8dad2008-09-05 15:43:34 +0000266ngx_read_dir(ngx_dir_t *dir)
267{
268 dir->de = readdir(dir->dir);
269
270 if (dir->de) {
271#if (NGX_HAVE_D_TYPE)
272 dir->type = dir->de->d_type;
Igor Sysoev78c95de2009-03-06 13:01:21 +0000273 dir->valid_type = dir->type ? 1 : 0;
274#else
275 dir->valid_type = 0;
Igor Sysoevdfc8dad2008-09-05 15:43:34 +0000276#endif
277 return NGX_OK;
278 }
279
280 return NGX_ERROR;
281}
282
283
284ngx_int_t
Igor Sysoev97c2f462006-10-02 08:46:45 +0000285ngx_open_glob(ngx_glob_t *gl)
286{
Igor Sysoeva13b3b92008-04-29 09:28:42 +0000287 int n;
288
289 n = glob((char *) gl->pattern, GLOB_NOSORT, NULL, &gl->pglob);
290
291 if (n == 0) {
292 return NGX_OK;
293 }
294
Igor Sysoev843ad942008-08-22 12:54:32 +0000295#ifdef GLOB_NOMATCH
296
Igor Sysoeva13b3b92008-04-29 09:28:42 +0000297 if (n == GLOB_NOMATCH && gl->test) {
Igor Sysoev97c2f462006-10-02 08:46:45 +0000298 return NGX_OK;
299 }
300
Igor Sysoev843ad942008-08-22 12:54:32 +0000301#endif
302
Igor Sysoev97c2f462006-10-02 08:46:45 +0000303 return NGX_ERROR;
304}
305
306
307ngx_int_t
308ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
309{
Igor Sysoev316eafb2008-08-26 17:15:11 +0000310 size_t count;
311
312#ifdef GLOB_NOMATCH
313 count = (size_t) gl->pglob.gl_pathc;
314#else
315 count = (size_t) gl->pglob.gl_matchc;
316#endif
317
318 if (gl->n < count) {
Igor Sysoev97c2f462006-10-02 08:46:45 +0000319
320 name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
321 name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
322 gl->n++;
323
324 return NGX_OK;
325 }
326
327 return NGX_DONE;
328}
329
330
331void
332ngx_close_glob(ngx_glob_t *gl)
333{
334 globfree(&gl->pglob);
335}
336
337
Igor Sysoevffe71442006-02-08 15:33:12 +0000338ngx_err_t
339ngx_trylock_fd(ngx_fd_t fd)
Igor Sysoev78452232005-10-12 13:50:36 +0000340{
Igor Sysoev78452232005-10-12 13:50:36 +0000341 struct flock fl;
342
Igor Sysoevffe71442006-02-08 15:33:12 +0000343 fl.l_start = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000344 fl.l_len = 0;
345 fl.l_pid = 0;
346 fl.l_type = F_WRLCK;
Igor Sysoevffe71442006-02-08 15:33:12 +0000347 fl.l_whence = SEEK_SET;
Igor Sysoev78452232005-10-12 13:50:36 +0000348
Igor Sysoevffe71442006-02-08 15:33:12 +0000349 if (fcntl(fd, F_SETLK, &fl) == -1) {
350 return ngx_errno;
Igor Sysoev78452232005-10-12 13:50:36 +0000351 }
352
Igor Sysoevffe71442006-02-08 15:33:12 +0000353 return 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000354}
355
356
Igor Sysoevffe71442006-02-08 15:33:12 +0000357ngx_err_t
358ngx_lock_fd(ngx_fd_t fd)
Igor Sysoev78452232005-10-12 13:50:36 +0000359{
Igor Sysoev78452232005-10-12 13:50:36 +0000360 struct flock fl;
361
Igor Sysoevffe71442006-02-08 15:33:12 +0000362 fl.l_start = 0;
363 fl.l_len = 0;
364 fl.l_pid = 0;
365 fl.l_type = F_WRLCK;
Igor Sysoev78452232005-10-12 13:50:36 +0000366 fl.l_whence = SEEK_SET;
Igor Sysoevffe71442006-02-08 15:33:12 +0000367
368 if (fcntl(fd, F_SETLKW, &fl) == -1) {
369 return ngx_errno;
370 }
371
372 return 0;
373}
374
375
376ngx_err_t
377ngx_unlock_fd(ngx_fd_t fd)
378{
379 struct flock fl;
380
381 fl.l_start = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000382 fl.l_len = 0;
383 fl.l_pid = 0;
384 fl.l_type = F_UNLCK;
Igor Sysoevffe71442006-02-08 15:33:12 +0000385 fl.l_whence = SEEK_SET;
Igor Sysoev78452232005-10-12 13:50:36 +0000386
Igor Sysoevffe71442006-02-08 15:33:12 +0000387 if (fcntl(fd, F_SETLK, &fl) == -1) {
388 return ngx_errno;
Igor Sysoev78452232005-10-12 13:50:36 +0000389 }
390
Igor Sysoevffe71442006-02-08 15:33:12 +0000391 return 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000392}
Igor Sysoev385af282008-07-30 12:34:04 +0000393
394
395#if (NGX_HAVE_O_DIRECT)
396
397ngx_int_t
Igor Sysoevfae2c002008-09-12 13:50:12 +0000398ngx_directio_on(ngx_fd_t fd)
Igor Sysoev385af282008-07-30 12:34:04 +0000399{
400 int flags;
401
402 flags = fcntl(fd, F_GETFL);
403
404 if (flags == -1) {
405 return -1;
406 }
407
408 return fcntl(fd, F_SETFL, flags | O_DIRECT);
409}
410
Igor Sysoevfae2c002008-09-12 13:50:12 +0000411
412ngx_int_t
413ngx_directio_off(ngx_fd_t fd)
414{
415 int flags;
416
417 flags = fcntl(fd, F_GETFL);
418
419 if (flags == -1) {
420 return -1;
421 }
422
423 return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
424}
425
Igor Sysoev385af282008-07-30 12:34:04 +0000426#endif
Igor Sysoev1be74192009-03-30 07:43:06 +0000427
428
429#if (NGX_HAVE_STATFS)
430
431size_t
432ngx_fs_bsize(u_char *name)
433{
434 struct statfs fs;
435
436 if (statfs((char *) name, &fs) == -1) {
437 return 512;
438 }
439
440 if ((fs.f_bsize % 512) != 0) {
441 return 512;
442 }
443
444 return (size_t) fs.f_bsize;
445}
446
447#elif (NGX_HAVE_STATVFS)
448
449size_t
450ngx_fs_bsize(u_char *name)
451{
452 struct statvfs fs;
453
454 if (statvfs((char *) name, &fs) == -1) {
455 return 512;
456 }
457
458 if ((fs.f_frsize % 512) != 0) {
459 return 512;
460 }
461
462 return (size_t) fs.f_frsize;
463}
464
465#else
466
467size_t
468ngx_fs_bsize(u_char *name)
469{
470 return 512;
471}
472
473#endif