istream-file.c revision 6449bd276af37b3e0b81a9c47ecd01f39a2cba53
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen/* @UNSAFE: whole file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen void (*timeout_cb)(void *);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct _istream *_stream = (struct _istream *) stream;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (fstream->autoclose_fd && _stream->fd != -1) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct _istream *_stream = (struct _istream *) stream;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen p_free(_stream->iostream.pool, _stream->w_buffer);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic void _set_blocking(struct _iostream *stream, int timeout_msecs,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen net_set_nonblock(fstream->istream.fd, timeout_msecs == 0);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic void i_stream_grow_buffer(struct _istream *stream, size_t bytes)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->buffer_size = nearest_power(stream->buffer_size);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen stream->buffer_size > fstream->max_buffer_size)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen stream->buffer_size = fstream->max_buffer_size;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen p_realloc(stream->iostream.pool, stream->w_buffer,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic void i_stream_compress(struct _istream *stream)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen memmove(stream->w_buffer, stream->w_buffer + stream->skip,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* remove the unused bytes from beginning of buffer */
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen stream->buffer_size < fstream->max_buffer_size) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* buffer is full - grow it */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen i_assert(stream->istream.v_limit >= stream->istream.v_offset);
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen stream->istream.v_offset + fstream->skip_left;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (read_limit <= stream->pos - stream->skip) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* virtual limit reached == EOF */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (ret == 0 && timeout_time > 0 && time(NULL) > timeout_time) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* timeouted */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen fstream->timeout_cb(fstream->timeout_context);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (errno == ECONNRESET || errno == ETIMEDOUT) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* treat as disconnection */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen } while (ret == 0 && STREAM_IS_BLOCKING(fstream));
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic void _skip(struct _istream *stream, uoff_t count)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic void _seek(struct _istream *stream, uoff_t v_offset)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct istream *i_stream_create_file(int fd, pool_t pool,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream = p_new(pool, struct file_istream, 1);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->istream.iostream.set_blocking = _set_blocking;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* get size of fd if it's a file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode))
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return _i_stream_create(&fstream->istream, pool, fd, 0, 0);