diff src/lib/istream-file.c @ 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 904a268921af
children e05a1af4bbc7
line wrap: on
line diff
--- 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)) {