Mercurial > hg > nginx-quic
view src/os/unix/ngx_solaris_sendfilev_chain.c @ 6469:7cdf612fd58c
Win32: replaced NGX_EXDEV with more appropriate error code.
Correct error code for NGX_EXDEV on Windows is ERROR_NOT_SAME_DEVICE,
"The system cannot move the file to a different disk drive".
Previously used ERROR_WRONG_DISK is about wrong diskette in the drive and
is not appropriate.
There is no real difference though, as MoveFile() is able to copy files
between disk drives, and will fail with ERROR_ACCESS_DENIED when asked
to copy directories. The ERROR_NOT_SAME_DEVICE error is only used
by MoveFileEx() when called without the MOVEFILE_COPY_ALLOWED flag.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 29 Mar 2016 09:52:15 +0300 |
parents | 646985c55393 |
children |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> #if (NGX_TEST_BUILD_SOLARIS_SENDFILEV) /* Solaris declarations */ typedef struct sendfilevec { int sfv_fd; u_int sfv_flag; off_t sfv_off; size_t sfv_len; } sendfilevec_t; #define SFV_FD_SELF -2 static ssize_t sendfilev(int fd, const struct sendfilevec *vec, int sfvcnt, size_t *xferred) { return -1; } ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit); #endif #define NGX_SENDFILEVECS NGX_IOVS_PREALLOCATE ngx_chain_t * ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { int fd; u_char *prev; off_t size, send, prev_send, aligned, fprev; size_t sent; ssize_t n; ngx_int_t eintr; ngx_err_t err; ngx_buf_t *file; ngx_uint_t nsfv; sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS]; ngx_event_t *wev; ngx_chain_t *cl; wev = c->write; if (!wev->ready) { return in; } if (!c->sendfile) { return ngx_writev_chain(c, in, limit); } /* the maximum limit size is the maximum size_t value - the page size */ if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; } send = 0; for ( ;; ) { fd = SFV_FD_SELF; prev = NULL; fprev = 0; file = NULL; sfv = NULL; eintr = 0; sent = 0; prev_send = send; nsfv = 0; /* create the sendfilevec and coalesce the neighbouring bufs */ for (cl = in; cl && send < limit; cl = cl->next) { if (ngx_buf_special(cl->buf)) { continue; } if (ngx_buf_in_memory_only(cl->buf)) { fd = SFV_FD_SELF; size = cl->buf->last - cl->buf->pos; if (send + size > limit) { size = limit - send; } if (prev == cl->buf->pos) { sfv->sfv_len += (size_t) size; } else { if (nsfv == NGX_SENDFILEVECS) { break; } sfv = &sfvs[nsfv++]; sfv->sfv_fd = SFV_FD_SELF; sfv->sfv_flag = 0; sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos; sfv->sfv_len = (size_t) size; } prev = cl->buf->pos + (size_t) size; send += size; } else { prev = NULL; size = cl->buf->file_last - cl->buf->file_pos; if (send + size > limit) { size = limit - send; aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) & ~((off_t) ngx_pagesize - 1); if (aligned <= cl->buf->file_last) { size = aligned - cl->buf->file_pos; } } if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) { sfv->sfv_len += (size_t) size; } else { if (nsfv == NGX_SENDFILEVECS) { break; } sfv = &sfvs[nsfv++]; fd = cl->buf->file->fd; sfv->sfv_fd = fd; sfv->sfv_flag = 0; sfv->sfv_off = cl->buf->file_pos; sfv->sfv_len = (size_t) size; } file = cl->buf; fprev = cl->buf->file_pos + size; send += size; } } n = sendfilev(c->fd, sfvs, nsfv, &sent); if (n == -1) { err = ngx_errno; switch (err) { case NGX_EAGAIN: break; case NGX_EINTR: eintr = 1; break; default: wev->error = 1; ngx_connection_error(c, err, "sendfilev() failed"); return NGX_CHAIN_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, "sendfilev() sent only %uz bytes", sent); } else if (n == 0 && sent == 0) { /* * sendfilev() is documented to return -1 with errno * set to EINVAL if svf_len is greater than the file size, * but at least Solaris 11 returns 0 instead */ if (file) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "sendfilev() reported that \"%s\" was truncated at %O", file->file->name.data, file->file_pos); } else { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "sendfilev() returned 0 with memory buffers"); } return NGX_CHAIN_ERROR; } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfilev: %z %z", n, sent); c->sent += sent; in = ngx_chain_update_sent(in, sent); if (eintr) { send = prev_send + sent; continue; } if (send - prev_send != (off_t) sent) { wev->ready = 0; return in; } if (send >= limit || in == NULL) { return in; } } }