Mercurial > dovecot > core-2.2
changeset 3241:b79853b4b005 HEAD
Replaced i_stream_get_size() with i_stream_stat(). Added i_stream_sync().
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 29 Mar 2005 13:28:06 +0300 |
parents | a6af023db10d |
children | 9a08cf5e5f61 |
files | src/lib-mail/istream-header-filter.c src/lib/istream-data.c src/lib/istream-file.c src/lib/istream-internal.h src/lib/istream-limit.c src/lib/istream-mmap.c src/lib/istream.c src/lib/istream.h src/lib/ostream-file.c |
diffstat | 9 files changed, 144 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-mail/istream-header-filter.c Tue Mar 29 01:35:12 2005 +0300 +++ b/src/lib-mail/istream-header-filter.c Tue Mar 29 13:28:06 2005 +0300 @@ -270,6 +270,16 @@ } } +static void _sync(struct _istream *stream __attr_unused__) +{ + i_panic("istream-header-filter sync() not implemented"); +} + +static const struct stat *_stat(struct _istream *stream __attr_unused__) +{ + i_panic("istream-header-filter stat() not implemented"); +} + struct istream * i_stream_create_header_filter(struct istream *input, enum header_filter_flags flags, @@ -309,6 +319,8 @@ mstream->istream.read = _read; mstream->istream.seek = _seek; + mstream->istream.sync = _sync; + mstream->istream.stat = _stat; mstream->istream.istream.seekable = input->seekable; return _i_stream_create(&mstream->istream, pool, -1, 0);
--- a/src/lib/istream-data.c Tue Mar 29 01:35:12 2005 +0300 +++ b/src/lib/istream-data.c Tue Mar 29 13:28:06 2005 +0300 @@ -28,9 +28,10 @@ stream->istream.v_offset = v_offset; } -static uoff_t _get_size(struct _istream *stream) +static const struct stat *_stat(struct _istream *stream) { - return stream->pos; + stream->statbuf.st_size = stream->pos; + return &stream->statbuf; } struct istream *i_stream_create_from_data(pool_t pool, const void *data, @@ -48,7 +49,7 @@ stream->read = _read; stream->seek = _seek; - stream->get_size = _get_size; + stream->stat = _stat; stream->istream.seekable = TRUE; return _i_stream_create(stream, pool, -1, 0);
--- a/src/lib/istream-file.c Tue Mar 29 01:35:12 2005 +0300 +++ b/src/lib/istream-file.c Tue Mar 29 13:28:06 2005 +0300 @@ -3,6 +3,7 @@ /* @UNSAFE: whole file */ #include "lib.h" +#include "ioloop.h" #include "istream-internal.h" #include "network.h" @@ -15,6 +16,8 @@ struct file_istream { struct _istream istream; + struct timeval fstat_cache_stamp; + size_t max_buffer_size; uoff_t skip_left; @@ -173,15 +176,45 @@ stream->skip = stream->pos = 0; } -static uoff_t _get_size(struct _istream *stream) +static void _sync(struct _istream *stream) { struct file_istream *fstream = (struct file_istream *) stream; - struct stat st; + + fstream->fstat_cache_stamp.tv_sec = 0; + + if (!stream->istream.seekable) { + /* can't do anything or data would be lost */ + return; + } + + stream->skip = stream->pos = 0; +} + +static int fstat_cached(struct file_istream *fstream) +{ + if (fstream->fstat_cache_stamp.tv_sec == ioloop_timeval.tv_sec && + fstream->fstat_cache_stamp.tv_usec == ioloop_timeval.tv_usec) + return 0; - if (fstream->file && fstat(stream->fd, &st) == 0 && S_ISREG(st.st_mode)) - return (uoff_t)st.st_size; - else - return (uoff_t)-1; + if (fstat(fstream->istream.fd, &fstream->istream.statbuf) < 0) { + i_error("file_istream.fstat() failed: %m"); + return -1; + } + + fstream->fstat_cache_stamp = ioloop_timeval; + return 0; +} + +static const struct stat *_stat(struct _istream *stream) +{ + struct file_istream *fstream = (struct file_istream *) stream; + + if (fstream->file) { + if (fstat_cached(fstream) < 0) + return NULL; + } + + return &stream->statbuf; } struct istream *i_stream_create_file(int fd, pool_t pool, @@ -200,7 +233,8 @@ fstream->istream.read = _read; fstream->istream.seek = _seek; - fstream->istream.get_size = _get_size; + fstream->istream.sync = _sync; + fstream->istream.stat = _stat; /* get size of fd if it's a file */ if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
--- a/src/lib/istream-internal.h Tue Mar 29 01:35:12 2005 +0300 +++ b/src/lib/istream-internal.h Tue Mar 29 13:28:06 2005 +0300 @@ -1,6 +1,8 @@ #ifndef __ISTREAM_INTERNAL_H #define __ISTREAM_INTERNAL_H +#include <sys/stat.h> + #include "istream.h" #include "iostream-internal.h" @@ -11,7 +13,8 @@ /* methods: */ ssize_t (*read)(struct _istream *stream); void (*seek)(struct _istream *stream, uoff_t v_offset); - uoff_t (*get_size)(struct _istream *stream); + void (*sync)(struct _istream *stream); + const struct stat *(*stat)(struct _istream *stream); /* data: */ struct istream istream; @@ -22,6 +25,7 @@ string_t *line_str; /* for i_stream_next_line() if w_buffer == NULL */ size_t buffer_size; uoff_t abs_start_offset; + struct stat statbuf; size_t skip, pos; };
--- a/src/lib/istream-limit.c Tue Mar 29 01:35:12 2005 +0300 +++ b/src/lib/istream-limit.c Tue Mar 29 13:28:06 2005 +0300 @@ -89,12 +89,19 @@ stream->skip = stream->pos = 0; } -static uoff_t _get_size(struct _istream *stream) +static const struct stat *_stat(struct _istream *stream) { struct limit_istream *lstream = (struct limit_istream *) stream; + const struct stat *st; - return lstream->v_size != (uoff_t)-1 ? lstream->v_size : - i_stream_get_size(lstream->input); + st = i_stream_stat(lstream->input); + if (st == NULL) + return NULL; + + stream->statbuf = *st; + if (lstream->v_size != (uoff_t)-1) + stream->statbuf.st_size = lstream->v_size; + return &stream->statbuf; } struct istream *i_stream_create_limit(pool_t pool, struct istream *input, @@ -120,7 +127,7 @@ lstream->istream.read = _read; lstream->istream.seek = _seek; - lstream->istream.get_size = _get_size; + lstream->istream.stat = _stat; lstream->istream.istream.seekable = input->seekable; return _i_stream_create(&lstream->istream, pool, i_stream_get_fd(input),
--- a/src/lib/istream-mmap.c Tue Mar 29 01:35:12 2005 +0300 +++ b/src/lib/istream-mmap.c Tue Mar 29 13:28:06 2005 +0300 @@ -1,6 +1,7 @@ /* Copyright (c) 2002-2003 Timo Sirainen */ #include "lib.h" +#include "ioloop.h" #include "mmap-util.h" #include "istream-internal.h" @@ -10,7 +11,8 @@ struct mmap_istream { struct _istream istream; - int fd; + struct timeval fstat_cache_stamp; + void *mmap_base; off_t mmap_offset; size_t mmap_block_size; @@ -25,10 +27,10 @@ { struct mmap_istream *mstream = (struct mmap_istream *) stream; - if (mstream->autoclose_fd && mstream->fd != -1) { - if (close(mstream->fd) < 0) + if (mstream->autoclose_fd && mstream->istream.fd != -1) { + if (close(mstream->istream.fd) < 0) i_error("mmap_istream.close() failed: %m"); - mstream->fd = -1; + mstream->istream.fd = -1; } } @@ -115,7 +117,7 @@ } else { mstream->mmap_base = mmap(NULL, stream->buffer_size, PROT_READ, MAP_PRIVATE, - mstream->fd, mstream->mmap_offset); + stream->fd, mstream->mmap_offset); if (mstream->mmap_base == MAP_FAILED) { stream->istream.stream_errno = errno; mstream->mmap_base = NULL; @@ -157,11 +159,39 @@ stream->istream.v_offset = v_offset; } -static uoff_t _get_size(struct _istream *stream) +static void _sync(struct _istream *stream) { struct mmap_istream *mstream = (struct mmap_istream *) stream; - return mstream->v_size; + i_stream_munmap(mstream); + stream->skip = stream->pos = stream->istream.v_offset; + + mstream->fstat_cache_stamp.tv_sec = 0; +} + +static int fstat_cached(struct mmap_istream *mstream) +{ + if (mstream->fstat_cache_stamp.tv_sec == ioloop_timeval.tv_sec && + mstream->fstat_cache_stamp.tv_usec == ioloop_timeval.tv_usec) + return 0; + + if (fstat(mstream->istream.fd, &mstream->istream.statbuf) < 0) { + i_error("mmap_istream.fstat() failed: %m"); + return -1; + } + + mstream->fstat_cache_stamp = ioloop_timeval; + return 0; +} + +static const struct stat *_stat(struct _istream *stream) +{ + struct mmap_istream *mstream = (struct mmap_istream *) stream; + + if (fstat_cached(mstream) < 0) + return NULL; + + return &stream->statbuf; } struct istream *i_stream_create_mmap(int fd, pool_t pool, size_t block_size, @@ -187,7 +217,6 @@ } mstream = p_new(pool, struct mmap_istream, 1); - mstream->fd = fd; _set_max_buffer_size(&mstream->istream.iostream, block_size); mstream->autoclose_fd = autoclose_fd; mstream->v_size = v_size; @@ -198,7 +227,8 @@ mstream->istream.read = _read; mstream->istream.seek = _seek; - mstream->istream.get_size = _get_size; + mstream->istream.sync = _sync; + mstream->istream.stat = _stat; istream = _i_stream_create(&mstream->istream, pool, fd, start_offset); istream->mmaped = TRUE;
--- a/src/lib/istream.c Tue Mar 29 01:35:12 2005 +0300 +++ b/src/lib/istream.c Tue Mar 29 13:28:06 2005 +0300 @@ -1,6 +1,7 @@ /* Copyright (c) 2002-2003 Timo Sirainen */ #include "lib.h" +#include "ioloop.h" #include "str.h" #include "istream-internal.h" @@ -90,11 +91,19 @@ _stream->seek(_stream, v_offset); } -uoff_t i_stream_get_size(struct istream *stream) +void i_stream_sync(struct istream *stream) { struct _istream *_stream = stream->real_stream; - return _stream->get_size(_stream); + if (!stream->closed && _stream->sync != NULL) + _stream->sync(_stream); +} + +const struct stat *i_stream_stat(struct istream *stream) +{ + struct _istream *_stream = stream->real_stream; + + return _stream->stat(_stream); } int i_stream_have_bytes_left(struct istream *stream) @@ -234,6 +243,12 @@ _stream->abs_start_offset = abs_start_offset; _stream->istream.real_stream = _stream; + memset(&_stream->statbuf, 0, sizeof(_stream->statbuf)); + _stream->statbuf.st_size = -1; + _stream->statbuf.st_atime = + _stream->statbuf.st_mtime = + _stream->statbuf.st_ctime = ioloop_time; + _io_stream_init(pool, &_stream->iostream); return &_stream->istream; }
--- a/src/lib/istream.h Tue Mar 29 01:35:12 2005 +0300 +++ b/src/lib/istream.h Tue Mar 29 13:28:06 2005 +0300 @@ -35,6 +35,9 @@ /* Mark the stream closed. Any reads after this will return -1. The data already read can still be used. */ void i_stream_close(struct istream *stream); +/* Sync the stream with the underlying backend, ie. if a file has been + modified, flush any cached data. */ +void i_stream_sync(struct istream *stream); /* Change the maximum size for stream's input buffer to grow. Useful only for buffered streams (currently only file). */ @@ -49,8 +52,10 @@ /* Seek to specified position from beginning of file. Never fails, the next read tells if it was successful. This works only for files. */ void i_stream_seek(struct istream *stream, uoff_t v_offset); -/* Returns size of the stream, or (uoff_t)-1 if unknown */ -uoff_t i_stream_get_size(struct istream *stream); +/* Returns struct stat, or NULL if error. As the underlying stream may not be + a file, only some of the fields might be set, others would be zero. + st_size is always set, and if it's not known, it's -1. */ +const struct stat *i_stream_stat(struct istream *stream); /* Returns TRUE if there are any bytes left to be read or in buffer. */ int i_stream_have_bytes_left(struct istream *stream);
--- a/src/lib/ostream-file.c Tue Mar 29 01:35:12 2005 +0300 +++ b/src/lib/ostream-file.c Tue Mar 29 13:28:06 2005 +0300 @@ -636,12 +636,19 @@ static off_t _send_istream(struct _ostream *outstream, struct istream *instream) { struct file_ostream *foutstream = (struct file_ostream *)outstream; + const struct stat *st; uoff_t in_size; off_t ret; int in_fd, overlapping; + st = i_stream_stat(instream); + if (st == NULL) { + outstream->ostream.stream_errno = instream->stream_errno; + return -1; + } + in_fd = i_stream_get_fd(instream); - in_size = i_stream_get_size(instream); + in_size = st->st_size; i_assert(instream->v_offset <= in_size); outstream->ostream.stream_errno = 0;