src/os/unix/ngx_files.c - nginx-1.7.10

Global variables defined

Functions defined

Macros 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_HAVE_FILE_AIO)

  8. ngx_uint_t  ngx_file_aio = 1;

  9. #endif


  10. ssize_t
  11. ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
  12. {
  13.     ssize_t  n;

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

  16. #if (NGX_HAVE_PREAD)

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

  18.     if (n == -1) {
  19.         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  20.                       "pread() \"%s\" failed", file->name.data);
  21.         return NGX_ERROR;
  22.     }

  23. #else

  24.     if (file->sys_offset != offset) {
  25.         if (lseek(file->fd, offset, SEEK_SET) == -1) {
  26.             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  27.                           "lseek() \"%s\" failed", file->name.data);
  28.             return NGX_ERROR;
  29.         }

  30.         file->sys_offset = offset;
  31.     }

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

  33.     if (n == -1) {
  34.         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  35.                       "read() \"%s\" failed", file->name.data);
  36.         return NGX_ERROR;
  37.     }

  38.     file->sys_offset += n;

  39. #endif

  40.     file->offset += n;

  41.     return n;
  42. }


  43. ssize_t
  44. ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
  45. {
  46.     ssize_t  n, written;

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

  49.     written = 0;

  50. #if (NGX_HAVE_PWRITE)

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

  53.         if (n == -1) {
  54.             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  55.                           "pwrite() \"%s\" failed", file->name.data);
  56.             return NGX_ERROR;
  57.         }

  58.         file->offset += n;
  59.         written += n;

  60.         if ((size_t) n == size) {
  61.             return written;
  62.         }

  63.         offset += n;
  64.         size -= n;
  65.     }

  66. #else

  67.     if (file->sys_offset != offset) {
  68.         if (lseek(file->fd, offset, SEEK_SET) == -1) {
  69.             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  70.                           "lseek() \"%s\" failed", file->name.data);
  71.             return NGX_ERROR;
  72.         }

  73.         file->sys_offset = offset;
  74.     }

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

  77.         if (n == -1) {
  78.             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  79.                           "write() \"%s\" failed", file->name.data);
  80.             return NGX_ERROR;
  81.         }

  82.         file->offset += n;
  83.         written += n;

  84.         if ((size_t) n == size) {
  85.             return written;
  86.         }

  87.         size -= n;
  88.     }
  89. #endif
  90. }


  91. ngx_fd_t
  92. ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
  93. {
  94.     ngx_fd_t  fd;

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

  97.     if (fd != -1 && !persistent) {
  98.         (void) unlink((const char *) name);
  99.     }

  100.     return fd;
  101. }


  102. #define NGX_IOVS  8

  103. ssize_t
  104. ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
  105.     ngx_pool_t *pool)
  106. {
  107.     u_char        *prev;
  108.     size_t         size;
  109.     ssize_t        total, n;
  110.     ngx_array_t    vec;
  111.     struct iovec  *iov, iovs[NGX_IOVS];

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

  113.     if (cl->next == NULL) {
  114.         return ngx_write_file(file, cl->buf->pos,
  115.                               (size_t) (cl->buf->last - cl->buf->pos),
  116.                               offset);
  117.     }

  118.     total = 0;

  119.     vec.elts = iovs;
  120.     vec.size = sizeof(struct iovec);
  121.     vec.nalloc = NGX_IOVS;
  122.     vec.pool = pool;

  123.     do {
  124.         prev = NULL;
  125.         iov = NULL;
  126.         size = 0;

  127.         vec.nelts = 0;

  128.         /* create the iovec and coalesce the neighbouring bufs */

  129.         while (cl && vec.nelts < IOV_MAX) {
  130.             if (prev == cl->buf->pos) {
  131.                 iov->iov_len += cl->buf->last - cl->buf->pos;

  132.             } else {
  133.                 iov = ngx_array_push(&vec);
  134.                 if (iov == NULL) {
  135.                     return NGX_ERROR;
  136.                 }

  137.                 iov->iov_base = (void *) cl->buf->pos;
  138.                 iov->iov_len = cl->buf->last - cl->buf->pos;
  139.             }

  140.             size += cl->buf->last - cl->buf->pos;
  141.             prev = cl->buf->last;
  142.             cl = cl->next;
  143.         }

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

  145.         if (vec.nelts == 1) {
  146.             iov = vec.elts;

  147.             n = ngx_write_file(file, (u_char *) iov[0].iov_base,
  148.                                iov[0].iov_len, offset);

  149.             if (n == NGX_ERROR) {
  150.                 return n;
  151.             }

  152.             return total + n;
  153.         }

  154.         if (file->sys_offset != offset) {
  155.             if (lseek(file->fd, offset, SEEK_SET) == -1) {
  156.                 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  157.                               "lseek() \"%s\" failed", file->name.data);
  158.                 return NGX_ERROR;
  159.             }

  160.             file->sys_offset = offset;
  161.         }

  162.         n = writev(file->fd, vec.elts, vec.nelts);

  163.         if (n == -1) {
  164.             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  165.                           "writev() \"%s\" failed", file->name.data);
  166.             return NGX_ERROR;
  167.         }

  168.         if ((size_t) n != size) {
  169.             ngx_log_error(NGX_LOG_CRIT, file->log, 0,
  170.                           "writev() \"%s\" has written only %z of %uz",
  171.                           file->name.data, n, size);
  172.             return NGX_ERROR;
  173.         }

  174.         ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0,
  175.                        "writev: %d, %z", file->fd, n);

  176.         file->sys_offset += n;
  177.         file->offset += n;
  178.         offset += n;
  179.         total += n;

  180.     } while (cl);

  181.     return total;
  182. }


  183. ngx_int_t
  184. ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
  185. {
  186.     struct timeval  tv[2];

  187.     tv[0].tv_sec = ngx_time();
  188.     tv[0].tv_usec = 0;
  189.     tv[1].tv_sec = s;
  190.     tv[1].tv_usec = 0;

  191.     if (utimes((char *) name, tv) != -1) {
  192.         return NGX_OK;
  193.     }

  194.     return NGX_ERROR;
  195. }


  196. ngx_int_t
  197. ngx_create_file_mapping(ngx_file_mapping_t *fm)
  198. {
  199.     fm->fd = ngx_open_file(fm->name, NGX_FILE_RDWR, NGX_FILE_TRUNCATE,
  200.                            NGX_FILE_DEFAULT_ACCESS);
  201.     if (fm->fd == NGX_INVALID_FILE) {
  202.         ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
  203.                       ngx_open_file_n " \"%s\" failed", fm->name);
  204.         return NGX_ERROR;
  205.     }

  206.     if (ftruncate(fm->fd, fm->size) == -1) {
  207.         ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
  208.                       "ftruncate() \"%s\" failed", fm->name);
  209.         goto failed;
  210.     }

  211.     fm->addr = mmap(NULL, fm->size, PROT_READ|PROT_WRITE, MAP_SHARED,
  212.                     fm->fd, 0);
  213.     if (fm->addr != MAP_FAILED) {
  214.         return NGX_OK;
  215.     }

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

  218. failed:

  219.     if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
  220.         ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
  221.                       ngx_close_file_n " \"%s\" failed", fm->name);
  222.     }

  223.     return NGX_ERROR;
  224. }


  225. void
  226. ngx_close_file_mapping(ngx_file_mapping_t *fm)
  227. {
  228.     if (munmap(fm->addr, fm->size) == -1) {
  229.         ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
  230.                       "munmap(%uz) \"%s\" failed", fm->size, fm->name);
  231.     }

  232.     if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
  233.         ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
  234.                       ngx_close_file_n " \"%s\" failed", fm->name);
  235.     }
  236. }


  237. ngx_int_t
  238. ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
  239. {
  240.     dir->dir = opendir((const char *) name->data);

  241.     if (dir->dir == NULL) {
  242.         return NGX_ERROR;
  243.     }

  244.     dir->valid_info = 0;

  245.     return NGX_OK;
  246. }


  247. ngx_int_t
  248. ngx_read_dir(ngx_dir_t *dir)
  249. {
  250.     dir->de = readdir(dir->dir);

  251.     if (dir->de) {
  252. #if (NGX_HAVE_D_TYPE)
  253.         dir->type = dir->de->d_type;
  254. #else
  255.         dir->type = 0;
  256. #endif
  257.         return NGX_OK;
  258.     }

  259.     return NGX_ERROR;
  260. }


  261. ngx_int_t
  262. ngx_open_glob(ngx_glob_t *gl)
  263. {
  264.     int  n;

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

  266.     if (n == 0) {
  267.         return NGX_OK;
  268.     }

  269. #ifdef GLOB_NOMATCH

  270.     if (n == GLOB_NOMATCH && gl->test) {
  271.         return NGX_OK;
  272.     }

  273. #endif

  274.     return NGX_ERROR;
  275. }


  276. ngx_int_t
  277. ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
  278. {
  279.     size_t  count;

  280. #ifdef GLOB_NOMATCH
  281.     count = (size_t) gl->pglob.gl_pathc;
  282. #else
  283.     count = (size_t) gl->pglob.gl_matchc;
  284. #endif

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

  286.         name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
  287.         name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
  288.         gl->n++;

  289.         return NGX_OK;
  290.     }

  291.     return NGX_DONE;
  292. }


  293. void
  294. ngx_close_glob(ngx_glob_t *gl)
  295. {
  296.     globfree(&gl->pglob);
  297. }


  298. ngx_err_t
  299. ngx_trylock_fd(ngx_fd_t fd)
  300. {
  301.     struct flock  fl;

  302.     ngx_memzero(&fl, sizeof(struct flock));
  303.     fl.l_type = F_WRLCK;
  304.     fl.l_whence = SEEK_SET;

  305.     if (fcntl(fd, F_SETLK, &fl) == -1) {
  306.         return ngx_errno;
  307.     }

  308.     return 0;
  309. }


  310. ngx_err_t
  311. ngx_lock_fd(ngx_fd_t fd)
  312. {
  313.     struct flock  fl;

  314.     ngx_memzero(&fl, sizeof(struct flock));
  315.     fl.l_type = F_WRLCK;
  316.     fl.l_whence = SEEK_SET;

  317.     if (fcntl(fd, F_SETLKW, &fl) == -1) {
  318.         return ngx_errno;
  319.     }

  320.     return 0;
  321. }


  322. ngx_err_t
  323. ngx_unlock_fd(ngx_fd_t fd)
  324. {
  325.     struct flock  fl;

  326.     ngx_memzero(&fl, sizeof(struct flock));
  327.     fl.l_type = F_UNLCK;
  328.     fl.l_whence = SEEK_SET;

  329.     if (fcntl(fd, F_SETLK, &fl) == -1) {
  330.         return  ngx_errno;
  331.     }

  332.     return 0;
  333. }


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

  335. ngx_int_t
  336. ngx_read_ahead(ngx_fd_t fd, size_t n)
  337. {
  338.     int  err;

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

  340.     if (err == 0) {
  341.         return 0;
  342.     }

  343.     ngx_set_errno(err);
  344.     return NGX_FILE_ERROR;
  345. }

  346. #endif


  347. #if (NGX_HAVE_O_DIRECT)

  348. ngx_int_t
  349. ngx_directio_on(ngx_fd_t fd)
  350. {
  351.     int  flags;

  352.     flags = fcntl(fd, F_GETFL);

  353.     if (flags == -1) {
  354.         return NGX_FILE_ERROR;
  355.     }

  356.     return fcntl(fd, F_SETFL, flags | O_DIRECT);
  357. }


  358. ngx_int_t
  359. ngx_directio_off(ngx_fd_t fd)
  360. {
  361.     int  flags;

  362.     flags = fcntl(fd, F_GETFL);

  363.     if (flags == -1) {
  364.         return NGX_FILE_ERROR;
  365.     }

  366.     return fcntl(fd, F_SETFL, flags & ~O_DIRECT);
  367. }

  368. #endif


  369. #if (NGX_HAVE_STATFS)

  370. size_t
  371. ngx_fs_bsize(u_char *name)
  372. {
  373.     struct statfs  fs;

  374.     if (statfs((char *) name, &fs) == -1) {
  375.         return 512;
  376.     }

  377.     if ((fs.f_bsize % 512) != 0) {
  378.         return 512;
  379.     }

  380.     return (size_t) fs.f_bsize;
  381. }

  382. #elif (NGX_HAVE_STATVFS)

  383. size_t
  384. ngx_fs_bsize(u_char *name)
  385. {
  386.     struct statvfs  fs;

  387.     if (statvfs((char *) name, &fs) == -1) {
  388.         return 512;
  389.     }

  390.     if ((fs.f_frsize % 512) != 0) {
  391.         return 512;
  392.     }

  393.     return (size_t) fs.f_frsize;
  394. }

  395. #else

  396. size_t
  397. ngx_fs_bsize(u_char *name)
  398. {
  399.     return 512;
  400. }

  401. #endif