661ecaa4e09c2186d4c23298d629c0d1ca391c42
[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 #if (NGX_HAVE_D_TYPE)
253     dir->valid_type = 1;
254 #else
255     dir->valid_type = 0;
256 #endif
257
258     return NGX_OK;
259 }
260
261
262 ngx_int_t
263 ngx_read_dir(ngx_dir_t *dir)
264 {
265     dir->de = readdir(dir->dir);
266
267     if (dir->de) {
268 #if (NGX_HAVE_D_TYPE)
269         dir->type = dir->de->d_type;
270 #endif
271         return NGX_OK;
272     }
273
274     return NGX_ERROR;
275 }
276
277
278 ngx_int_t
279 ngx_open_glob(ngx_glob_t *gl)
280 {
281     int  n;
282
283     n = glob((char *) gl->pattern, GLOB_NOSORT, NULL, &gl->pglob);
284
285     if (n == 0) {
286         return NGX_OK;
287     }
288
289 #ifdef GLOB_NOMATCH
290
291     if (n == GLOB_NOMATCH && gl->test) {
292         return NGX_OK;
293     }
294
295 #endif
296
297     return NGX_ERROR;
298 }
299
300
301 ngx_int_t
302 ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
303 {
304     size_t  count;
305
306 #ifdef GLOB_NOMATCH
307     count = (size_t) gl->pglob.gl_pathc;
308 #else
309     count = (size_t) gl->pglob.gl_matchc;
310 #endif
311
312     if (gl->n < count) {
313
314         name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
315         name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
316         gl->n++;
317
318         return NGX_OK;
319     }
320
321     return NGX_DONE;
322 }
323
324
325 void
326 ngx_close_glob(ngx_glob_t *gl)
327 {
328     globfree(&gl->pglob);
329 }
330
331
332 ngx_err_t
333 ngx_trylock_fd(ngx_fd_t fd)
334 {
335     struct flock  fl;
336
337     fl.l_start = 0;
338     fl.l_len = 0;
339     fl.l_pid = 0;
340     fl.l_type = F_WRLCK;
341     fl.l_whence = SEEK_SET;
342
343     if (fcntl(fd, F_SETLK, &fl) == -1) {
344         return ngx_errno;
345     }
346
347     return 0;
348 }
349
350
351 ngx_err_t
352 ngx_lock_fd(ngx_fd_t fd)
353 {
354     struct flock  fl;
355
356     fl.l_start = 0;
357     fl.l_len = 0;
358     fl.l_pid = 0;
359     fl.l_type = F_WRLCK;
360     fl.l_whence = SEEK_SET;
361
362     if (fcntl(fd, F_SETLKW, &fl) == -1) {
363         return ngx_errno;
364     }
365
366     return 0;
367 }
368
369
370 ngx_err_t
371 ngx_unlock_fd(ngx_fd_t fd)
372 {
373     struct flock  fl;
374
375     fl.l_start = 0;
376     fl.l_len = 0;
377     fl.l_pid = 0;
378     fl.l_type = F_UNLCK;
379     fl.l_whence = SEEK_SET;
380
381     if (fcntl(fd, F_SETLK, &fl) == -1) {
382         return  ngx_errno;
383     }
384
385     return 0;
386 }
387
388
389 #if (NGX_HAVE_O_DIRECT)
390
391 ngx_int_t
392 ngx_directio_on(ngx_fd_t fd)
393 {
394     int  flags;
395
396     flags = fcntl(fd, F_GETFL);
397
398     if (flags == -1) {
399         return -1;
400     }
401
402     return fcntl(fd, F_SETFL, flags | O_DIRECT);
403 }
404
405
406 ngx_int_t
407 ngx_directio_off(ngx_fd_t fd)
408 {
409     int  flags;
410
411     flags = fcntl(fd, F_GETFL);
412
413     if (flags == -1) {
414         return -1;
415     }
416
417     return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
418 }
419
420 #endif