comparison src/lib/iobuffer.c @ 363:567e932cdc66 HEAD

Added autoclose_fd-flag for io_buffer_create_file() and io_buffer_create_mmap().
author Timo Sirainen <tss@iki.fi>
date Sun, 06 Oct 2002 06:09:36 +0300
parents 2c6b6594a14b
children ea958a5b9de1
comparison
equal deleted inserted replaced
362:aa449d013563 363:567e932cdc66
63 buf->priority = priority; 63 buf->priority = priority;
64 buf->max_buffer_size = max_buffer_size; 64 buf->max_buffer_size = max_buffer_size;
65 return buf; 65 return buf;
66 } 66 }
67 67
68 IOBuffer *io_buffer_create_file(int fd, Pool pool, size_t max_buffer_size) 68 IOBuffer *io_buffer_create_file(int fd, Pool pool, size_t max_buffer_size,
69 int autoclose_fd)
69 { 70 {
70 IOBuffer *buf; 71 IOBuffer *buf;
71 72
72 buf = io_buffer_create(fd, pool, IO_PRIORITY_DEFAULT, max_buffer_size); 73 buf = io_buffer_create(fd, pool, IO_PRIORITY_DEFAULT, max_buffer_size);
73 buf->file = TRUE; 74 buf->file = TRUE;
75 buf->close_file = autoclose_fd;
74 return buf; 76 return buf;
75 } 77 }
76 78
77 IOBuffer *io_buffer_create_mmap(int fd, Pool pool, size_t block_size, 79 IOBuffer *io_buffer_create_mmap(int fd, Pool pool, size_t block_size,
78 uoff_t size) 80 uoff_t size, int autoclose_fd)
79 { 81 {
80 IOBuffer *buf; 82 IOBuffer *buf;
81 off_t start_offset, stop_offset; 83 off_t start_offset, stop_offset;
82 84
83 /* block size must be page aligned, and at least two pages long */ 85 /* block size must be page aligned, and at least two pages long */
91 else if ((block_size & mmap_pagemask) != 0) { 93 else if ((block_size & mmap_pagemask) != 0) {
92 block_size &= ~mmap_pagemask; 94 block_size &= ~mmap_pagemask;
93 block_size += mmap_pagesize; 95 block_size += mmap_pagesize;
94 } 96 }
95 97
96 buf = io_buffer_create_file(fd, pool, block_size); 98 buf = io_buffer_create_file(fd, pool, block_size, autoclose_fd);
97 buf->mmaped = TRUE; 99 buf->mmaped = TRUE;
98 buf->receive = TRUE; 100 buf->receive = TRUE;
99 101
100 /* set offsets */ 102 /* set offsets */
101 start_offset = lseek(fd, 0, SEEK_CUR); 103 start_offset = lseek(fd, 0, SEEK_CUR);
139 i_error("io_buffer_destroy(): " 141 i_error("io_buffer_destroy(): "
140 "munmap() failed: %m"); 142 "munmap() failed: %m");
141 } 143 }
142 } 144 }
143 } 145 }
146 io_buffer_close(buf);
144 p_free(buf->pool, buf); 147 p_free(buf->pool, buf);
145 } 148 }
146 149
147 void io_buffer_close(IOBuffer *buf) 150 void io_buffer_close(IOBuffer *buf)
148 { 151 {
149 if (buf == NULL) 152 if (buf == NULL)
150 return; 153 return;
151 154
152 buf->closed = TRUE; 155 buf->closed = TRUE;
156 if (buf->close_file && buf->fd != -1) {
157 if (close(buf->fd) < 0)
158 i_error("io_buffer_close(): close() failed: %m");
159 buf->fd = -1;
160 }
153 } 161 }
154 162
155 void io_buffer_reset(IOBuffer *buf) 163 void io_buffer_reset(IOBuffer *buf)
156 { 164 {
157 buf->pos = buf->skip = buf->cr_lookup_pos = 0; 165 buf->pos = buf->skip = buf->cr_lookup_pos = 0;
242 ret = my_write(buf->fd, buf->buffer + buf->skip, 250 ret = my_write(buf->fd, buf->buffer + buf->skip,
243 buf->pos - buf->skip); 251 buf->pos - buf->skip);
244 } 252 }
245 253
246 if (ret < 0) { 254 if (ret < 0) {
247 buf->closed = TRUE;
248 buf->buf_errno = errno; 255 buf->buf_errno = errno;
256 io_buffer_close(buf);
249 } else { 257 } else {
250 buf->offset += ret; 258 buf->offset += ret;
251 buf->skip += ret; 259 buf->skip += ret;
252 if (buf->skip == buf->pos) { 260 if (buf->skip == buf->pos) {
253 /* everything sent */ 261 /* everything sent */
295 ret = !ctx->outbuf->file ? 303 ret = !ctx->outbuf->file ?
296 net_transmit(ctx->outbuf->fd, ctx->data, size) : 304 net_transmit(ctx->outbuf->fd, ctx->data, size) :
297 my_write(ctx->outbuf->fd, ctx->data, size); 305 my_write(ctx->outbuf->fd, ctx->data, size);
298 306
299 if (ret < 0) { 307 if (ret < 0) {
300 ctx->outbuf->closed = TRUE;
301 ctx->outbuf->buf_errno = errno; 308 ctx->outbuf->buf_errno = errno;
309 io_buffer_close(ctx->outbuf);
302 } else { 310 } else {
303 ctx->outbuf->offset += ret; 311 ctx->outbuf->offset += ret;
304 ctx->data += ret; 312 ctx->data += ret;
305 ctx->size -= ret; 313 ctx->size -= ret;
306 } 314 }
442 /* buffer is empty, try to send the data immediately */ 450 /* buffer is empty, try to send the data immediately */
443 ret = buf->file ? my_write(buf->fd, data, size) : 451 ret = buf->file ? my_write(buf->fd, data, size) :
444 net_transmit(buf->fd, data, size); 452 net_transmit(buf->fd, data, size);
445 if (ret < 0) { 453 if (ret < 0) {
446 /* disconnected */ 454 /* disconnected */
447 buf->closed = TRUE;
448 buf->buf_errno = errno; 455 buf->buf_errno = errno;
456 io_buffer_close(buf);
449 return -1; 457 return -1;
450 } 458 }
451 459
452 buf->offset += ret; 460 buf->offset += ret;
453 data = (const char *) data + ret; 461 data = (const char *) data + ret;
497 ret = safe_sendfile(ctx->outbuf->fd, ctx->inbuf->fd, &offset, 505 ret = safe_sendfile(ctx->outbuf->fd, ctx->inbuf->fd, &offset,
498 MAX_SSIZE_T(ctx->size)); 506 MAX_SSIZE_T(ctx->size));
499 if (ret < 0) { 507 if (ret < 0) {
500 if (errno != EINTR && errno != EAGAIN) { 508 if (errno != EINTR && errno != EAGAIN) {
501 ctx->outbuf->buf_errno = errno; 509 ctx->outbuf->buf_errno = errno;
502 ctx->outbuf->closed = TRUE; 510 io_buffer_close(ctx->outbuf);
503 } 511 }
504 ret = 0; 512 ret = 0;
505 } 513 }
506 514
507 io_buffer_skip(ctx->inbuf, (size_t)ret); 515 io_buffer_skip(ctx->inbuf, (size_t)ret);
588 IOBufferBlockContext ctx; 596 IOBufferBlockContext ctx;
589 int ret; 597 int ret;
590 598
591 i_assert(size < OFF_T_MAX); 599 i_assert(size < OFF_T_MAX);
592 i_assert(inbuf->limit > 0 || size <= inbuf->limit - inbuf->offset); 600 i_assert(inbuf->limit > 0 || size <= inbuf->limit - inbuf->offset);
601
602 if (inbuf->closed || outbuf->closed)
603 return -1;
593 604
594 ret = io_buffer_sendfile(outbuf, inbuf, size); 605 ret = io_buffer_sendfile(outbuf, inbuf, size);
595 if (ret > 0 || outbuf->buf_errno != EINVAL) 606 if (ret > 0 || outbuf->buf_errno != EINVAL)
596 return ret < 0 ? -1 : 1; 607 return ret < 0 ? -1 : 1;
597 608
855 866
856 int io_buffer_seek(IOBuffer *buf, uoff_t offset) 867 int io_buffer_seek(IOBuffer *buf, uoff_t offset)
857 { 868 {
858 uoff_t real_offset; 869 uoff_t real_offset;
859 870
871 if (buf->closed)
872 return FALSE;
873
860 real_offset = buf->start_offset + offset; 874 real_offset = buf->start_offset + offset;
861 if (real_offset > OFF_T_MAX) { 875 if (real_offset > OFF_T_MAX) {
862 errno = EINVAL; 876 errno = EINVAL;
863 return FALSE; 877 return FALSE;
864 } 878 }
990 ssize_t ret; 1004 ssize_t ret;
991 1005
992 i_assert(size <= SSIZE_T_MAX); 1006 i_assert(size <= SSIZE_T_MAX);
993 i_assert(!buf->receive); 1007 i_assert(!buf->receive);
994 1008
1009 if (buf->closed)
1010 return -1;
1011
995 if (buf->pos == 0 && !buf->corked) { 1012 if (buf->pos == 0 && !buf->corked) {
996 /* buffer is empty, try to send the data immediately */ 1013 /* buffer is empty, try to send the data immediately */
997 ret = buf->file ? my_write(buf->fd, buf->buffer, size) : 1014 ret = buf->file ? my_write(buf->fd, buf->buffer, size) :
998 net_transmit(buf->fd, buf->buffer, size); 1015 net_transmit(buf->fd, buf->buffer, size);
999 if (ret < 0) { 1016 if (ret < 0) {
1000 /* disconnected */ 1017 /* disconnected */
1001 buf->closed = TRUE;
1002 buf->buf_errno = errno; 1018 buf->buf_errno = errno;
1019 io_buffer_close(buf);
1003 return -1; 1020 return -1;
1004 } 1021 }
1005 1022
1006 buf->offset += ret; 1023 buf->offset += ret;
1007 if ((size_t)ret == size) { 1024 if ((size_t)ret == size) {