From: Timo Sirainen Date: Thu, 15 Jul 2010 19:38:29 +0000 (+0100) Subject: Added i_stream_create_file() for creating istream from lazily opened file. X-Git-Tag: 2.0.rc3~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=09801f106cd531a28b4e03ec665e44c421264560;p=thirdparty%2Fdovecot%2Fcore.git Added i_stream_create_file() for creating istream from lazily opened file. --- diff --git a/src/lib/istream-file.c b/src/lib/istream-file.c index 6e78162ce6..ef79173393 100644 --- a/src/lib/istream-file.c +++ b/src/lib/istream-file.c @@ -9,6 +9,7 @@ #include #include +#include #include struct file_istream { @@ -35,6 +36,19 @@ static void i_stream_file_close(struct iostream_private *stream) _stream->fd = -1; } +static int i_stream_file_open(struct istream_private *stream) +{ + const char *path = i_stream_get_name(&stream->istream); + + stream->fd = open(path, O_RDONLY); + if (stream->fd == -1) { + stream->istream.stream_errno = errno; + i_error("file_istream.open(%s) failed: %m", path); + return -1; + } + return 0; +} + static ssize_t i_stream_file_read(struct istream_private *stream) { struct file_istream *fstream = (struct file_istream *) stream; @@ -44,6 +58,11 @@ static ssize_t i_stream_file_read(struct istream_private *stream) if (!i_stream_get_buffer_space(stream, 1, &size)) return -2; + if (stream->fd == -1) { + if (i_stream_file_open(stream) < 0) + return -1; + } + do { if (fstream->file) { ret = pread(stream->fd, stream->w_buffer + stream->pos, @@ -129,11 +148,18 @@ static const struct stat * i_stream_file_stat(struct istream_private *stream, bool exact ATTR_UNUSED) { struct file_istream *fstream = (struct file_istream *) stream; + const char *name = i_stream_get_name(&stream->istream); - if (fstream->file) { - if (fstat(fstream->istream.fd, &fstream->istream.statbuf) < 0) { - i_error("file_istream.fstat(%s) failed: %m", - i_stream_get_name(&stream->istream)); + if (!fstream->file) { + /* return defaults */ + } else if (stream->fd != -1) { + if (fstat(stream->fd, &stream->statbuf) < 0) { + i_error("file_istream.fstat(%s) failed: %m", name); + return NULL; + } + } else { + if (stat(name, &stream->statbuf) < 0) { + i_error("file_istream.fstat(%s) failed: %m", name); return NULL; } } @@ -141,8 +167,8 @@ i_stream_file_stat(struct istream_private *stream, bool exact ATTR_UNUSED) return &stream->statbuf; } -struct istream *i_stream_create_fd(int fd, size_t max_buffer_size, - bool autoclose_fd) +static struct istream * +i_stream_create_file_common(int fd, size_t max_buffer_size, bool autoclose_fd) { struct file_istream *fstream; struct stat st; @@ -158,7 +184,7 @@ struct istream *i_stream_create_fd(int fd, size_t max_buffer_size, fstream->istream.stat = i_stream_file_stat; /* if it's a file, set the flags properly */ - if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) { + if (fd == -1 || (fstat(fd, &st) == 0 && S_ISREG(st.st_mode))) { fstream->file = TRUE; fstream->istream.istream.blocking = TRUE; fstream->istream.istream.seekable = TRUE; @@ -167,3 +193,20 @@ struct istream *i_stream_create_fd(int fd, size_t max_buffer_size, return i_stream_create(&fstream->istream, NULL, fd); } + +struct istream *i_stream_create_fd(int fd, size_t max_buffer_size, + bool autoclose_fd) +{ + i_assert(fd != -1); + + return i_stream_create_file_common(fd, max_buffer_size, autoclose_fd); +} + +struct istream *i_stream_create_file(const char *path, size_t max_buffer_size) +{ + struct istream *input; + + input = i_stream_create_file_common(-1, max_buffer_size, TRUE); + i_stream_set_name(input, path); + return input; +} diff --git a/src/lib/istream.h b/src/lib/istream.h index 648decf33f..a15d8ed91f 100644 --- a/src/lib/istream.h +++ b/src/lib/istream.h @@ -24,6 +24,9 @@ typedef void istream_callback_t(void *context); struct istream *i_stream_create_fd(int fd, size_t max_buffer_size, bool autoclose_fd); +/* Open the given path only when something is actually tried to be read from + the stream. */ +struct istream *i_stream_create_file(const char *path, size_t max_buffer_size); struct istream *i_stream_create_mmap(int fd, size_t block_size, uoff_t start_offset, uoff_t v_size, bool autoclose_fd);