src/os/unix/ngx_files.c - nginx source code

Global variables defined

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>


  7. #if (NGX_THREADS)
  8. #include <ngx_thread_pool.h>
  9. static void ngx_thread_read_handler(void *data, ngx_log_t *log);
  10. static void ngx_thread_write_chain_to_file_handler(void *data, ngx_log_t *log);
  11. #endif

  12. static ngx_chain_t *ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl);
  13. static ssize_t ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec,
  14.     off_t offset);


  15. #if (NGX_HAVE_FILE_AIO)

  16. ngx_uint_t  ngx_file_aio = 1;

  17. #endif


  18. ssize_t
  19. ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
  20. {
  21.     ssize_t  n;

  22.     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
  23.                    "read: %d, %p, %uz, %O", file->fd, buf, size, offset);

  24. #if (NGX_HAVE_PREAD)

  25.     n = pread(file->fd, buf, size, offset);

  26.     if (n == -1) {
  27.         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  28.                       "pread() \"%s\" failed", file->name.data);
  29.         return NGX_ERROR;
  30.     }

  31. #else

  32.     if (file->sys_offset != offset) {
  33.         if (lseek(file->fd, offset, SEEK_SET) == -1) {
  34.             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  35.                           "lseek() \"%s\" failed", file->name.data);
  36.             return NGX_ERROR;
  37.         }

  38.         file->sys_offset = offset;
  39.     }

  40.     n = read(file->fd, buf, size);

  41.     if (n == -1) {
  42.         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  43.                       "read() \"%s\" failed", file->name.data);
  44.         return NGX_ERROR;
  45.     }

  46.     file->sys_offset += n;

  47. #endif

  48.     file->offset += n;

  49.     return n;
  50. }


  51. #if (NGX_THREADS)

  52. typedef struct {
  53.     ngx_fd_t       fd;
  54.     ngx_uint_t     write;   /* unsigned  write:1; */

  55.     u_char        *buf;
  56.     size_t         size;
  57.     ngx_chain_t   *chain;
  58.     off_t          offset;

  59.     size_t         nbytes;
  60.     ngx_err_t      err;
  61. } ngx_thread_file_ctx_t;


  62. ssize_t
  63. ngx_thread_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
  64.     ngx_pool_t *pool)
  65. {
  66.     ngx_thread_task_t      *task;
  67.     ngx_thread_file_ctx_t  *ctx;

  68.     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
  69.                    "thread read: %d, %p, %uz, %O",
  70.                    file->fd, buf, size, offset);

  71.     task = file->thread_task;

  72.     if (task == NULL) {
  73.         task = ngx_thread_task_alloc(pool, sizeof(ngx_thread_file_ctx_t));
  74.         if (task == NULL) {
  75.             return NGX_ERROR;
  76.         }

  77.         task->event.log = file->log;

  78.         file->thread_task = task;
  79.     }

  80.     ctx = task->ctx;

  81.     if (task->event.complete) {
  82.         task->event.complete = 0;

  83.         if (ctx->write) {
  84.             ngx_log_error(NGX_LOG_ALERT, file->log, 0,
  85.                           "invalid thread call, read instead of write");
  86.             return NGX_ERROR;
  87.         }

  88.         if (ctx->err) {
  89.             ngx_log_error(NGX_LOG_CRIT, file->log, ctx->err,
  90.                           "pread() \"%s\" failed", file->name.data);
  91.             return NGX_ERROR;
  92.         }

  93.         return ctx->nbytes;
  94.     }

  95.     task->handler = ngx_thread_read_handler;

  96.     ctx->write = 0;

  97.     ctx->fd = file->fd;
  98.     ctx->buf = buf;
  99.     ctx->size = size;
  100.     ctx->offset = offset;

  101.     if (file->thread_handler(task, file) != NGX_OK) {
  102.         return NGX_ERROR;
  103.     }

  104.     return NGX_AGAIN;
  105. }


  106. #if (NGX_HAVE_PREAD)

  107. static void
  108. ngx_thread_read_handler(void *data, ngx_log_t *log)
  109. {
  110.     ngx_thread_file_ctx_t *ctx = data;

  111.     ssize_t  n;

  112.     ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "thread read handler");

  113.     n = pread(ctx->fd, ctx->buf, ctx->size, ctx->offset);

  114.     if (n == -1) {
  115.         ctx->err = ngx_errno;

  116.     } else {
  117.         ctx->nbytes = n;
  118.         ctx->err = 0;
  119.     }

  120. #if 0
  121.     ngx_time_update();
  122. #endif

  123.     ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0,
  124.                    "pread: %z (err: %d) of %uz @%O",
  125.                    n, ctx->err, ctx->size, ctx->offset);
  126. }

  127. #else

  128. #error pread() is required!

  129. #endif

  130. #endif /* NGX_THREADS */


  131. ssize_t
  132. ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
  133. {
  134.     ssize_t    n, written;
  135.     ngx_err_t  err;

  136.     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
  137.                    "write: %d, %p, %uz, %O", file->fd, buf, size, offset);

  138.     written = 0;

  139. #if (NGX_HAVE_PWRITE)

  140.     for ( ;; ) {
  141.         n = pwrite(file->fd, buf + written, size, offset);

  142.         if (n == -1) {
  143.             err = ngx_errno;

  144.             if (err == NGX_EINTR) {
  145.                 ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
  146.                                "pwrite() was interrupted");
  147.                 continue;
  148.             }

  149.             ngx_log_error(NGX_LOG_CRIT, file->log, err,
  150.                           "pwrite() \"%s\" failed", file->name.data);
  151.             return NGX_ERROR;
  152.         }

  153.         file->offset += n;
  154.         written += n;

  155.         if ((size_t) n == size) {
  156.             return written;
  157.         }

  158.         offset += n;
  159.         size -= n;
  160.     }

  161. #else

  162.     if (file->sys_offset != offset) {
  163.         if (lseek(file->fd, offset, SEEK_SET) == -1) {
  164.             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  165.                           "lseek() \"%s\" failed", file->name.data);
  166.             return NGX_ERROR;
  167.         }

  168.         file->sys_offset = offset;
  169.     }

  170.     for ( ;; ) {
  171.         n = write(file->fd, buf + written, size);

  172.         if (n == -1) {
  173.             err = ngx_errno;

  174.             if (err == NGX_EINTR) {
  175.                 ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
  176.                                "write() was interrupted");
  177.                 continue;
  178.             }

  179.             ngx_log_error(NGX_LOG_CRIT, file->log, err,
  180.                           "write() \"%s\" failed", file->name.data);
  181.             return NGX_ERROR;
  182.         }

  183.         file->sys_offset += n;
  184.         file->offset += n;
  185.         written += n;

  186.         if ((size_t) n == size) {
  187.             return written;
  188.         }

  189.         size -= n;
  190.     }
  191. #endif
  192. }


  193. ngx_fd_t
  194. ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
  195. {
  196.     ngx_fd_t  fd;

  197.     fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,
  198.               access ? access : 0600);

  199.     if (fd != -1 && !persistent) {
  200.         (void) unlink((const char *) name);
  201.     }

  202.     return fd;
  203. }


  204. ssize_t
  205. ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
  206.     ngx_pool_t *pool)
  207. {
  208.     ssize_t        total, n;
  209.     ngx_iovec_t    vec;
  210.     struct iovec   iovs[NGX_IOVS_PREALLOCATE];

  211.     /* use pwrite() if there is the only buf in a chain */

  212.     if (cl->next == NULL) {
  213.         return ngx_write_file(file, cl->buf->pos,
  214.                               (size_t) (cl->buf->last - cl->buf->pos),
  215.                               offset);
  216.     }

  217.     total = 0;

  218.     vec.iovs = iovs;
  219.     vec.nalloc = NGX_IOVS_PREALLOCATE;

  220.     do {
  221.         /* create the iovec and coalesce the neighbouring bufs */
  222.         cl = ngx_chain_to_iovec(&vec, cl);

  223.         /* use pwrite() if there is the only iovec buffer */

  224.         if (vec.count == 1) {
  225.             n = ngx_write_file(file, (u_char *) iovs[0].iov_base,
  226.                                iovs[0].iov_len, offset);

  227.             if (n == NGX_ERROR) {
  228.                 return n;
  229.             }

  230.             return total + n;
  231.         }

  232.         n = ngx_writev_file(file, &vec, offset);

  233.         if (n == NGX_ERROR) {
  234.             return n;
  235.         }

  236.         offset += n;
  237.         total += n;

  238.     } while (cl);

  239.     return total;
  240. }


  241. static ngx_chain_t *
  242. ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl)
  243. {
  244.     size_t         total, size;
  245.     u_char        *prev;
  246.     ngx_uint_t     n;
  247.     struct iovec  *iov;

  248.     iov = NULL;
  249.     prev = NULL;
  250.     total = 0;
  251.     n = 0;

  252.     for ( /* void */ ; cl; cl = cl->next) {

  253.         if (ngx_buf_special(cl->buf)) {
  254.             continue;
  255.         }

  256.         size = cl->buf->last - cl->buf->pos;

  257.         if (prev == cl->buf->pos) {
  258.             iov->iov_len += size;

  259.         } else {
  260.             if (n == vec->nalloc) {
  261.                 break;
  262.             }

  263.             iov = &vec->iovs[n++];

  264.             iov->iov_base = (void *) cl->buf->pos;
  265.             iov->iov_len = size;
  266.         }

  267.         prev = cl->buf->pos + size;
  268.         total += size;
  269.     }

  270.     vec->count = n;
  271.     vec->size = total;

  272.     return cl;
  273. }


  274. static ssize_t
  275. ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec, off_t offset)
  276. {
  277.     ssize_t    n;
  278.     ngx_err_t  err;

  279.     ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0,
  280.                    "writev: %d, %uz, %O", file->fd, vec->size, offset);

  281. #if (NGX_HAVE_PWRITEV)

  282. eintr:

  283.     n = pwritev(file->fd, vec->iovs, vec->count, offset);

  284.     if (n == -1) {
  285.         err = ngx_errno;

  286.         if (err == NGX_EINTR) {
  287.             ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
  288.                            "pwritev() was interrupted");
  289.             goto eintr;
  290.         }

  291.         ngx_log_error(NGX_LOG_CRIT, file->log, err,
  292.                       "pwritev() \"%s\" failed", file->name.data);
  293.         return NGX_ERROR;
  294.     }

  295.     if ((size_t) n != vec->size) {
  296.         ngx_log_error(NGX_LOG_CRIT, file->log, 0,
  297.                       "pwritev() \"%s\" has written only %z of %uz",
  298.                       file->name.data, n, vec->size);
  299.         return NGX_ERROR;
  300.     }

  301. #else

  302.     if (file->sys_offset != offset) {
  303.         if (lseek(file->fd, offset, SEEK_SET) == -1) {
  304.             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  305.                           "lseek() \"%s\" failed", file->name.data);
  306.             return NGX_ERROR;
  307.         }

  308.         file->sys_offset = offset;
  309.     }

  310. eintr:

  311.     n = writev(file->fd, vec->iovs, vec->count);

  312.     if (n == -1) {
  313.         err = ngx_errno;

  314.         if (err == NGX_EINTR) {
  315.             ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
  316.                            "writev() was interrupted");
  317.             goto eintr;
  318.         }

  319.         ngx_log_error(NGX_LOG_CRIT, file->log, err,
  320.                       "writev() \"%s\" failed", file->name.data);
  321.         return NGX_ERROR;
  322.     }

  323.     if ((size_t) n != vec->size) {
  324.         ngx_log_error(NGX_LOG_CRIT, file->log, 0,
  325.                       "writev() \"%s\" has written only %z of %uz",
  326.                       file->name.data, n, vec->size);
  327.         return NGX_ERROR;
  328.     }

  329.     file->sys_offset += n;

  330. #endif

  331.     file->offset += n;

  332.     return n;
  333. }


  334. #if (NGX_THREADS)

  335. ssize_t
  336. ngx_thread_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
  337.     ngx_pool_t *pool)
  338. {
  339.     ngx_thread_task_t      *task;
  340.     ngx_thread_file_ctx_t  *ctx;

  341.     ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0,
  342.                    "thread write chain: %d, %p, %O",
  343.                    file->fd, cl, offset);

  344.     task = file->thread_task;

  345.     if (task == NULL) {
  346.         task = ngx_thread_task_alloc(pool,
  347.                                      sizeof(ngx_thread_file_ctx_t));
  348.         if (task == NULL) {
  349.             return NGX_ERROR;
  350.         }

  351.         task->event.log = file->log;

  352.         file->thread_task = task;
  353.     }

  354.     ctx = task->ctx;

  355.     if (task->event.complete) {
  356.         task->event.complete = 0;

  357.         if (!ctx->write) {
  358.             ngx_log_error(NGX_LOG_ALERT, file->log, 0,
  359.                           "invalid thread call, write instead of read");
  360.             return NGX_ERROR;
  361.         }

  362.         if (ctx->err || ctx->nbytes == 0) {
  363.             ngx_log_error(NGX_LOG_CRIT, file->log, ctx->err,
  364.                           "pwritev() \"%s\" failed", file->name.data);
  365.             return NGX_ERROR;
  366.         }

  367.         file->offset += ctx->nbytes;
  368.         return ctx->nbytes;
  369.     }

  370.     task->handler = ngx_thread_write_chain_to_file_handler;

  371.     ctx->write = 1;

  372.     ctx->fd = file->fd;
  373.     ctx->chain = cl;
  374.     ctx->offset = offset;

  375.     if (file->thread_handler(task, file) != NGX_OK) {
  376.         return NGX_ERROR;
  377.     }

  378.     return NGX_AGAIN;
  379. }


  380. static void
  381. ngx_thread_write_chain_to_file_handler(void *data, ngx_log_t *log)
  382. {
  383.     ngx_thread_file_ctx_t *ctx = data;

  384. #if (NGX_HAVE_PWRITEV)

  385.     off_t          offset;
  386.     ssize_t        n;
  387.     ngx_err_t      err;
  388.     ngx_chain_t   *cl;
  389.     ngx_iovec_t    vec;
  390.     struct iovec   iovs[NGX_IOVS_PREALLOCATE];

  391.     vec.iovs = iovs;
  392.     vec.nalloc = NGX_IOVS_PREALLOCATE;

  393.     cl = ctx->chain;
  394.     offset = ctx->offset;

  395.     ctx->nbytes = 0;
  396.     ctx->err = 0;

  397.     do {
  398.         /* create the iovec and coalesce the neighbouring bufs */
  399.         cl = ngx_chain_to_iovec(&vec, cl);

  400. eintr:

  401.         n = pwritev(ctx->fd, iovs, vec.count, offset);

  402.         if (n == -1) {
  403.             err = ngx_errno;

  404.             if (err == NGX_EINTR) {
  405.                 ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, err,
  406.                                "pwritev() was interrupted");
  407.                 goto eintr;
  408.             }

  409.             ctx->err = err;
  410.             return;
  411.         }

  412.         if ((size_t) n != vec.size) {
  413.             ctx->nbytes = 0;
  414.             return;
  415.         }

  416.         ctx->nbytes += n;
  417.         offset += n;
  418.     } while (cl);

  419. #else

  420.     ctx->err = NGX_ENOSYS;
  421.     return;

  422. #endif
  423. }

  424. #endif /* NGX_THREADS */


  425. ngx_int_t
  426. ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
  427. {
  428.     struct timeval  tv[2];

  429.     tv[0].tv_sec = ngx_time();
  430.     tv[0].tv_usec = 0;
  431.     tv[1].tv_sec = s;
  432.     tv[1].tv_usec = 0;

  433.     if (utimes((char *) name, tv) != -1) {
  434.         return NGX_OK;
  435.     }

  436.     return NGX_ERROR;
  437. }


  438. ngx_int_t
  439. ngx_create_file_mapping(ngx_file_mapping_t *fm)
  440. {
  441.     fm->fd = ngx_open_file(fm->name, NGX_FILE_RDWR, NGX_FILE_TRUNCATE,
  442.                            NGX_FILE_DEFAULT_ACCESS);

  443.     if (fm->fd == NGX_INVALID_FILE) {
  444.         ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
  445.                       ngx_open_file_n " \"%s\" failed", fm->name);
  446.         return NGX_ERROR;
  447.     }

  448.     if (ftruncate(fm->fd, fm->size) == -1) {
  449.         ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
  450.                       "ftruncate() \"%s\" failed", fm->name);
  451.         goto failed;
  452.     }

  453.     fm->addr = mmap(NULL, fm->size, PROT_READ|PROT_WRITE, MAP_SHARED,
  454.                     fm->fd, 0);
  455.     if (fm->addr != MAP_FAILED) {
  456.         return NGX_OK;
  457.     }

  458.     ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
  459.                   "mmap(%uz) \"%s\" failed", fm->size, fm->name);

  460. failed:

  461.     if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
  462.         ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
  463.                       ngx_close_file_n " \"%s\" failed", fm->name);
  464.     }

  465.     return NGX_ERROR;
  466. }


  467. void
  468. ngx_close_file_mapping(ngx_file_mapping_t *fm)
  469. {
  470.     if (munmap(fm->addr, fm->size) == -1) {
  471.         ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
  472.                       "munmap(%uz) \"%s\" failed", fm->size, fm->name);
  473.     }

  474.     if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
  475.         ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
  476.                       ngx_close_file_n " \"%s\" failed", fm->name);
  477.     }
  478. }


  479. ngx_int_t
  480. ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
  481. {
  482.     dir->dir = opendir((const char *) name->data);

  483.     if (dir->dir == NULL) {
  484.         return NGX_ERROR;
  485.     }

  486.     dir->valid_info = 0;

  487.     return NGX_OK;
  488. }


  489. ngx_int_t
  490. ngx_read_dir(ngx_dir_t *dir)
  491. {
  492.     dir->de = readdir(dir->dir);

  493.     if (dir->de) {
  494. #if (NGX_HAVE_D_TYPE)
  495.         dir->type = dir->de->d_type;
  496. #else
  497.         dir->type = 0;
  498. #endif
  499.         return NGX_OK;
  500.     }

  501.     return NGX_ERROR;
  502. }


  503. ngx_int_t
  504. ngx_open_glob(ngx_glob_t *gl)
  505. {
  506.     int  n;

  507.     n = glob((char *) gl->pattern, 0, NULL, &gl->pglob);

  508.     if (n == 0) {
  509.         return NGX_OK;
  510.     }

  511. #ifdef GLOB_NOMATCH

  512.     if (n == GLOB_NOMATCH && gl->test) {
  513.         return NGX_OK;
  514.     }

  515. #endif

  516.     return NGX_ERROR;
  517. }


  518. ngx_int_t
  519. ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
  520. {
  521.     size_t  count;

  522. #ifdef GLOB_NOMATCH
  523.     count = (size_t) gl->pglob.gl_pathc;
  524. #else
  525.     count = (size_t) gl->pglob.gl_matchc;
  526. #endif

  527.     if (gl->n < count) {

  528.         name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
  529.         name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
  530.         gl->n++;

  531.         return NGX_OK;
  532.     }

  533.     return NGX_DONE;
  534. }


  535. void
  536. ngx_close_glob(ngx_glob_t *gl)
  537. {
  538.     globfree(&gl->pglob);
  539. }


  540. ngx_err_t
  541. ngx_trylock_fd(ngx_fd_t fd)
  542. {
  543.     struct flock  fl;

  544.     ngx_memzero(&fl, sizeof(struct flock));
  545.     fl.l_type = F_WRLCK;
  546.     fl.l_whence = SEEK_SET;

  547.     if (fcntl(fd, F_SETLK, &fl) == -1) {
  548.         return ngx_errno;
  549.     }

  550.     return 0;
  551. }


  552. ngx_err_t
  553. ngx_lock_fd(ngx_fd_t fd)
  554. {
  555.     struct flock  fl;

  556.     ngx_memzero(&fl, sizeof(struct flock));
  557.     fl.l_type = F_WRLCK;
  558.     fl.l_whence = SEEK_SET;

  559.     if (fcntl(fd, F_SETLKW, &fl) == -1) {
  560.         return ngx_errno;
  561.     }

  562.     return 0;
  563. }


  564. ngx_err_t
  565. ngx_unlock_fd(ngx_fd_t fd)
  566. {
  567.     struct flock  fl;

  568.     ngx_memzero(&fl, sizeof(struct flock));
  569.     fl.l_type = F_UNLCK;
  570.     fl.l_whence = SEEK_SET;

  571.     if (fcntl(fd, F_SETLK, &fl) == -1) {
  572.         return  ngx_errno;
  573.     }

  574.     return 0;
  575. }


  576. #if (NGX_HAVE_POSIX_FADVISE) && !(NGX_HAVE_F_READAHEAD)

  577. ngx_int_t
  578. ngx_read_ahead(ngx_fd_t fd, size_t n)
  579. {
  580.     int  err;

  581.     err = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);

  582.     if (err == 0) {
  583.         return 0;
  584.     }

  585.     ngx_set_errno(err);
  586.     return NGX_FILE_ERROR;
  587. }

  588. #endif


  589. #if (NGX_HAVE_O_DIRECT)

  590. ngx_int_t
  591. ngx_directio_on(ngx_fd_t fd)
  592. {
  593.     int  flags;

  594.     flags = fcntl(fd, F_GETFL);

  595.     if (flags == -1) {
  596.         return NGX_FILE_ERROR;
  597.     }

  598.     return fcntl(fd, F_SETFL, flags | O_DIRECT);
  599. }


  600. ngx_int_t
  601. ngx_directio_off(ngx_fd_t fd)
  602. {
  603.     int  flags;

  604.     flags = fcntl(fd, F_GETFL);

  605.     if (flags == -1) {
  606.         return NGX_FILE_ERROR;
  607.     }

  608.     return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
  609. }

  610. #endif


  611. #if (NGX_HAVE_STATFS)

  612. size_t
  613. ngx_fs_bsize(u_char *name)
  614. {
  615.     struct statfs  fs;

  616.     if (statfs((char *) name, &fs) == -1) {
  617.         return 512;
  618.     }

  619.     if ((fs.f_bsize % 512) != 0) {
  620.         return 512;
  621.     }

  622. #if (NGX_LINUX)
  623.     if ((size_t) fs.f_bsize > ngx_pagesize) {
  624.         return 512;
  625.     }
  626. #endif

  627.     return (size_t) fs.f_bsize;
  628. }


  629. off_t
  630. ngx_fs_available(u_char *name)
  631. {
  632.     struct statfs  fs;

  633.     if (statfs((char *) name, &fs) == -1) {
  634.         return NGX_MAX_OFF_T_VALUE;
  635.     }

  636.     return (off_t) fs.f_bavail * fs.f_bsize;
  637. }

  638. #elif (NGX_HAVE_STATVFS)

  639. size_t
  640. ngx_fs_bsize(u_char *name)
  641. {
  642.     struct statvfs  fs;

  643.     if (statvfs((char *) name, &fs) == -1) {
  644.         return 512;
  645.     }

  646.     if ((fs.f_frsize % 512) != 0) {
  647.         return 512;
  648.     }

  649. #if (NGX_LINUX)
  650.     if ((size_t) fs.f_frsize > ngx_pagesize) {
  651.         return 512;
  652.     }
  653. #endif

  654.     return (size_t) fs.f_frsize;
  655. }


  656. off_t
  657. ngx_fs_available(u_char *name)
  658. {
  659.     struct statvfs  fs;

  660.     if (statvfs((char *) name, &fs) == -1) {
  661.         return NGX_MAX_OFF_T_VALUE;
  662.     }

  663.     return (off_t) fs.f_bavail * fs.f_frsize;
  664. }

  665. #else

  666. size_t
  667. ngx_fs_bsize(u_char *name)
  668. {
  669.     return 512;
  670. }


  671. off_t
  672. ngx_fs_available(u_char *name)
  673. {
  674.     return NGX_MAX_OFF_T_VALUE;
  675. }

  676. #endif