changeset 8922:5106852f552a HEAD

Added i_stream_get_size(). Use it instead of i_stream_stat() where possible.
author Timo Sirainen <tss@iki.fi>
date Tue, 24 Feb 2009 21:13:29 -0500
parents 84379691de26
children 47076db1f911
files src/lib-storage/index/mbox/mbox-sync.c src/lib/istream-internal.h src/lib/istream-limit.c src/lib/istream.c src/lib/istream.h src/plugins/quota/quota-storage.c
diffstat 6 files changed, 69 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/mbox/mbox-sync.c	Tue Feb 24 19:45:07 2009 -0500
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Tue Feb 24 21:13:29 2009 -0500
@@ -866,22 +866,24 @@
 {
 	struct mail_index_view *sync_view = sync_ctx->sync_view;
 	uint32_t seq1, seq2;
-	const struct stat *st;
+	uoff_t size;
+	int ret;
 
 	i_assert(!sync_ctx->index_reset);
 
 	if (!mail_index_lookup_seq_range(sync_view, uid, (uint32_t)-1,
 					 &seq1, &seq2)) {
 		/* doesn't exist anymore, seek to end of file */
-		st = i_stream_stat(sync_ctx->file_input, TRUE);
-		if (st == NULL) {
+		ret = i_stream_get_size(sync_ctx->file_input, TRUE, &size);
+		if (ret < 0) {
 			mbox_set_syscall_error(sync_ctx->mbox,
-					       "i_stream_stat()");
+					       "i_stream_get_size()");
 			return -1;
 		}
+		i_assert(ret != 0);
 
 		if (istream_raw_mbox_seek(sync_ctx->mbox->mbox_stream,
-					  st->st_size) < 0) {
+					  size) < 0) {
 			mbox_sync_set_critical(sync_ctx,
 				"Error seeking to end of mbox file %s",
 				sync_ctx->mbox->path);
@@ -1218,8 +1220,8 @@
 static int mbox_sync_handle_eof_updates(struct mbox_sync_context *sync_ctx,
 					struct mbox_sync_mail_context *mail_ctx)
 {
-	const struct stat *st;
 	uoff_t file_size, offset, padding, trailer_size;
+	int ret;
 
 	if (!istream_raw_mbox_is_eof(sync_ctx->input)) {
 		i_assert(sync_ctx->need_space_seq == 0);
@@ -1227,17 +1229,16 @@
 		return 0;
 	}
 
-	st = i_stream_stat(sync_ctx->file_input, TRUE);
-	if (st == NULL) {
-		mbox_set_syscall_error(sync_ctx->mbox, "i_stream_stat()");
+	ret = i_stream_get_size(sync_ctx->file_input, TRUE, &file_size);
+	if (ret < 0) {
+		mbox_set_syscall_error(sync_ctx->mbox, "i_stream_get_size()");
 		return -1;
 	}
-	if (st->st_size < 0) {
+	if (ret == 0) {
 		/* Not a file - allow anyway */
 		return 0;
 	}
 
-	file_size = st->st_size;
 	if (file_size < sync_ctx->file_input->v_offset) {
 		mbox_sync_set_critical(sync_ctx,
 			"file size unexpectedly shrank in mbox file %s "
--- a/src/lib/istream-internal.h	Tue Feb 24 19:45:07 2009 -0500
+++ b/src/lib/istream-internal.h	Tue Feb 24 21:13:29 2009 -0500
@@ -16,6 +16,7 @@
 		     uoff_t v_offset, bool mark);
 	void (*sync)(struct istream_private *stream);
 	const struct stat *(*stat)(struct istream_private *stream, bool exact);
+	int (*get_size)(struct istream_private *stream, bool exact, uoff_t *size_r);
 
 /* data: */
 	struct istream istream;
--- a/src/lib/istream-limit.c	Tue Feb 24 19:45:07 2009 -0500
+++ b/src/lib/istream-limit.c	Tue Feb 24 21:13:29 2009 -0500
@@ -112,6 +112,27 @@
 	return &stream->statbuf;
 }
 
+static int i_stream_limit_get_size(struct istream_private *stream,
+				   bool exact, uoff_t *size_r)
+{
+	struct limit_istream *lstream = (struct limit_istream *) stream;
+	const struct stat *st;
+
+	if (lstream->v_size != (uoff_t)-1) {
+		*size_r = lstream->v_size;
+		return 1;
+	}
+
+	st = i_stream_stat(&stream->istream, exact);
+	if (st == NULL)
+		return -1;
+	if (st->st_size == -1)
+		return 0;
+
+	*size_r = st->st_size;
+	return 1;
+}
+
 struct istream *i_stream_create_limit(struct istream *input, uoff_t v_size)
 {
 	struct limit_istream *lstream;
@@ -130,6 +151,7 @@
 	lstream->istream.read = i_stream_limit_read;
 	lstream->istream.seek = i_stream_limit_seek;
 	lstream->istream.stat = i_stream_limit_stat;
+	lstream->istream.get_size = i_stream_limit_get_size;
 
 	lstream->istream.istream.blocking = input->blocking;
 	lstream->istream.istream.seekable = input->seekable;
--- a/src/lib/istream.c	Tue Feb 24 19:45:07 2009 -0500
+++ b/src/lib/istream.c	Tue Feb 24 21:13:29 2009 -0500
@@ -191,6 +191,16 @@
 	return _stream->stat(_stream, exact);
 }
 
+int i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r)
+{
+	struct istream_private *_stream = stream->real_stream;
+
+	if (unlikely(stream->closed))
+		return -1;
+
+	return _stream->get_size(_stream, exact, size_r);
+}
+
 bool i_stream_have_bytes_left(const struct istream *stream)
 {
 	const struct istream_private *_stream = stream->real_stream;
@@ -429,6 +439,22 @@
 	return &stream->statbuf;
 }
 
+static int
+i_stream_default_get_size(struct istream_private *stream,
+			  bool exact, uoff_t *size_r)
+{
+	const struct stat *st;
+
+	st = stream->stat(stream, exact);
+	if (st == NULL)
+		return -1;
+	if (st->st_size == -1)
+		return 0;
+
+	*size_r = st->st_size;
+	return 1;
+}
+
 struct istream *
 i_stream_create(struct istream_private *_stream, struct istream *parent, int fd)
 {
@@ -443,6 +469,8 @@
 
 	if (_stream->stat == NULL)
 		_stream->stat = i_stream_default_stat;
+	if (_stream->get_size == NULL)
+		_stream->get_size = i_stream_default_get_size;
 	if (_stream->iostream.set_max_buffer_size == NULL) {
 		_stream->iostream.set_max_buffer_size =
 			i_stream_default_set_max_buffer_size;
--- a/src/lib/istream.h	Tue Feb 24 19:45:07 2009 -0500
+++ b/src/lib/istream.h	Tue Feb 24 21:13:29 2009 -0500
@@ -82,6 +82,9 @@
    returned values can be compared to see if anything had changed (eg. in
    compressed stream st_size could be compressed size) */
 const struct stat *i_stream_stat(struct istream *stream, bool exact);
+/* Similar to i_stream_stat() call. Returns 1 if size was successfully
+   set, 0 if size is unknown, -1 if error. */
+int i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r);
 /* Returns TRUE if there are any bytes left to be read or in buffer. */
 bool i_stream_have_bytes_left(const struct istream *stream) ATTR_PURE;
 
--- a/src/plugins/quota/quota-storage.c	Tue Feb 24 19:45:07 2009 -0500
+++ b/src/plugins/quota/quota-storage.c	Tue Feb 24 21:13:29 2009 -0500
@@ -200,11 +200,10 @@
 	struct mailbox_transaction_context *t = ctx->transaction;
 	struct quota_transaction_context *qt = QUOTA_CONTEXT(t);
 	struct quota_mailbox *qbox = QUOTA_CONTEXT(t->box);
-	const struct stat *st;
+	uoff_t size;
 	int ret;
 
-	st = i_stream_stat(input, TRUE);
-	if (st != NULL && st->st_size != -1) {
+	if (i_stream_get_size(input, TRUE, &size) > 0) {
 		/* Input size is known, check for quota immediately. This
 		   check isn't perfect, especially because input stream's
 		   linefeeds may contain CR+LFs while physical message would
@@ -216,7 +215,7 @@
 		   full mail. */
 		bool too_large;
 
-		ret = quota_test_alloc(qt, st->st_size, &too_large);
+		ret = quota_test_alloc(qt, size, &too_large);
 		if (ret == 0) {
 			mail_storage_set_error(t->box->storage,
 				MAIL_ERROR_NOSPACE,