xref: /f-stack/app/nginx-1.16.1/src/os/unix/ngx_files.c (revision 3da8d17d)
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 
11 
12 #if (NGX_THREADS)
13 #include <ngx_thread_pool.h>
14 static void ngx_thread_read_handler(void *data, ngx_log_t *log);
15 static void ngx_thread_write_chain_to_file_handler(void *data, ngx_log_t *log);
16 #endif
17 
18 static ngx_chain_t *ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl);
19 static ssize_t ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec,
20     off_t offset);
21 
22 
23 #if (NGX_HAVE_FILE_AIO)
24 
25 ngx_uint_t  ngx_file_aio = 1;
26 
27 #endif
28 
29 
30 ssize_t
ngx_read_file(ngx_file_t * file,u_char * buf,size_t size,off_t offset)31 ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
32 {
33     ssize_t  n;
34 
35     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
36                    "read: %d, %p, %uz, %O", file->fd, buf, size, offset);
37 
38 #if (NGX_HAVE_PREAD)
39 
40     n = pread(file->fd, buf, size, offset);
41 
42     if (n == -1) {
43         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
44                       "pread() \"%s\" failed", file->name.data);
45         return NGX_ERROR;
46     }
47 
48 #else
49 
50     if (file->sys_offset != offset) {
51         if (lseek(file->fd, offset, SEEK_SET) == -1) {
52             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
53                           "lseek() \"%s\" failed", file->name.data);
54             return NGX_ERROR;
55         }
56 
57         file->sys_offset = offset;
58     }
59 
60     n = read(file->fd, buf, size);
61 
62     if (n == -1) {
63         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
64                       "read() \"%s\" failed", file->name.data);
65         return NGX_ERROR;
66     }
67 
68     file->sys_offset += n;
69 
70 #endif
71 
72     file->offset += n;
73 
74     return n;
75 }
76 
77 
78 #if (NGX_THREADS)
79 
80 typedef struct {
81     ngx_fd_t       fd;
82     ngx_uint_t     write;   /* unsigned  write:1; */
83 
84     u_char        *buf;
85     size_t         size;
86     ngx_chain_t   *chain;
87     off_t          offset;
88 
89     size_t         nbytes;
90     ngx_err_t      err;
91 } ngx_thread_file_ctx_t;
92 
93 
94 ssize_t
ngx_thread_read(ngx_file_t * file,u_char * buf,size_t size,off_t offset,ngx_pool_t * pool)95 ngx_thread_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
96     ngx_pool_t *pool)
97 {
98     ngx_thread_task_t      *task;
99     ngx_thread_file_ctx_t  *ctx;
100 
101     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
102                    "thread read: %d, %p, %uz, %O",
103                    file->fd, buf, size, offset);
104 
105     task = file->thread_task;
106 
107     if (task == NULL) {
108         task = ngx_thread_task_alloc(pool, sizeof(ngx_thread_file_ctx_t));
109         if (task == NULL) {
110             return NGX_ERROR;
111         }
112 
113         file->thread_task = task;
114     }
115 
116     ctx = task->ctx;
117 
118     if (task->event.complete) {
119         task->event.complete = 0;
120 
121         if (ctx->write) {
122             ngx_log_error(NGX_LOG_ALERT, file->log, 0,
123                           "invalid thread call, read instead of write");
124             return NGX_ERROR;
125         }
126 
127         if (ctx->err) {
128             ngx_log_error(NGX_LOG_CRIT, file->log, ctx->err,
129                           "pread() \"%s\" failed", file->name.data);
130             return NGX_ERROR;
131         }
132 
133         return ctx->nbytes;
134     }
135 
136     task->handler = ngx_thread_read_handler;
137 
138     ctx->write = 0;
139 
140     ctx->fd = file->fd;
141     ctx->buf = buf;
142     ctx->size = size;
143     ctx->offset = offset;
144 
145     if (file->thread_handler(task, file) != NGX_OK) {
146         return NGX_ERROR;
147     }
148 
149     return NGX_AGAIN;
150 }
151 
152 
153 #if (NGX_HAVE_PREAD)
154 
155 static void
ngx_thread_read_handler(void * data,ngx_log_t * log)156 ngx_thread_read_handler(void *data, ngx_log_t *log)
157 {
158     ngx_thread_file_ctx_t *ctx = data;
159 
160     ssize_t  n;
161 
162     ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "thread read handler");
163 
164     n = pread(ctx->fd, ctx->buf, ctx->size, ctx->offset);
165 
166     if (n == -1) {
167         ctx->err = ngx_errno;
168 
169     } else {
170         ctx->nbytes = n;
171         ctx->err = 0;
172     }
173 
174 #if 0
175     ngx_time_update();
176 #endif
177 
178     ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0,
179                    "pread: %z (err: %d) of %uz @%O",
180                    n, ctx->err, ctx->size, ctx->offset);
181 }
182 
183 #else
184 
185 #error pread() is required!
186 
187 #endif
188 
189 #endif /* NGX_THREADS */
190 
191 
192 ssize_t
ngx_write_file(ngx_file_t * file,u_char * buf,size_t size,off_t offset)193 ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
194 {
195     ssize_t    n, written;
196     ngx_err_t  err;
197 
198     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
199                    "write: %d, %p, %uz, %O", file->fd, buf, size, offset);
200 
201     written = 0;
202 
203 #if (NGX_HAVE_PWRITE)
204 
205     for ( ;; ) {
206         n = pwrite(file->fd, buf + written, size, offset);
207 
208         if (n == -1) {
209             err = ngx_errno;
210 
211             if (err == NGX_EINTR) {
212                 ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
213                                "pwrite() was interrupted");
214                 continue;
215             }
216 
217             ngx_log_error(NGX_LOG_CRIT, file->log, err,
218                           "pwrite() \"%s\" failed", file->name.data);
219             return NGX_ERROR;
220         }
221 
222         file->offset += n;
223         written += n;
224 
225         if ((size_t) n == size) {
226             return written;
227         }
228 
229         offset += n;
230         size -= n;
231     }
232 
233 #else
234 
235     if (file->sys_offset != offset) {
236         if (lseek(file->fd, offset, SEEK_SET) == -1) {
237             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
238                           "lseek() \"%s\" failed", file->name.data);
239             return NGX_ERROR;
240         }
241 
242         file->sys_offset = offset;
243     }
244 
245     for ( ;; ) {
246         n = write(file->fd, buf + written, size);
247 
248         if (n == -1) {
249             err = ngx_errno;
250 
251             if (err == NGX_EINTR) {
252                 ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
253                                "write() was interrupted");
254                 continue;
255             }
256 
257             ngx_log_error(NGX_LOG_CRIT, file->log, err,
258                           "write() \"%s\" failed", file->name.data);
259             return NGX_ERROR;
260         }
261 
262         file->sys_offset += n;
263         file->offset += n;
264         written += n;
265 
266         if ((size_t) n == size) {
267             return written;
268         }
269 
270         size -= n;
271     }
272 #endif
273 }
274 
275 
276 ngx_fd_t
ngx_open_tempfile(u_char * name,ngx_uint_t persistent,ngx_uint_t access)277 ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
278 {
279     ngx_fd_t  fd;
280 
281     fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,
282               access ? access : 0600);
283 
284     if (fd != -1 && !persistent) {
285         (void) unlink((const char *) name);
286     }
287 
288     return fd;
289 }
290 
291 
292 ssize_t
ngx_write_chain_to_file(ngx_file_t * file,ngx_chain_t * cl,off_t offset,ngx_pool_t * pool)293 ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
294     ngx_pool_t *pool)
295 {
296     ssize_t        total, n;
297     ngx_iovec_t    vec;
298     struct iovec   iovs[NGX_IOVS_PREALLOCATE];
299 
300     /* use pwrite() if there is the only buf in a chain */
301 
302     if (cl->next == NULL) {
303         return ngx_write_file(file, cl->buf->pos,
304                               (size_t) (cl->buf->last - cl->buf->pos),
305                               offset);
306     }
307 
308     total = 0;
309 
310     vec.iovs = iovs;
311     vec.nalloc = NGX_IOVS_PREALLOCATE;
312 
313     do {
314         /* create the iovec and coalesce the neighbouring bufs */
315         cl = ngx_chain_to_iovec(&vec, cl);
316 
317         /* use pwrite() if there is the only iovec buffer */
318 
319         if (vec.count == 1) {
320             n = ngx_write_file(file, (u_char *) iovs[0].iov_base,
321                                iovs[0].iov_len, offset);
322 
323             if (n == NGX_ERROR) {
324                 return n;
325             }
326 
327             return total + n;
328         }
329 
330         n = ngx_writev_file(file, &vec, offset);
331 
332         if (n == NGX_ERROR) {
333             return n;
334         }
335 
336         offset += n;
337         total += n;
338 
339     } while (cl);
340 
341     return total;
342 }
343 
344 
345 static ngx_chain_t *
ngx_chain_to_iovec(ngx_iovec_t * vec,ngx_chain_t * cl)346 ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl)
347 {
348     size_t         total, size;
349     u_char        *prev;
350     ngx_uint_t     n;
351     struct iovec  *iov;
352 
353     iov = NULL;
354     prev = NULL;
355     total = 0;
356     n = 0;
357 
358     for ( /* void */ ; cl; cl = cl->next) {
359 
360         if (ngx_buf_special(cl->buf)) {
361             continue;
362         }
363 
364         size = cl->buf->last - cl->buf->pos;
365 
366         if (prev == cl->buf->pos) {
367             iov->iov_len += size;
368 
369         } else {
370             if (n == vec->nalloc) {
371                 break;
372             }
373 
374             iov = &vec->iovs[n++];
375 
376             iov->iov_base = (void *) cl->buf->pos;
377             iov->iov_len = size;
378         }
379 
380         prev = cl->buf->pos + size;
381         total += size;
382     }
383 
384     vec->count = n;
385     vec->size = total;
386 
387     return cl;
388 }
389 
390 
391 static ssize_t
ngx_writev_file(ngx_file_t * file,ngx_iovec_t * vec,off_t offset)392 ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec, off_t offset)
393 {
394     ssize_t    n;
395     ngx_err_t  err;
396 
397     ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0,
398                    "writev: %d, %uz, %O", file->fd, vec->size, offset);
399 
400 #if (NGX_HAVE_PWRITEV)
401 
402 eintr:
403 
404     n = pwritev(file->fd, vec->iovs, vec->count, offset);
405 
406     if (n == -1) {
407         err = ngx_errno;
408 
409         if (err == NGX_EINTR) {
410             ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
411                            "pwritev() was interrupted");
412             goto eintr;
413         }
414 
415         ngx_log_error(NGX_LOG_CRIT, file->log, err,
416                       "pwritev() \"%s\" failed", file->name.data);
417         return NGX_ERROR;
418     }
419 
420     if ((size_t) n != vec->size) {
421         ngx_log_error(NGX_LOG_CRIT, file->log, 0,
422                       "pwritev() \"%s\" has written only %z of %uz",
423                       file->name.data, n, vec->size);
424         return NGX_ERROR;
425     }
426 
427 #else
428 
429     if (file->sys_offset != offset) {
430         if (lseek(file->fd, offset, SEEK_SET) == -1) {
431             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
432                           "lseek() \"%s\" failed", file->name.data);
433             return NGX_ERROR;
434         }
435 
436         file->sys_offset = offset;
437     }
438 
439 eintr:
440 
441     n = writev(file->fd, vec->iovs, vec->count);
442 
443     if (n == -1) {
444         err = ngx_errno;
445 
446         if (err == NGX_EINTR) {
447             ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
448                            "writev() was interrupted");
449             goto eintr;
450         }
451 
452         ngx_log_error(NGX_LOG_CRIT, file->log, err,
453                       "writev() \"%s\" failed", file->name.data);
454         return NGX_ERROR;
455     }
456 
457     if ((size_t) n != vec->size) {
458         ngx_log_error(NGX_LOG_CRIT, file->log, 0,
459                       "writev() \"%s\" has written only %z of %uz",
460                       file->name.data, n, vec->size);
461         return NGX_ERROR;
462     }
463 
464     file->sys_offset += n;
465 
466 #endif
467 
468     file->offset += n;
469 
470     return n;
471 }
472 
473 
474 #if (NGX_THREADS)
475 
476 ssize_t
ngx_thread_write_chain_to_file(ngx_file_t * file,ngx_chain_t * cl,off_t offset,ngx_pool_t * pool)477 ngx_thread_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
478     ngx_pool_t *pool)
479 {
480     ngx_thread_task_t      *task;
481     ngx_thread_file_ctx_t  *ctx;
482 
483     ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0,
484                    "thread write chain: %d, %p, %O",
485                    file->fd, cl, offset);
486 
487     task = file->thread_task;
488 
489     if (task == NULL) {
490         task = ngx_thread_task_alloc(pool,
491                                      sizeof(ngx_thread_file_ctx_t));
492         if (task == NULL) {
493             return NGX_ERROR;
494         }
495 
496         file->thread_task = task;
497     }
498 
499     ctx = task->ctx;
500 
501     if (task->event.complete) {
502         task->event.complete = 0;
503 
504         if (!ctx->write) {
505             ngx_log_error(NGX_LOG_ALERT, file->log, 0,
506                           "invalid thread call, write instead of read");
507             return NGX_ERROR;
508         }
509 
510         if (ctx->err || ctx->nbytes == 0) {
511             ngx_log_error(NGX_LOG_CRIT, file->log, ctx->err,
512                           "pwritev() \"%s\" failed", file->name.data);
513             return NGX_ERROR;
514         }
515 
516         file->offset += ctx->nbytes;
517         return ctx->nbytes;
518     }
519 
520     task->handler = ngx_thread_write_chain_to_file_handler;
521 
522     ctx->write = 1;
523 
524     ctx->fd = file->fd;
525     ctx->chain = cl;
526     ctx->offset = offset;
527 
528     if (file->thread_handler(task, file) != NGX_OK) {
529         return NGX_ERROR;
530     }
531 
532     return NGX_AGAIN;
533 }
534 
535 
536 static void
ngx_thread_write_chain_to_file_handler(void * data,ngx_log_t * log)537 ngx_thread_write_chain_to_file_handler(void *data, ngx_log_t *log)
538 {
539     ngx_thread_file_ctx_t *ctx = data;
540 
541 #if (NGX_HAVE_PWRITEV)
542 
543     off_t          offset;
544     ssize_t        n;
545     ngx_err_t      err;
546     ngx_chain_t   *cl;
547     ngx_iovec_t    vec;
548     struct iovec   iovs[NGX_IOVS_PREALLOCATE];
549 
550     vec.iovs = iovs;
551     vec.nalloc = NGX_IOVS_PREALLOCATE;
552 
553     cl = ctx->chain;
554     offset = ctx->offset;
555 
556     ctx->nbytes = 0;
557     ctx->err = 0;
558 
559     do {
560         /* create the iovec and coalesce the neighbouring bufs */
561         cl = ngx_chain_to_iovec(&vec, cl);
562 
563 eintr:
564 
565         n = pwritev(ctx->fd, iovs, vec.count, offset);
566 
567         if (n == -1) {
568             err = ngx_errno;
569 
570             if (err == NGX_EINTR) {
571                 ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, err,
572                                "pwritev() was interrupted");
573                 goto eintr;
574             }
575 
576             ctx->err = err;
577             return;
578         }
579 
580         if ((size_t) n != vec.size) {
581             ctx->nbytes = 0;
582             return;
583         }
584 
585         ctx->nbytes += n;
586         offset += n;
587     } while (cl);
588 
589 #else
590 
591     ctx->err = NGX_ENOSYS;
592     return;
593 
594 #endif
595 }
596 
597 #endif /* NGX_THREADS */
598 
599 
600 ngx_int_t
ngx_set_file_time(u_char * name,ngx_fd_t fd,time_t s)601 ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
602 {
603     struct timeval  tv[2];
604 
605     tv[0].tv_sec = ngx_time();
606     tv[0].tv_usec = 0;
607     tv[1].tv_sec = s;
608     tv[1].tv_usec = 0;
609 
610     if (utimes((char *) name, tv) != -1) {
611         return NGX_OK;
612     }
613 
614     return NGX_ERROR;
615 }
616 
617 
618 ngx_int_t
ngx_create_file_mapping(ngx_file_mapping_t * fm)619 ngx_create_file_mapping(ngx_file_mapping_t *fm)
620 {
621     fm->fd = ngx_open_file(fm->name, NGX_FILE_RDWR, NGX_FILE_TRUNCATE,
622                            NGX_FILE_DEFAULT_ACCESS);
623 
624     if (fm->fd == NGX_INVALID_FILE) {
625         ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
626                       ngx_open_file_n " \"%s\" failed", fm->name);
627         return NGX_ERROR;
628     }
629 
630     if (ftruncate(fm->fd, fm->size) == -1) {
631         ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
632                       "ftruncate() \"%s\" failed", fm->name);
633         goto failed;
634     }
635 
636     fm->addr = mmap(NULL, fm->size, PROT_READ|PROT_WRITE, MAP_SHARED,
637                     fm->fd, 0);
638     if (fm->addr != MAP_FAILED) {
639         return NGX_OK;
640     }
641 
642     ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
643                   "mmap(%uz) \"%s\" failed", fm->size, fm->name);
644 
645 failed:
646 
647     if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
648         ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
649                       ngx_close_file_n " \"%s\" failed", fm->name);
650     }
651 
652     return NGX_ERROR;
653 }
654 
655 
656 void
ngx_close_file_mapping(ngx_file_mapping_t * fm)657 ngx_close_file_mapping(ngx_file_mapping_t *fm)
658 {
659     if (munmap(fm->addr, fm->size) == -1) {
660         ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
661                       "munmap(%uz) \"%s\" failed", fm->size, fm->name);
662     }
663 
664     if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
665         ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
666                       ngx_close_file_n " \"%s\" failed", fm->name);
667     }
668 }
669 
670 
671 ngx_int_t
ngx_open_dir(ngx_str_t * name,ngx_dir_t * dir)672 ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
673 {
674     dir->dir = opendir((const char *) name->data);
675 
676     if (dir->dir == NULL) {
677         return NGX_ERROR;
678     }
679 
680     dir->valid_info = 0;
681 
682     return NGX_OK;
683 }
684 
685 
686 ngx_int_t
ngx_read_dir(ngx_dir_t * dir)687 ngx_read_dir(ngx_dir_t *dir)
688 {
689     dir->de = readdir(dir->dir);
690 
691     if (dir->de) {
692 #if (NGX_HAVE_D_TYPE)
693         dir->type = dir->de->d_type;
694 #else
695         dir->type = 0;
696 #endif
697         return NGX_OK;
698     }
699 
700     return NGX_ERROR;
701 }
702 
703 
704 ngx_int_t
ngx_open_glob(ngx_glob_t * gl)705 ngx_open_glob(ngx_glob_t *gl)
706 {
707     int  n;
708 
709     n = glob((char *) gl->pattern, 0, NULL, &gl->pglob);
710 
711     if (n == 0) {
712         return NGX_OK;
713     }
714 
715 #ifdef GLOB_NOMATCH
716 
717     if (n == GLOB_NOMATCH && gl->test) {
718         return NGX_OK;
719     }
720 
721 #endif
722 
723     return NGX_ERROR;
724 }
725 
726 
727 ngx_int_t
ngx_read_glob(ngx_glob_t * gl,ngx_str_t * name)728 ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
729 {
730     size_t  count;
731 
732 #ifdef GLOB_NOMATCH
733     count = (size_t) gl->pglob.gl_pathc;
734 #else
735     count = (size_t) gl->pglob.gl_matchc;
736 #endif
737 
738     if (gl->n < count) {
739 
740         name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
741         name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
742         gl->n++;
743 
744         return NGX_OK;
745     }
746 
747     return NGX_DONE;
748 }
749 
750 
751 void
ngx_close_glob(ngx_glob_t * gl)752 ngx_close_glob(ngx_glob_t *gl)
753 {
754     globfree(&gl->pglob);
755 }
756 
757 
758 ngx_err_t
ngx_trylock_fd(ngx_fd_t fd)759 ngx_trylock_fd(ngx_fd_t fd)
760 {
761     struct flock  fl;
762 
763     ngx_memzero(&fl, sizeof(struct flock));
764     fl.l_type = F_WRLCK;
765     fl.l_whence = SEEK_SET;
766 
767     if (fcntl(fd, F_SETLK, &fl) == -1) {
768         return ngx_errno;
769     }
770 
771     return 0;
772 }
773 
774 
775 ngx_err_t
ngx_lock_fd(ngx_fd_t fd)776 ngx_lock_fd(ngx_fd_t fd)
777 {
778     struct flock  fl;
779 
780     ngx_memzero(&fl, sizeof(struct flock));
781     fl.l_type = F_WRLCK;
782     fl.l_whence = SEEK_SET;
783 
784     if (fcntl(fd, F_SETLKW, &fl) == -1) {
785         return ngx_errno;
786     }
787 
788     return 0;
789 }
790 
791 
792 ngx_err_t
ngx_unlock_fd(ngx_fd_t fd)793 ngx_unlock_fd(ngx_fd_t fd)
794 {
795     struct flock  fl;
796 
797     ngx_memzero(&fl, sizeof(struct flock));
798     fl.l_type = F_UNLCK;
799     fl.l_whence = SEEK_SET;
800 
801     if (fcntl(fd, F_SETLK, &fl) == -1) {
802         return  ngx_errno;
803     }
804 
805     return 0;
806 }
807 
808 
809 #if (NGX_HAVE_POSIX_FADVISE) && !(NGX_HAVE_F_READAHEAD)
810 
811 ngx_int_t
ngx_read_ahead(ngx_fd_t fd,size_t n)812 ngx_read_ahead(ngx_fd_t fd, size_t n)
813 {
814     int  err;
815 
816     err = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
817 
818     if (err == 0) {
819         return 0;
820     }
821 
822     ngx_set_errno(err);
823     return NGX_FILE_ERROR;
824 }
825 
826 #endif
827 
828 
829 #if (NGX_HAVE_O_DIRECT)
830 
831 ngx_int_t
ngx_directio_on(ngx_fd_t fd)832 ngx_directio_on(ngx_fd_t fd)
833 {
834     int  flags;
835 
836     flags = fcntl(fd, F_GETFL);
837 
838     if (flags == -1) {
839         return NGX_FILE_ERROR;
840     }
841 
842     return fcntl(fd, F_SETFL, flags | O_DIRECT);
843 }
844 
845 
846 ngx_int_t
ngx_directio_off(ngx_fd_t fd)847 ngx_directio_off(ngx_fd_t fd)
848 {
849     int  flags;
850 
851     flags = fcntl(fd, F_GETFL);
852 
853     if (flags == -1) {
854         return NGX_FILE_ERROR;
855     }
856 
857     return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
858 }
859 
860 #endif
861 
862 
863 #if (NGX_HAVE_STATFS)
864 
865 size_t
ngx_fs_bsize(u_char * name)866 ngx_fs_bsize(u_char *name)
867 {
868     struct statfs  fs;
869 
870     if (statfs((char *) name, &fs) == -1) {
871         return 512;
872     }
873 
874     if ((fs.f_bsize % 512) != 0) {
875         return 512;
876     }
877 
878     return (size_t) fs.f_bsize;
879 }
880 
881 #elif (NGX_HAVE_STATVFS)
882 
883 size_t
ngx_fs_bsize(u_char * name)884 ngx_fs_bsize(u_char *name)
885 {
886     struct statvfs  fs;
887 
888     if (statvfs((char *) name, &fs) == -1) {
889         return 512;
890     }
891 
892     if ((fs.f_frsize % 512) != 0) {
893         return 512;
894     }
895 
896     return (size_t) fs.f_frsize;
897 }
898 
899 #else
900 
901 size_t
ngx_fs_bsize(u_char * name)902 ngx_fs_bsize(u_char *name)
903 {
904     return 512;
905 }
906 
907 #endif
908