Mercurial > hg > nginx-mail
view src/os/unix/ngx_files.c @ 436:9b19e26b2660
Mail: smtp pipelining support.
Basically, this does the following two changes (and corresponding
modifications of related code):
1. Does not reset session buffer unless it's reached it's end, and always
wait for LF to terminate command (even if we detected invalid command).
2. Record command name as the first argument to make it available for
handlers (since now we can't assume that command starts from s->buffer->start).
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 11 Sep 2008 15:26:25 +0400 |
parents | 79c5df00501e |
children | a8e3f1441eec |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev */ #include <ngx_config.h> #include <ngx_core.h> ssize_t ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) { ssize_t n; ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, "read: %d, %p, %uz, %O", file->fd, buf, size, offset); #if (NGX_HAVE_PREAD) n = pread(file->fd, buf, size, offset); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pread() failed, file \"%s\"", file->name.data); return NGX_ERROR; } #else if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed"); return NGX_ERROR; } file->sys_offset = offset; } n = read(file->fd, buf, size); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "read() failed"); return NGX_ERROR; } file->sys_offset += n; #endif file->offset += n; return n; } ssize_t ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) { ssize_t n; ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, "write: %d, %p, %uz, %O", file->fd, buf, size, offset); #if (NGX_HAVE_PWRITE) n = pwrite(file->fd, buf, size, offset); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pwrite() failed"); return NGX_ERROR; } if ((size_t) n != size) { ngx_log_error(NGX_LOG_CRIT, file->log, 0, "pwrite() has written only %z of %uz", n, size); return NGX_ERROR; } #else if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed"); return NGX_ERROR; } file->sys_offset = offset; } n = write(file->fd, buf, size); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "write() failed"); return NGX_ERROR; } if ((size_t) n != size) { ngx_log_error(NGX_LOG_CRIT, file->log, 0, "write() has written only %z of %uz", n, size); return NGX_ERROR; } file->sys_offset += n; #endif file->offset += n; return n; } ngx_fd_t ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access) { ngx_fd_t fd; fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR, access ? access : 0600); if (fd != -1 && !persistent) { unlink((const char *) name); } return fd; } #define NGX_IOVS 8 ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, ngx_pool_t *pool) { u_char *prev; size_t size; ssize_t n; ngx_array_t vec; struct iovec *iov, iovs[NGX_IOVS]; /* use pwrite() if there is the only buf in a chain */ if (cl->next == NULL) { return ngx_write_file(file, cl->buf->pos, (size_t) (cl->buf->last - cl->buf->pos), offset); } vec.elts = iovs; vec.size = sizeof(struct iovec); vec.nalloc = NGX_IOVS; vec.pool = pool; do { prev = NULL; iov = NULL; size = 0; vec.nelts = 0; /* create the iovec and coalesce the neighbouring bufs */ while (cl && vec.nelts < IOV_MAX) { if (prev == cl->buf->pos) { iov->iov_len += cl->buf->last - cl->buf->pos; } else { iov = ngx_array_push(&vec); if (iov == NULL) { return NGX_ERROR; } iov->iov_base = (void *) cl->buf->pos; iov->iov_len = cl->buf->last - cl->buf->pos; } size += cl->buf->last - cl->buf->pos; prev = cl->buf->last; cl = cl->next; } /* use pwrite() if there is the only iovec buffer */ if (vec.nelts == 1) { iov = vec.elts; return ngx_write_file(file, (u_char *) iov[0].iov_base, iov[0].iov_len, offset); } if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed"); return NGX_ERROR; } file->sys_offset = offset; } n = writev(file->fd, vec.elts, vec.nelts); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "writev() failed"); return NGX_ERROR; } if ((size_t) n != size) { ngx_log_error(NGX_LOG_CRIT, file->log, 0, "writev() has written only %z of %uz", n, size); return NGX_ERROR; } file->sys_offset += n; file->offset += n; } while (cl); return n; } ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s) { struct timeval tv[2]; tv[0].tv_sec = s; tv[0].tv_usec = 0; tv[1].tv_sec = s; tv[1].tv_usec = 0; if (utimes((char *) name, tv) != -1) { return NGX_OK; } return NGX_ERROR; } ngx_int_t ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir) { dir->dir = opendir((const char *) name->data); if (dir->dir == NULL) { return NGX_ERROR; } dir->valid_info = 0; #if (NGX_HAVE_D_TYPE) dir->valid_type = 1; #else dir->valid_type = 0; #endif return NGX_OK; } ngx_int_t ngx_read_dir(ngx_dir_t *dir) { dir->de = readdir(dir->dir); if (dir->de) { #if (NGX_HAVE_D_TYPE) dir->type = dir->de->d_type; #endif return NGX_OK; } return NGX_ERROR; } ngx_int_t ngx_open_glob(ngx_glob_t *gl) { int n; n = glob((char *) gl->pattern, GLOB_NOSORT, NULL, &gl->pglob); if (n == 0) { return NGX_OK; } #ifdef GLOB_NOMATCH if (n == GLOB_NOMATCH && gl->test) { return NGX_OK; } #endif return NGX_ERROR; } ngx_int_t ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name) { size_t count; #ifdef GLOB_NOMATCH count = (size_t) gl->pglob.gl_pathc; #else count = (size_t) gl->pglob.gl_matchc; #endif if (gl->n < count) { name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]); name->data = (u_char *) gl->pglob.gl_pathv[gl->n]; gl->n++; return NGX_OK; } return NGX_DONE; } void ngx_close_glob(ngx_glob_t *gl) { globfree(&gl->pglob); } ngx_err_t ngx_trylock_fd(ngx_fd_t fd) { struct flock fl; fl.l_start = 0; fl.l_len = 0; fl.l_pid = 0; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; if (fcntl(fd, F_SETLK, &fl) == -1) { return ngx_errno; } return 0; } ngx_err_t ngx_lock_fd(ngx_fd_t fd) { struct flock fl; fl.l_start = 0; fl.l_len = 0; fl.l_pid = 0; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; if (fcntl(fd, F_SETLKW, &fl) == -1) { return ngx_errno; } return 0; } ngx_err_t ngx_unlock_fd(ngx_fd_t fd) { struct flock fl; fl.l_start = 0; fl.l_len = 0; fl.l_pid = 0; fl.l_type = F_UNLCK; fl.l_whence = SEEK_SET; if (fcntl(fd, F_SETLK, &fl) == -1) { return ngx_errno; } return 0; } #if (NGX_HAVE_O_DIRECT) ngx_int_t ngx_directio(ngx_fd_t fd) { int flags; flags = fcntl(fd, F_GETFL); if (flags == -1) { return -1; } return fcntl(fd, F_SETFL, flags | O_DIRECT); } #endif