1203989b64422f4fa20fc2461f240ba7221d92ea
[nginx.git] / nginx / src / os / unix / ngx_files.c
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9
10
11 ssize_t
12 ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
13 {
14     ssize_t  n;
15
16     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
17                    "read: %d, %p, %uz, %O", file->fd, buf, size, offset);
18
19 #if (NGX_HAVE_PREAD)
20
21     n = pread(file->fd, buf, size, offset);
22
23     if (n == -1) {
24         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
25                       "pread() failed, file \"%s\"", file->name.data);
26         return NGX_ERROR;
27     }
28
29 #else
30
31     if (file->sys_offset != offset) {
32         if (lseek(file->fd, offset, SEEK_SET) == -1) {
33             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
34             return NGX_ERROR;
35         }
36
37         file->sys_offset = offset;
38     }
39
40     n = read(file->fd, buf, size);
41
42     if (n == -1) {
43         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "read() failed");
44         return NGX_ERROR;
45     }
46
47     file->sys_offset += n;
48
49 #endif
50
51     file->offset += n;
52
53     return n;
54 }
55
56
57 ssize_t
58 ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
59 {
60     ssize_t  n;
61
62     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
63                    "write: %d, %p, %uz, %O", file->fd, buf, size, offset);
64
65 #if (NGX_HAVE_PWRITE)
66
67     n = pwrite(file->fd, buf, size, offset);
68
69     if (n == -1) {
70         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pwrite() failed");
71         return NGX_ERROR;
72     }
73
74     if ((size_t) n != size) {
75         ngx_log_error(NGX_LOG_CRIT, file->log, 0,
76                       "pwrite() has written only %z of %uz", n, size);
77         return NGX_ERROR;
78     }
79
80 #else
81
82     if (file->sys_offset != offset) {
83         if (lseek(file->fd, offset, SEEK_SET) == -1) {
84             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
85             return NGX_ERROR;
86         }
87
88         file->sys_offset = offset;
89     }
90
91     n = write(file->fd, buf, size);
92
93     if (n == -1) {
94         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "write() failed");
95         return NGX_ERROR;
96     }
97
98     if ((size_t) n != size) {
99         ngx_log_error(NGX_LOG_CRIT, file->log, 0,
100                       "write() has written only %z of %uz", n, size);
101         return NGX_ERROR;
102     }
103
104     file->sys_offset += n;
105
106 #endif
107
108     file->offset += n;
109
110     return n;
111 }
112
113
114 ngx_fd_t
115 ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
116 {
117     ngx_fd_t  fd;
118
119     fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,
120               access ? access : 0600);
121
122     if (fd != -1 && !persistent) {
123         unlink((const char *) name);
124     }
125
126     return fd;
127 }
128
129
130 #define NGX_IOVS  8
131
132 ssize_t
133 ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
134     ngx_pool_t *pool)
135 {
136     u_char        *prev;
137     size_t         size;
138     ssize_t        n;
139     ngx_array_t    vec;
140     struct iovec  *iov, iovs[NGX_IOVS];
141
142     /* use pwrite() if there is the only buf in a chain */
143
144     if (cl->next == NULL) {
145         return ngx_write_file(file, cl->buf->pos,
146                               (size_t) (cl->buf->last - cl->buf->pos),
147                               offset);
148     }
149
150     vec.elts = iovs;
151     vec.size = sizeof(struct iovec);
152     vec.nalloc = NGX_IOVS;
153     vec.pool = pool;
154
155     do {
156         prev = NULL;
157         iov = NULL;
158         size = 0;
159
160         vec.nelts = 0;
161
162         /* create the iovec and coalesce the neighbouring bufs */
163
164         while (cl && vec.nelts < IOV_MAX) {
165             if (prev == cl->buf->pos) {
166                 iov->iov_len += cl->buf->last - cl->buf->pos;
167
168             } else {
169                 iov = ngx_array_push(&vec);
170                 if (iov == NULL) {
171                     return NGX_ERROR;
172                 }
173
174                 iov->iov_base = (void *) cl->buf->pos;
175                 iov->iov_len = cl->buf->last - cl->buf->pos;
176             }
177
178             size += cl->buf->last - cl->buf->pos;
179             prev = cl->buf->last;
180             cl = cl->next;
181         }
182
183         /* use pwrite() if there is the only iovec buffer */
184
185         if (vec.nelts == 1) {
186             iov = vec.elts;
187             return ngx_write_file(file, (u_char *) iov[0].iov_base,
188                                   iov[0].iov_len, offset);
189         }
190
191         if (file->sys_offset != offset) {
192             if (lseek(file->fd, offset, SEEK_SET) == -1) {
193                 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
194                               "lseek() failed");
195                 return NGX_ERROR;
196             }
197
198             file->sys_offset = offset;
199         }
200
201         n = writev(file->fd, vec.elts, vec.nelts);
202
203         if (n == -1) {
204             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
205                           "writev() failed");
206             return NGX_ERROR;
207         }
208
209         if ((size_t) n != size) {
210             ngx_log_error(NGX_LOG_CRIT, file->log, 0,
211                           "writev() has written only %z of %uz", n, size);
212             return NGX_ERROR;
213         }
214
215         file->sys_offset += n;
216         file->offset += n;
217
218     } while (cl);
219
220     return n;
221 }
222
223
224 ngx_int_t
225 ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
226 {
227     struct timeval  tv[2];
228
229     tv[0].tv_sec = s;
230     tv[0].tv_usec = 0;
231     tv[1].tv_sec = s;
232     tv[1].tv_usec = 0;
233
234     if (utimes((char *) name, tv) != -1) {
235         return NGX_OK;
236     }
237
238     return NGX_ERROR;
239 }
240
241
242 ngx_int_t
243 ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
244 {
245     dir->dir = opendir((const char *) name->data);
246
247     if (dir->dir == NULL) {
248         return NGX_ERROR;
249     }
250
251     dir->valid_info = 0;
252
253     return NGX_OK;
254 }
255
256
257 ngx_int_t
258 ngx_read_dir(ngx_dir_t *dir)
259 {
260     dir->de = readdir(dir->dir);
261
262     if (dir->de) {
263 #if (NGX_HAVE_D_TYPE)
264         dir->type = dir->de->d_type;
265         dir->valid_type = dir->type ? 1 : 0;
266 #else
267         dir->valid_type = 0;
268 #endif
269         return NGX_OK;
270     }
271
272     return NGX_ERROR;
273 }
274
275
276 ngx_int_t
277 ngx_open_glob(ngx_glob_t *gl)
278 {
279     int  n;
280
281     n = glob((char *) gl->pattern, GLOB_NOSORT, NULL, &gl->pglob);
282
283     if (n == 0) {
284         return NGX_OK;
285     }
286
287 #ifdef GLOB_NOMATCH
288
289     if (n == GLOB_NOMATCH && gl->test) {
290         return NGX_OK;
291     }
292
293 #endif
294
295     return NGX_ERROR;
296 }
297
298
299 ngx_int_t
300 ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
301 {
302     size_t  count;
303
304 #ifdef GLOB_NOMATCH
305     count = (size_t) gl->pglob.gl_pathc;
306 #else
307     count = (size_t) gl->pglob.gl_matchc;
308 #endif
309
310     if (gl->n < count) {
311
312         name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
313         name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
314         gl->n++;
315
316         return NGX_OK;
317     }
318
319     return NGX_DONE;
320 }
321
322
323 void
324 ngx_close_glob(ngx_glob_t *gl)
325 {
326     globfree(&gl->pglob);
327 }
328
329
330 ngx_err_t
331 ngx_trylock_fd(ngx_fd_t fd)
332 {
333     struct flock  fl;
334
335     fl.l_start = 0;
336     fl.l_len = 0;
337     fl.l_pid = 0;
338     fl.l_type = F_WRLCK;
339     fl.l_whence = SEEK_SET;
340
341     if (fcntl(fd, F_SETLK, &fl) == -1) {
342         return ngx_errno;
343     }
344
345     return 0;
346 }
347
348
349 ngx_err_t
350 ngx_lock_fd(ngx_fd_t fd)
351 {
352     struct flock  fl;
353
354     fl.l_start = 0;
355     fl.l_len = 0;
356     fl.l_pid = 0;
357     fl.l_type = F_WRLCK;
358     fl.l_whence = SEEK_SET;
359
360     if (fcntl(fd, F_SETLKW, &fl) == -1) {
361         return ngx_errno;
362     }
363
364     return 0;
365 }
366
367
368 ngx_err_t
369 ngx_unlock_fd(ngx_fd_t fd)
370 {
371     struct flock  fl;
372
373     fl.l_start = 0;
374     fl.l_len = 0;
375     fl.l_pid = 0;
376     fl.l_type = F_UNLCK;
377     fl.l_whence = SEEK_SET;
378
379     if (fcntl(fd, F_SETLK, &fl) == -1) {
380         return  ngx_errno;
381     }
382
383     return 0;
384 }
385
386
387 #if (NGX_HAVE_O_DIRECT)
388
389 ngx_int_t
390 ngx_directio_on(ngx_fd_t fd)
391 {
392     int  flags;
393
394     flags = fcntl(fd, F_GETFL);
395
396     if (flags == -1) {
397         return -1;
398     }
399
400     return fcntl(fd, F_SETFL, flags | O_DIRECT);
401 }
402
403
404 ngx_int_t
405 ngx_directio_off(ngx_fd_t fd)
406 {
407     int  flags;
408
409     flags = fcntl(fd, F_GETFL);
410
411     if (flags == -1) {
412         return -1;
413     }
414
415     return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
416 }
417
418 #endif