]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-fs: Added istream-fs-file to lazily read from fs_file.
authorTimo Sirainen <tss@iki.fi>
Wed, 6 Nov 2013 19:06:15 +0000 (21:06 +0200)
committerTimo Sirainen <tss@iki.fi>
Wed, 6 Nov 2013 19:06:15 +0000 (21:06 +0200)
src/lib-fs/Makefile.am
src/lib-fs/istream-fs-file.c [new file with mode: 0644]
src/lib-fs/istream-fs-file.h [new file with mode: 0644]

index 4aef997a049c446e77b74008d868c1aeaafd5924..3e1487aec906116e66b61693e3a95d600967b30a 100644 (file)
@@ -12,6 +12,7 @@ libfs_la_SOURCES = \
        fs-sis.c \
        fs-sis-common.c \
        fs-sis-queue.c \
+       istream-fs-file.c \
        istream-metawrap.c \
        ostream-metawrap.c \
        ostream-cmp.c
@@ -20,6 +21,7 @@ headers = \
        fs-api.h \
        fs-api-private.h \
        fs-sis-common.h \
+       istream-fs-file.h \
        istream-metawrap.h \
        ostream-metawrap.h \
        ostream-cmp.h
diff --git a/src/lib-fs/istream-fs-file.c b/src/lib-fs/istream-fs-file.c
new file mode 100644 (file)
index 0000000..0b94c8a
--- /dev/null
@@ -0,0 +1,61 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "istream-private.h"
+#include "fs-api-private.h"
+#include "istream-fs-file.h"
+
+struct fs_file_istream {
+       struct istream_private istream;
+       struct fs_file *file;
+};
+
+static void i_stream_fs_file_close(struct iostream_private *stream,
+                                  bool close_parent ATTR_UNUSED)
+{
+       struct fs_file_istream *fstream = (struct fs_file_istream *)stream;
+
+       i_stream_destroy(&fstream->istream.parent);
+       fs_file_deinit(&fstream->file);
+}
+
+static ssize_t i_stream_fs_file_read(struct istream_private *stream)
+{
+       struct fs_file_istream *fstream = (struct fs_file_istream *)stream;
+       struct istream *input;
+
+       if (fstream->istream.parent == NULL) {
+               input = fs_read_stream(fstream->file,
+                                      fstream->istream.max_buffer_size);
+               i_stream_init_parent(stream, input);
+               i_stream_unref(&input);
+       }
+
+       i_stream_seek(stream->parent, stream->parent_start_offset +
+                     stream->istream.v_offset);
+       return i_stream_read_copy_from_parent(&stream->istream);
+}
+
+struct istream *
+i_stream_create_fs_file(struct fs_file **file, size_t max_buffer_size)
+{
+       struct fs_file_istream *fstream;
+       struct istream *input;
+
+       fstream = i_new(struct fs_file_istream, 1);
+       fstream->file = *file;
+       fstream->istream.iostream.close = i_stream_fs_file_close;
+       fstream->istream.max_buffer_size = max_buffer_size;
+       fstream->istream.read = i_stream_fs_file_read;
+       fstream->istream.stream_size_passthrough = TRUE;
+
+       fstream->istream.istream.blocking =
+               ((*file)->flags & FS_OPEN_FLAG_ASYNC) == 0;
+       fstream->istream.istream.seekable =
+               ((*file)->flags & FS_OPEN_FLAG_SEEKABLE) != 0;
+
+       input = i_stream_create(&fstream->istream, NULL, -1);
+       i_stream_set_name(input, fs_file_path(*file));
+       *file = NULL;
+       return input;
+}
diff --git a/src/lib-fs/istream-fs-file.h b/src/lib-fs/istream-fs-file.h
new file mode 100644 (file)
index 0000000..2821c0e
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef ISTREAM_FS_FILE_H
+#define ISTREAM_FS_FILE_H
+
+struct fs_file;
+
+/* Open the given file only when something is actually tried to be read from
+   the stream. The file is automatically deinitialized when the stream is
+   destroyed (which is why it's also set to NULL so it's not accidentally
+   double-freed). */
+struct istream *
+i_stream_create_fs_file(struct fs_file **file, size_t max_buffer_size);
+
+#endif