blob: 618d4e2144487d044f043711ca7004a05eb717ef [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 Sysoev38a7faa2009-09-25 13:55:46 +000062 ssize_t n, written;
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 Sysoev38a7faa2009-09-25 13:55:46 +000067 written = 0;
68
Igor Sysoevf6906042004-11-25 16:17:31 +000069#if (NGX_HAVE_PWRITE)
Igor Sysoev562e53e2003-11-13 06:14:05 +000070
Igor Sysoev38a7faa2009-09-25 13:55:46 +000071 for ( ;; ) {
72 n = pwrite(file->fd, buf, size, offset);
Igor Sysoevcde24782003-04-10 15:08:54 +000073
Igor Sysoev38a7faa2009-09-25 13:55:46 +000074 if (n == -1) {
75 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
76 "pwrite() \"%s\" failed", file->name.data);
77 return NGX_ERROR;
78 }
Igor Sysoevcde24782003-04-10 15:08:54 +000079
Igor Sysoev38a7faa2009-09-25 13:55:46 +000080 file->offset += n;
81 written += n;
82
83 if ((size_t) n == size) {
84 return written;
85 }
86
87 offset += n;
88 size -= n;
Igor Sysoevcde24782003-04-10 15:08:54 +000089 }
90
Igor Sysoev562e53e2003-11-13 06:14:05 +000091#else
92
Igor Sysoev1b138ed2003-11-18 21:34:08 +000093 if (file->sys_offset != offset) {
Igor Sysoev562e53e2003-11-13 06:14:05 +000094 if (lseek(file->fd, offset, SEEK_SET) == -1) {
Igor Sysoevf4d97e22009-09-24 20:04:10 +000095 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
96 "lseek() \"%s\" failed", file->name.data);
Igor Sysoev562e53e2003-11-13 06:14:05 +000097 return NGX_ERROR;
98 }
Igor Sysoev562e53e2003-11-13 06:14:05 +000099
Igor Sysoev160d7742003-11-19 16:26:41 +0000100 file->sys_offset = offset;
101 }
Igor Sysoev1b138ed2003-11-18 21:34:08 +0000102
Igor Sysoev38a7faa2009-09-25 13:55:46 +0000103 for ( ;; ) {
104 n = write(file->fd, buf, size);
Igor Sysoev562e53e2003-11-13 06:14:05 +0000105
Igor Sysoev38a7faa2009-09-25 13:55:46 +0000106 if (n == -1) {
107 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
108 "write() \"%s\" failed", file->name.data);
109 return NGX_ERROR;
110 }
111
112 file->offset += n;
113 written += n;
114
115 if ((size_t) n == size) {
116 return written;
117 }
118
119 size -= n;
Igor Sysoev562e53e2003-11-13 06:14:05 +0000120 }
Igor Sysoev562e53e2003-11-13 06:14:05 +0000121#endif
Igor Sysoevcde24782003-04-10 15:08:54 +0000122}
123
124
Igor Sysoev78452232005-10-12 13:50:36 +0000125ngx_fd_t
Igor Sysoevfe1cb8c2007-01-18 19:52:18 +0000126ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
Igor Sysoevdbb27762004-04-01 16:20:53 +0000127{
128 ngx_fd_t fd;
129
Igor Sysoevfe1cb8c2007-01-18 19:52:18 +0000130 fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,
131 access ? access : 0600);
Igor Sysoevdbb27762004-04-01 16:20:53 +0000132
133 if (fd != -1 && !persistent) {
134 unlink((const char *) name);
135 }
136
137 return fd;
138}
139
140
Igor Sysoev1b735832004-11-11 14:07:14 +0000141#define NGX_IOVS 8
142
Igor Sysoev78452232005-10-12 13:50:36 +0000143ssize_t
144ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
145 ngx_pool_t *pool)
Igor Sysoevfd675862003-04-11 16:01:14 +0000146{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000147 u_char *prev;
Igor Sysoevfd675862003-04-11 16:01:14 +0000148 size_t size;
149 ssize_t n;
Igor Sysoev1b735832004-11-11 14:07:14 +0000150 ngx_array_t vec;
151 struct iovec *iov, iovs[NGX_IOVS];
Igor Sysoevfd675862003-04-11 16:01:14 +0000152
Igor Sysoev1b735832004-11-11 14:07:14 +0000153 /* use pwrite() if there is the only buf in a chain */
Igor Sysoevfd675862003-04-11 16:01:14 +0000154
Igor Sysoev65977492003-11-02 22:56:18 +0000155 if (cl->next == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +0000156 return ngx_write_file(file, cl->buf->pos,
157 (size_t) (cl->buf->last - cl->buf->pos),
Igor Sysoevd9d0ca12003-11-21 06:30:49 +0000158 offset);
Igor Sysoevfd675862003-04-11 16:01:14 +0000159 }
160
Igor Sysoev1b735832004-11-11 14:07:14 +0000161 vec.elts = iovs;
162 vec.size = sizeof(struct iovec);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000163 vec.nalloc = NGX_IOVS;
Igor Sysoev1b735832004-11-11 14:07:14 +0000164 vec.pool = pool;
Igor Sysoevfd675862003-04-11 16:01:14 +0000165
Igor Sysoev1b735832004-11-11 14:07:14 +0000166 do {
167 prev = NULL;
168 iov = NULL;
169 size = 0;
Igor Sysoev65977492003-11-02 22:56:18 +0000170
Igor Sysoev1b735832004-11-11 14:07:14 +0000171 vec.nelts = 0;
Igor Sysoev65977492003-11-02 22:56:18 +0000172
Igor Sysoev1b735832004-11-11 14:07:14 +0000173 /* create the iovec and coalesce the neighbouring bufs */
Igor Sysoev65977492003-11-02 22:56:18 +0000174
Igor Sysoev1b735832004-11-11 14:07:14 +0000175 while (cl && vec.nelts < IOV_MAX) {
176 if (prev == cl->buf->pos) {
177 iov->iov_len += cl->buf->last - cl->buf->pos;
178
179 } else {
Igor Sysoevc1571722005-03-19 12:38:37 +0000180 iov = ngx_array_push(&vec);
181 if (iov == NULL) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000182 return NGX_ERROR;
183 }
184
185 iov->iov_base = (void *) cl->buf->pos;
186 iov->iov_len = cl->buf->last - cl->buf->pos;
187 }
188
189 size += cl->buf->last - cl->buf->pos;
190 prev = cl->buf->last;
191 cl = cl->next;
Igor Sysoev65977492003-11-02 22:56:18 +0000192 }
193
Igor Sysoev1b735832004-11-11 14:07:14 +0000194 /* use pwrite() if there is the only iovec buffer */
Igor Sysoev65977492003-11-02 22:56:18 +0000195
Igor Sysoev1b735832004-11-11 14:07:14 +0000196 if (vec.nelts == 1) {
197 iov = vec.elts;
198 return ngx_write_file(file, (u_char *) iov[0].iov_base,
199 iov[0].iov_len, offset);
200 }
Igor Sysoev65977492003-11-02 22:56:18 +0000201
Igor Sysoev1b735832004-11-11 14:07:14 +0000202 if (file->sys_offset != offset) {
203 if (lseek(file->fd, offset, SEEK_SET) == -1) {
204 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
Igor Sysoevf4d97e22009-09-24 20:04:10 +0000205 "lseek() \"%s\" failed", file->name.data);
Igor Sysoev1b735832004-11-11 14:07:14 +0000206 return NGX_ERROR;
207 }
Igor Sysoevfd675862003-04-11 16:01:14 +0000208
Igor Sysoev1b735832004-11-11 14:07:14 +0000209 file->sys_offset = offset;
210 }
211
212 n = writev(file->fd, vec.elts, vec.nelts);
213
214 if (n == -1) {
215 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
Igor Sysoevf4d97e22009-09-24 20:04:10 +0000216 "writev() \"%s\" failed", file->name.data);
Igor Sysoev5bf3d252003-10-22 07:05:29 +0000217 return NGX_ERROR;
218 }
Igor Sysoevfd675862003-04-11 16:01:14 +0000219
Igor Sysoev1b735832004-11-11 14:07:14 +0000220 if ((size_t) n != size) {
221 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
Igor Sysoevf4d97e22009-09-24 20:04:10 +0000222 "writev() \"%s\" has written only %z of %uz",
223 file->name.data, n, size);
Igor Sysoev1b735832004-11-11 14:07:14 +0000224 return NGX_ERROR;
225 }
Igor Sysoev1b138ed2003-11-18 21:34:08 +0000226
Igor Sysoev1b735832004-11-11 14:07:14 +0000227 file->sys_offset += n;
228 file->offset += n;
Igor Sysoevfd675862003-04-11 16:01:14 +0000229
Igor Sysoev1b735832004-11-11 14:07:14 +0000230 } while (cl);
Igor Sysoevfd675862003-04-11 16:01:14 +0000231
232 return n;
233}
234
235
Igor Sysoev78452232005-10-12 13:50:36 +0000236ngx_int_t
Igor Sysoevda173ab2006-08-30 10:39:17 +0000237ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
238{
239 struct timeval tv[2];
240
241 tv[0].tv_sec = s;
242 tv[0].tv_usec = 0;
243 tv[1].tv_sec = s;
244 tv[1].tv_usec = 0;
245
246 if (utimes((char *) name, tv) != -1) {
247 return NGX_OK;
248 }
249
250 return NGX_ERROR;
251}
252
253
254ngx_int_t
Igor Sysoev78452232005-10-12 13:50:36 +0000255ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000256{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000257 dir->dir = opendir((const char *) name->data);
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000258
259 if (dir->dir == NULL) {
260 return NGX_ERROR;
261 }
262
Igor Sysoev723e6cc2004-10-25 15:29:23 +0000263 dir->valid_info = 0;
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000264
265 return NGX_OK;
266}
Igor Sysoev78452232005-10-12 13:50:36 +0000267
268
Igor Sysoev97c2f462006-10-02 08:46:45 +0000269ngx_int_t
Igor Sysoevdfc8dad2008-09-05 15:43:34 +0000270ngx_read_dir(ngx_dir_t *dir)
271{
272 dir->de = readdir(dir->dir);
273
274 if (dir->de) {
275#if (NGX_HAVE_D_TYPE)
276 dir->type = dir->de->d_type;
Igor Sysoev78c95de2009-03-06 13:01:21 +0000277#else
Igor Sysoeve58700d2009-10-14 11:33:35 +0000278 dir->type = 0;
Igor Sysoevdfc8dad2008-09-05 15:43:34 +0000279#endif
280 return NGX_OK;
281 }
282
283 return NGX_ERROR;
284}
285
286
287ngx_int_t
Igor Sysoev97c2f462006-10-02 08:46:45 +0000288ngx_open_glob(ngx_glob_t *gl)
289{
Igor Sysoeva13b3b92008-04-29 09:28:42 +0000290 int n;
291
292 n = glob((char *) gl->pattern, GLOB_NOSORT, NULL, &gl->pglob);
293
294 if (n == 0) {
295 return NGX_OK;
296 }
297
Igor Sysoev843ad942008-08-22 12:54:32 +0000298#ifdef GLOB_NOMATCH
299
Igor Sysoeva13b3b92008-04-29 09:28:42 +0000300 if (n == GLOB_NOMATCH && gl->test) {
Igor Sysoev97c2f462006-10-02 08:46:45 +0000301 return NGX_OK;
302 }
303
Igor Sysoev843ad942008-08-22 12:54:32 +0000304#endif
305
Igor Sysoev97c2f462006-10-02 08:46:45 +0000306 return NGX_ERROR;
307}
308
309
310ngx_int_t
311ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
312{
Igor Sysoev316eafb2008-08-26 17:15:11 +0000313 size_t count;
314
315#ifdef GLOB_NOMATCH
316 count = (size_t) gl->pglob.gl_pathc;
317#else
318 count = (size_t) gl->pglob.gl_matchc;
319#endif
320
321 if (gl->n < count) {
Igor Sysoev97c2f462006-10-02 08:46:45 +0000322
323 name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
324 name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
325 gl->n++;
326
327 return NGX_OK;
328 }
329
330 return NGX_DONE;
331}
332
333
334void
335ngx_close_glob(ngx_glob_t *gl)
336{
337 globfree(&gl->pglob);
338}
339
340
Igor Sysoevffe71442006-02-08 15:33:12 +0000341ngx_err_t
342ngx_trylock_fd(ngx_fd_t fd)
Igor Sysoev78452232005-10-12 13:50:36 +0000343{
Igor Sysoev78452232005-10-12 13:50:36 +0000344 struct flock fl;
345
Igor Sysoevffe71442006-02-08 15:33:12 +0000346 fl.l_start = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000347 fl.l_len = 0;
348 fl.l_pid = 0;
349 fl.l_type = F_WRLCK;
Igor Sysoevffe71442006-02-08 15:33:12 +0000350 fl.l_whence = SEEK_SET;
Igor Sysoev78452232005-10-12 13:50:36 +0000351
Igor Sysoevffe71442006-02-08 15:33:12 +0000352 if (fcntl(fd, F_SETLK, &fl) == -1) {
353 return ngx_errno;
Igor Sysoev78452232005-10-12 13:50:36 +0000354 }
355
Igor Sysoevffe71442006-02-08 15:33:12 +0000356 return 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000357}
358
359
Igor Sysoevffe71442006-02-08 15:33:12 +0000360ngx_err_t
361ngx_lock_fd(ngx_fd_t fd)
Igor Sysoev78452232005-10-12 13:50:36 +0000362{
Igor Sysoev78452232005-10-12 13:50:36 +0000363 struct flock fl;
364
Igor Sysoevffe71442006-02-08 15:33:12 +0000365 fl.l_start = 0;
366 fl.l_len = 0;
367 fl.l_pid = 0;
368 fl.l_type = F_WRLCK;
Igor Sysoev78452232005-10-12 13:50:36 +0000369 fl.l_whence = SEEK_SET;
Igor Sysoevffe71442006-02-08 15:33:12 +0000370
371 if (fcntl(fd, F_SETLKW, &fl) == -1) {
372 return ngx_errno;
373 }
374
375 return 0;
376}
377
378
379ngx_err_t
380ngx_unlock_fd(ngx_fd_t fd)
381{
382 struct flock fl;
383
384 fl.l_start = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000385 fl.l_len = 0;
386 fl.l_pid = 0;
387 fl.l_type = F_UNLCK;
Igor Sysoevffe71442006-02-08 15:33:12 +0000388 fl.l_whence = SEEK_SET;
Igor Sysoev78452232005-10-12 13:50:36 +0000389
Igor Sysoevffe71442006-02-08 15:33:12 +0000390 if (fcntl(fd, F_SETLK, &fl) == -1) {
391 return ngx_errno;
Igor Sysoev78452232005-10-12 13:50:36 +0000392 }
393
Igor Sysoevffe71442006-02-08 15:33:12 +0000394 return 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000395}
Igor Sysoev385af282008-07-30 12:34:04 +0000396
397
398#if (NGX_HAVE_O_DIRECT)
399
400ngx_int_t
Igor Sysoevfae2c002008-09-12 13:50:12 +0000401ngx_directio_on(ngx_fd_t fd)
Igor Sysoev385af282008-07-30 12:34:04 +0000402{
403 int flags;
404
405 flags = fcntl(fd, F_GETFL);
406
407 if (flags == -1) {
Igor Sysoev48a28e22009-09-25 14:17:28 +0000408 return NGX_FILE_ERROR;
Igor Sysoev385af282008-07-30 12:34:04 +0000409 }
410
411 return fcntl(fd, F_SETFL, flags | O_DIRECT);
412}
413
Igor Sysoevfae2c002008-09-12 13:50:12 +0000414
415ngx_int_t
416ngx_directio_off(ngx_fd_t fd)
417{
418 int flags;
419
420 flags = fcntl(fd, F_GETFL);
421
422 if (flags == -1) {
Igor Sysoev48a28e22009-09-25 14:17:28 +0000423 return NGX_FILE_ERROR;
Igor Sysoevfae2c002008-09-12 13:50:12 +0000424 }
425
426 return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
427}
428
Igor Sysoev385af282008-07-30 12:34:04 +0000429#endif
Igor Sysoev1be74192009-03-30 07:43:06 +0000430
431
432#if (NGX_HAVE_STATFS)
433
434size_t
435ngx_fs_bsize(u_char *name)
436{
437 struct statfs fs;
438
439 if (statfs((char *) name, &fs) == -1) {
440 return 512;
441 }
442
443 if ((fs.f_bsize % 512) != 0) {
444 return 512;
445 }
446
447 return (size_t) fs.f_bsize;
448}
449
450#elif (NGX_HAVE_STATVFS)
451
452size_t
453ngx_fs_bsize(u_char *name)
454{
455 struct statvfs fs;
456
457 if (statvfs((char *) name, &fs) == -1) {
458 return 512;
459 }
460
461 if ((fs.f_frsize % 512) != 0) {
462 return 512;
463 }
464
465 return (size_t) fs.f_frsize;
466}
467
468#else
469
470size_t
471ngx_fs_bsize(u_char *name)
472{
473 return 512;
474}
475
476#endif