Mercurial > dovecot > original-hg > dovecot-1.2
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) { |