1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev#if (NGX_THREADS)
13e18a033bSKonstantin Ananyev#include <ngx_thread_pool.h>
14e18a033bSKonstantin Ananyevstatic void ngx_thread_read_handler(void *data, ngx_log_t *log);
15e18a033bSKonstantin Ananyevstatic void ngx_thread_write_chain_to_file_handler(void *data, ngx_log_t *log);
16e18a033bSKonstantin Ananyev#endif
17e18a033bSKonstantin Ananyev
18e18a033bSKonstantin Ananyevstatic ngx_chain_t *ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl);
19e18a033bSKonstantin Ananyevstatic ssize_t ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec,
20e18a033bSKonstantin Ananyev    off_t offset);
21e18a033bSKonstantin Ananyev
22e18a033bSKonstantin Ananyev
23e18a033bSKonstantin Ananyev#if (NGX_HAVE_FILE_AIO)
24e18a033bSKonstantin Ananyev
25e18a033bSKonstantin Ananyevngx_uint_t  ngx_file_aio = 1;
26e18a033bSKonstantin Ananyev
27e18a033bSKonstantin Ananyev#endif
28e18a033bSKonstantin Ananyev
29e18a033bSKonstantin Ananyev
30e18a033bSKonstantin Ananyevssize_t
31e18a033bSKonstantin Ananyevngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
32e18a033bSKonstantin Ananyev{
33e18a033bSKonstantin Ananyev    ssize_t  n;
34e18a033bSKonstantin Ananyev
35e18a033bSKonstantin Ananyev    ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
36e18a033bSKonstantin Ananyev                   "read: %d, %p, %uz, %O", file->fd, buf, size, offset);
37e18a033bSKonstantin Ananyev
38e18a033bSKonstantin Ananyev#if (NGX_HAVE_PREAD)
39e18a033bSKonstantin Ananyev
40e18a033bSKonstantin Ananyev    n = pread(file->fd, buf, size, offset);
41e18a033bSKonstantin Ananyev
42e18a033bSKonstantin Ananyev    if (n == -1) {
43e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
44e18a033bSKonstantin Ananyev                      "pread() \"%s\" failed", file->name.data);
45e18a033bSKonstantin Ananyev        return NGX_ERROR;
46e18a033bSKonstantin Ananyev    }
47e18a033bSKonstantin Ananyev
48e18a033bSKonstantin Ananyev#else
49e18a033bSKonstantin Ananyev
50e18a033bSKonstantin Ananyev    if (file->sys_offset != offset) {
51e18a033bSKonstantin Ananyev        if (lseek(file->fd, offset, SEEK_SET) == -1) {
52e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
53e18a033bSKonstantin Ananyev                          "lseek() \"%s\" failed", file->name.data);
54e18a033bSKonstantin Ananyev            return NGX_ERROR;
55e18a033bSKonstantin Ananyev        }
56e18a033bSKonstantin Ananyev
57e18a033bSKonstantin Ananyev        file->sys_offset = offset;
58e18a033bSKonstantin Ananyev    }
59e18a033bSKonstantin Ananyev
60e18a033bSKonstantin Ananyev    n = read(file->fd, buf, size);
61e18a033bSKonstantin Ananyev
62e18a033bSKonstantin Ananyev    if (n == -1) {
63e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
64e18a033bSKonstantin Ananyev                      "read() \"%s\" failed", file->name.data);
65e18a033bSKonstantin Ananyev        return NGX_ERROR;
66e18a033bSKonstantin Ananyev    }
67e18a033bSKonstantin Ananyev
68e18a033bSKonstantin Ananyev    file->sys_offset += n;
69e18a033bSKonstantin Ananyev
70e18a033bSKonstantin Ananyev#endif
71e18a033bSKonstantin Ananyev
72e18a033bSKonstantin Ananyev    file->offset += n;
73e18a033bSKonstantin Ananyev
74e18a033bSKonstantin Ananyev    return n;
75e18a033bSKonstantin Ananyev}
76e18a033bSKonstantin Ananyev
77e18a033bSKonstantin Ananyev
78e18a033bSKonstantin Ananyev#if (NGX_THREADS)
79e18a033bSKonstantin Ananyev
80e18a033bSKonstantin Ananyevtypedef struct {
81e18a033bSKonstantin Ananyev    ngx_fd_t       fd;
82e18a033bSKonstantin Ananyev    ngx_uint_t     write;   /* unsigned  write:1; */
83e18a033bSKonstantin Ananyev
84e18a033bSKonstantin Ananyev    u_char        *buf;
85e18a033bSKonstantin Ananyev    size_t         size;
86e18a033bSKonstantin Ananyev    ngx_chain_t   *chain;
87e18a033bSKonstantin Ananyev    off_t          offset;
88e18a033bSKonstantin Ananyev
89e18a033bSKonstantin Ananyev    size_t         nbytes;
90e18a033bSKonstantin Ananyev    ngx_err_t      err;
91e18a033bSKonstantin Ananyev} ngx_thread_file_ctx_t;
92e18a033bSKonstantin Ananyev
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyevssize_t
95e18a033bSKonstantin Ananyevngx_thread_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
96e18a033bSKonstantin Ananyev    ngx_pool_t *pool)
97e18a033bSKonstantin Ananyev{
98e18a033bSKonstantin Ananyev    ngx_thread_task_t      *task;
99e18a033bSKonstantin Ananyev    ngx_thread_file_ctx_t  *ctx;
100e18a033bSKonstantin Ananyev
101e18a033bSKonstantin Ananyev    ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
102e18a033bSKonstantin Ananyev                   "thread read: %d, %p, %uz, %O",
103e18a033bSKonstantin Ananyev                   file->fd, buf, size, offset);
104e18a033bSKonstantin Ananyev
105e18a033bSKonstantin Ananyev    task = file->thread_task;
106e18a033bSKonstantin Ananyev
107e18a033bSKonstantin Ananyev    if (task == NULL) {
108e18a033bSKonstantin Ananyev        task = ngx_thread_task_alloc(pool, sizeof(ngx_thread_file_ctx_t));
109e18a033bSKonstantin Ananyev        if (task == NULL) {
110e18a033bSKonstantin Ananyev            return NGX_ERROR;
111e18a033bSKonstantin Ananyev        }
112e18a033bSKonstantin Ananyev
113e18a033bSKonstantin Ananyev        file->thread_task = task;
114e18a033bSKonstantin Ananyev    }
115e18a033bSKonstantin Ananyev
116e18a033bSKonstantin Ananyev    ctx = task->ctx;
117e18a033bSKonstantin Ananyev
118e18a033bSKonstantin Ananyev    if (task->event.complete) {
119e18a033bSKonstantin Ananyev        task->event.complete = 0;
120e18a033bSKonstantin Ananyev
121e18a033bSKonstantin Ananyev        if (ctx->write) {
122e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, file->log, 0,
123e18a033bSKonstantin Ananyev                          "invalid thread call, read instead of write");
124e18a033bSKonstantin Ananyev            return NGX_ERROR;
125e18a033bSKonstantin Ananyev        }
126e18a033bSKonstantin Ananyev
127e18a033bSKonstantin Ananyev        if (ctx->err) {
128e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_CRIT, file->log, ctx->err,
129e18a033bSKonstantin Ananyev                          "pread() \"%s\" failed", file->name.data);
130e18a033bSKonstantin Ananyev            return NGX_ERROR;
131e18a033bSKonstantin Ananyev        }
132e18a033bSKonstantin Ananyev
133e18a033bSKonstantin Ananyev        return ctx->nbytes;
134e18a033bSKonstantin Ananyev    }
135e18a033bSKonstantin Ananyev
136e18a033bSKonstantin Ananyev    task->handler = ngx_thread_read_handler;
137e18a033bSKonstantin Ananyev
138e18a033bSKonstantin Ananyev    ctx->write = 0;
139e18a033bSKonstantin Ananyev
140e18a033bSKonstantin Ananyev    ctx->fd = file->fd;
141e18a033bSKonstantin Ananyev    ctx->buf = buf;
142e18a033bSKonstantin Ananyev    ctx->size = size;
143e18a033bSKonstantin Ananyev    ctx->offset = offset;
144e18a033bSKonstantin Ananyev
145e18a033bSKonstantin Ananyev    if (file->thread_handler(task, file) != NGX_OK) {
146e18a033bSKonstantin Ananyev        return NGX_ERROR;
147e18a033bSKonstantin Ananyev    }
148e18a033bSKonstantin Ananyev
149e18a033bSKonstantin Ananyev    return NGX_AGAIN;
150e18a033bSKonstantin Ananyev}
151e18a033bSKonstantin Ananyev
152e18a033bSKonstantin Ananyev
153e18a033bSKonstantin Ananyev#if (NGX_HAVE_PREAD)
154e18a033bSKonstantin Ananyev
155e18a033bSKonstantin Ananyevstatic void
156e18a033bSKonstantin Ananyevngx_thread_read_handler(void *data, ngx_log_t *log)
157e18a033bSKonstantin Ananyev{
158e18a033bSKonstantin Ananyev    ngx_thread_file_ctx_t *ctx = data;
159e18a033bSKonstantin Ananyev
160e18a033bSKonstantin Ananyev    ssize_t  n;
161e18a033bSKonstantin Ananyev
162e18a033bSKonstantin Ananyev    ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "thread read handler");
163e18a033bSKonstantin Ananyev
164e18a033bSKonstantin Ananyev    n = pread(ctx->fd, ctx->buf, ctx->size, ctx->offset);
165e18a033bSKonstantin Ananyev
166e18a033bSKonstantin Ananyev    if (n == -1) {
167e18a033bSKonstantin Ananyev        ctx->err = ngx_errno;
168e18a033bSKonstantin Ananyev
169e18a033bSKonstantin Ananyev    } else {
170e18a033bSKonstantin Ananyev        ctx->nbytes = n;
171e18a033bSKonstantin Ananyev        ctx->err = 0;
172e18a033bSKonstantin Ananyev    }
173e18a033bSKonstantin Ananyev
174e18a033bSKonstantin Ananyev#if 0
175e18a033bSKonstantin Ananyev    ngx_time_update();
176e18a033bSKonstantin Ananyev#endif
177e18a033bSKonstantin Ananyev
178e18a033bSKonstantin Ananyev    ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0,
179e18a033bSKonstantin Ananyev                   "pread: %z (err: %d) of %uz @%O",
180e18a033bSKonstantin Ananyev                   n, ctx->err, ctx->size, ctx->offset);
181e18a033bSKonstantin Ananyev}
182e18a033bSKonstantin Ananyev
183e18a033bSKonstantin Ananyev#else
184e18a033bSKonstantin Ananyev
185e18a033bSKonstantin Ananyev#error pread() is required!
186e18a033bSKonstantin Ananyev
187e18a033bSKonstantin Ananyev#endif
188e18a033bSKonstantin Ananyev
189e18a033bSKonstantin Ananyev#endif /* NGX_THREADS */
190e18a033bSKonstantin Ananyev
191e18a033bSKonstantin Ananyev
192e18a033bSKonstantin Ananyevssize_t
193e18a033bSKonstantin Ananyevngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
194e18a033bSKonstantin Ananyev{
195e18a033bSKonstantin Ananyev    ssize_t    n, written;
196e18a033bSKonstantin Ananyev    ngx_err_t  err;
197e18a033bSKonstantin Ananyev
198e18a033bSKonstantin Ananyev    ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
199e18a033bSKonstantin Ananyev                   "write: %d, %p, %uz, %O", file->fd, buf, size, offset);
200e18a033bSKonstantin Ananyev
201e18a033bSKonstantin Ananyev    written = 0;
202e18a033bSKonstantin Ananyev
203e18a033bSKonstantin Ananyev#if (NGX_HAVE_PWRITE)
204e18a033bSKonstantin Ananyev
205e18a033bSKonstantin Ananyev    for ( ;; ) {
206e18a033bSKonstantin Ananyev        n = pwrite(file->fd, buf + written, size, offset);
207e18a033bSKonstantin Ananyev
208e18a033bSKonstantin Ananyev        if (n == -1) {
209e18a033bSKonstantin Ananyev            err = ngx_errno;
210e18a033bSKonstantin Ananyev
211e18a033bSKonstantin Ananyev            if (err == NGX_EINTR) {
212e18a033bSKonstantin Ananyev                ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
213e18a033bSKonstantin Ananyev                               "pwrite() was interrupted");
214e18a033bSKonstantin Ananyev                continue;
215e18a033bSKonstantin Ananyev            }
216e18a033bSKonstantin Ananyev
217e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_CRIT, file->log, err,
218e18a033bSKonstantin Ananyev                          "pwrite() \"%s\" failed", file->name.data);
219e18a033bSKonstantin Ananyev            return NGX_ERROR;
220e18a033bSKonstantin Ananyev        }
221e18a033bSKonstantin Ananyev
222e18a033bSKonstantin Ananyev        file->offset += n;
223e18a033bSKonstantin Ananyev        written += n;
224e18a033bSKonstantin Ananyev
225e18a033bSKonstantin Ananyev        if ((size_t) n == size) {
226e18a033bSKonstantin Ananyev            return written;
227e18a033bSKonstantin Ananyev        }
228e18a033bSKonstantin Ananyev
229e18a033bSKonstantin Ananyev        offset += n;
230e18a033bSKonstantin Ananyev        size -= n;
231e18a033bSKonstantin Ananyev    }
232e18a033bSKonstantin Ananyev
233e18a033bSKonstantin Ananyev#else
234e18a033bSKonstantin Ananyev
235e18a033bSKonstantin Ananyev    if (file->sys_offset != offset) {
236e18a033bSKonstantin Ananyev        if (lseek(file->fd, offset, SEEK_SET) == -1) {
237e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
238e18a033bSKonstantin Ananyev                          "lseek() \"%s\" failed", file->name.data);
239e18a033bSKonstantin Ananyev            return NGX_ERROR;
240e18a033bSKonstantin Ananyev        }
241e18a033bSKonstantin Ananyev
242e18a033bSKonstantin Ananyev        file->sys_offset = offset;
243e18a033bSKonstantin Ananyev    }
244e18a033bSKonstantin Ananyev
245e18a033bSKonstantin Ananyev    for ( ;; ) {
246e18a033bSKonstantin Ananyev        n = write(file->fd, buf + written, size);
247e18a033bSKonstantin Ananyev
248e18a033bSKonstantin Ananyev        if (n == -1) {
249e18a033bSKonstantin Ananyev            err = ngx_errno;
250e18a033bSKonstantin Ananyev
251e18a033bSKonstantin Ananyev            if (err == NGX_EINTR) {
252e18a033bSKonstantin Ananyev                ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
253e18a033bSKonstantin Ananyev                               "write() was interrupted");
254e18a033bSKonstantin Ananyev                continue;
255e18a033bSKonstantin Ananyev            }
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_CRIT, file->log, err,
258e18a033bSKonstantin Ananyev                          "write() \"%s\" failed", file->name.data);
259e18a033bSKonstantin Ananyev            return NGX_ERROR;
260e18a033bSKonstantin Ananyev        }
261e18a033bSKonstantin Ananyev
262e18a033bSKonstantin Ananyev        file->sys_offset += n;
263e18a033bSKonstantin Ananyev        file->offset += n;
264e18a033bSKonstantin Ananyev        written += n;
265e18a033bSKonstantin Ananyev
266e18a033bSKonstantin Ananyev        if ((size_t) n == size) {
267e18a033bSKonstantin Ananyev            return written;
268e18a033bSKonstantin Ananyev        }
269e18a033bSKonstantin Ananyev
270e18a033bSKonstantin Ananyev        size -= n;
271e18a033bSKonstantin Ananyev    }
272e18a033bSKonstantin Ananyev#endif
273e18a033bSKonstantin Ananyev}
274e18a033bSKonstantin Ananyev
275e18a033bSKonstantin Ananyev
276e18a033bSKonstantin Ananyevngx_fd_t
277e18a033bSKonstantin Ananyevngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access)
278e18a033bSKonstantin Ananyev{
279e18a033bSKonstantin Ananyev    ngx_fd_t  fd;
280e18a033bSKonstantin Ananyev
281e18a033bSKonstantin Ananyev    fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR,
282e18a033bSKonstantin Ananyev              access ? access : 0600);
283e18a033bSKonstantin Ananyev
284e18a033bSKonstantin Ananyev    if (fd != -1 && !persistent) {
285e18a033bSKonstantin Ananyev        (void) unlink((const char *) name);
286e18a033bSKonstantin Ananyev    }
287e18a033bSKonstantin Ananyev
288e18a033bSKonstantin Ananyev    return fd;
289e18a033bSKonstantin Ananyev}
290e18a033bSKonstantin Ananyev
291e18a033bSKonstantin Ananyev
292e18a033bSKonstantin Ananyevssize_t
293e18a033bSKonstantin Ananyevngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
294e18a033bSKonstantin Ananyev    ngx_pool_t *pool)
295e18a033bSKonstantin Ananyev{
296e18a033bSKonstantin Ananyev    ssize_t        total, n;
297e18a033bSKonstantin Ananyev    ngx_iovec_t    vec;
298e18a033bSKonstantin Ananyev    struct iovec   iovs[NGX_IOVS_PREALLOCATE];
299e18a033bSKonstantin Ananyev
300e18a033bSKonstantin Ananyev    /* use pwrite() if there is the only buf in a chain */
301e18a033bSKonstantin Ananyev
302e18a033bSKonstantin Ananyev    if (cl->next == NULL) {
303e18a033bSKonstantin Ananyev        return ngx_write_file(file, cl->buf->pos,
304e18a033bSKonstantin Ananyev                              (size_t) (cl->buf->last - cl->buf->pos),
305e18a033bSKonstantin Ananyev                              offset);
306e18a033bSKonstantin Ananyev    }
307e18a033bSKonstantin Ananyev
308e18a033bSKonstantin Ananyev    total = 0;
309e18a033bSKonstantin Ananyev
310e18a033bSKonstantin Ananyev    vec.iovs = iovs;
311e18a033bSKonstantin Ananyev    vec.nalloc = NGX_IOVS_PREALLOCATE;
312e18a033bSKonstantin Ananyev
313e18a033bSKonstantin Ananyev    do {
314e18a033bSKonstantin Ananyev        /* create the iovec and coalesce the neighbouring bufs */
315e18a033bSKonstantin Ananyev        cl = ngx_chain_to_iovec(&vec, cl);
316e18a033bSKonstantin Ananyev
317e18a033bSKonstantin Ananyev        /* use pwrite() if there is the only iovec buffer */
318e18a033bSKonstantin Ananyev
319e18a033bSKonstantin Ananyev        if (vec.count == 1) {
320e18a033bSKonstantin Ananyev            n = ngx_write_file(file, (u_char *) iovs[0].iov_base,
321e18a033bSKonstantin Ananyev                               iovs[0].iov_len, offset);
322e18a033bSKonstantin Ananyev
323e18a033bSKonstantin Ananyev            if (n == NGX_ERROR) {
324e18a033bSKonstantin Ananyev                return n;
325e18a033bSKonstantin Ananyev            }
326e18a033bSKonstantin Ananyev
327e18a033bSKonstantin Ananyev            return total + n;
328e18a033bSKonstantin Ananyev        }
329e18a033bSKonstantin Ananyev
330e18a033bSKonstantin Ananyev        n = ngx_writev_file(file, &vec, offset);
331e18a033bSKonstantin Ananyev
332e18a033bSKonstantin Ananyev        if (n == NGX_ERROR) {
333e18a033bSKonstantin Ananyev            return n;
334e18a033bSKonstantin Ananyev        }
335e18a033bSKonstantin Ananyev
336e18a033bSKonstantin Ananyev        offset += n;
337e18a033bSKonstantin Ananyev        total += n;
338e18a033bSKonstantin Ananyev
339e18a033bSKonstantin Ananyev    } while (cl);
340e18a033bSKonstantin Ananyev
341e18a033bSKonstantin Ananyev    return total;
342e18a033bSKonstantin Ananyev}
343e18a033bSKonstantin Ananyev
344e18a033bSKonstantin Ananyev
345e18a033bSKonstantin Ananyevstatic ngx_chain_t *
346e18a033bSKonstantin Ananyevngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl)
347e18a033bSKonstantin Ananyev{
348e18a033bSKonstantin Ananyev    size_t         total, size;
349e18a033bSKonstantin Ananyev    u_char        *prev;
350e18a033bSKonstantin Ananyev    ngx_uint_t     n;
351e18a033bSKonstantin Ananyev    struct iovec  *iov;
352e18a033bSKonstantin Ananyev
353e18a033bSKonstantin Ananyev    iov = NULL;
354e18a033bSKonstantin Ananyev    prev = NULL;
355e18a033bSKonstantin Ananyev    total = 0;
356e18a033bSKonstantin Ananyev    n = 0;
357e18a033bSKonstantin Ananyev
358e18a033bSKonstantin Ananyev    for ( /* void */ ; cl; cl = cl->next) {
359e18a033bSKonstantin Ananyev
360e18a033bSKonstantin Ananyev        if (ngx_buf_special(cl->buf)) {
361e18a033bSKonstantin Ananyev            continue;
362e18a033bSKonstantin Ananyev        }
363e18a033bSKonstantin Ananyev
364e18a033bSKonstantin Ananyev        size = cl->buf->last - cl->buf->pos;
365e18a033bSKonstantin Ananyev
366e18a033bSKonstantin Ananyev        if (prev == cl->buf->pos) {
367e18a033bSKonstantin Ananyev            iov->iov_len += size;
368e18a033bSKonstantin Ananyev
369e18a033bSKonstantin Ananyev        } else {
370e18a033bSKonstantin Ananyev            if (n == vec->nalloc) {
371e18a033bSKonstantin Ananyev                break;
372e18a033bSKonstantin Ananyev            }
373e18a033bSKonstantin Ananyev
374e18a033bSKonstantin Ananyev            iov = &vec->iovs[n++];
375e18a033bSKonstantin Ananyev
376e18a033bSKonstantin Ananyev            iov->iov_base = (void *) cl->buf->pos;
377e18a033bSKonstantin Ananyev            iov->iov_len = size;
378e18a033bSKonstantin Ananyev        }
379e18a033bSKonstantin Ananyev
380e18a033bSKonstantin Ananyev        prev = cl->buf->pos + size;
381e18a033bSKonstantin Ananyev        total += size;
382e18a033bSKonstantin Ananyev    }
383e18a033bSKonstantin Ananyev
384e18a033bSKonstantin Ananyev    vec->count = n;
385e18a033bSKonstantin Ananyev    vec->size = total;
386e18a033bSKonstantin Ananyev
387e18a033bSKonstantin Ananyev    return cl;
388e18a033bSKonstantin Ananyev}
389e18a033bSKonstantin Ananyev
390e18a033bSKonstantin Ananyev
391e18a033bSKonstantin Ananyevstatic ssize_t
392e18a033bSKonstantin Ananyevngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec, off_t offset)
393e18a033bSKonstantin Ananyev{
394e18a033bSKonstantin Ananyev    ssize_t    n;
395e18a033bSKonstantin Ananyev    ngx_err_t  err;
396e18a033bSKonstantin Ananyev
397e18a033bSKonstantin Ananyev    ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0,
398e18a033bSKonstantin Ananyev                   "writev: %d, %uz, %O", file->fd, vec->size, offset);
399e18a033bSKonstantin Ananyev
400e18a033bSKonstantin Ananyev#if (NGX_HAVE_PWRITEV)
401e18a033bSKonstantin Ananyev
402e18a033bSKonstantin Ananyeveintr:
403e18a033bSKonstantin Ananyev
404e18a033bSKonstantin Ananyev    n = pwritev(file->fd, vec->iovs, vec->count, offset);
405e18a033bSKonstantin Ananyev
406e18a033bSKonstantin Ananyev    if (n == -1) {
407e18a033bSKonstantin Ananyev        err = ngx_errno;
408e18a033bSKonstantin Ananyev
409e18a033bSKonstantin Ananyev        if (err == NGX_EINTR) {
410e18a033bSKonstantin Ananyev            ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err,
411e18a033bSKonstantin Ananyev                           "pwritev() was interrupted");
412e18a033bSKonstantin Ananyev            goto eintr;
413e18a033bSKonstantin Ananyev        }
414e18a033bSKonstantin Ananyev
415e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_CRIT, file->log, err,
416e18a033bSKonstantin Ananyev                      "pwritev() \"%s\" failed", file->name.data);
417e18a033bSKonstantin Ananyev        return NGX_ERROR;
418e18a033bSKonstantin Ananyev    }
419e18a033bSKonstantin Ananyev
420