aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-stream-fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-stream-fs.c')
-rw-r--r--camel/camel-stream-fs.c464
1 files changed, 164 insertions, 300 deletions
diff --git a/camel/camel-stream-fs.c b/camel/camel-stream-fs.c
index fa5766de48..ae46141e19 100644
--- a/camel/camel-stream-fs.c
+++ b/camel/camel-stream-fs.c
@@ -1,11 +1,9 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-stream-fs.c : file system based stream */
-
/* inspired by gnome-stream-fs.c in bonobo by Miguel de Icaza */
/*
- *
- * Author :
- * Bertrand Guiheneuf <bertrand@helixcode.com>
+ * Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
+ * Michael Zucchi <notzed@helixcode.com>
*
* Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com)
*
@@ -35,26 +33,22 @@
static CamelSeekableStreamClass *parent_class=NULL;
-
/* Returns the class for a CamelStreamFS */
#define CSFS_CLASS(so) CAMEL_STREAM_FS_CLASS (GTK_OBJECT(so)->klass)
-static gint _read (CamelStream *stream, gchar *buffer, gint n);
-static gint _write (CamelStream *stream, const gchar *buffer, gint n);
-static void _flush (CamelStream *stream);
-static gboolean _available (CamelStream *stream);
-static gboolean _eos (CamelStream *stream);
-static void _close (CamelStream *stream);
-static gint _seek (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy);
+static gint stream_read (CamelStream *stream, gchar *buffer, gint n);
+static gint stream_write (CamelStream *stream, const gchar *buffer, gint n);
+static void stream_flush (CamelStream *stream);
+static void stream_close (CamelStream *stream);
+static off_t stream_seek (CamelSeekableStream *stream, off_t offset, CamelStreamSeekPolicy policy);
-static void _finalize (GtkObject *object);
-static void _destroy (GtkObject *object);
+static void finalize (GtkObject *object);
-static void _init_with_fd (CamelStreamFs *stream_fs, int fd);
-static void _init_with_fd_and_bounds (CamelStreamFs *stream_fs, int fd, guint32 inf_bound, gint32 sup_bound);
-static void _init_with_name (CamelStreamFs *stream_fs, const gchar *name, CamelStreamFsMode mode);
-static void _init_with_name_and_bounds (CamelStreamFs *stream_fs, const gchar *name, CamelStreamFsMode mode,
- guint32 inf_bound, gint32 sup_bound);
+static void init_with_fd (CamelStreamFs *stream_fs, int fd);
+static void init_with_fd_and_bounds (CamelStreamFs *stream_fs, int fd, off_t start, off_t end);
+static int init_with_name (CamelStreamFs *stream_fs, const gchar *name, int flags, int mode);
+static int init_with_name_and_bounds (CamelStreamFs *stream_fs, const gchar *name, int flags, int mode,
+ off_t start, off_t end);
static void
camel_stream_fs_class_init (CamelStreamFsClass *camel_stream_fs_class)
@@ -66,24 +60,20 @@ camel_stream_fs_class_init (CamelStreamFsClass *camel_stream_fs_class)
parent_class = gtk_type_class (camel_seekable_stream_get_type ());
/* virtual method definition */
- camel_stream_fs_class->init_with_fd = _init_with_fd;
- camel_stream_fs_class->init_with_fd_and_bounds = _init_with_fd_and_bounds;
- camel_stream_fs_class->init_with_name = _init_with_name;
- camel_stream_fs_class->init_with_name_and_bounds = _init_with_name_and_bounds;
+ camel_stream_fs_class->init_with_fd = init_with_fd;
+ camel_stream_fs_class->init_with_fd_and_bounds = init_with_fd_and_bounds;
+ camel_stream_fs_class->init_with_name = init_with_name;
+ camel_stream_fs_class->init_with_name_and_bounds = init_with_name_and_bounds;
/* virtual method overload */
- camel_stream_class->read = _read;
- camel_stream_class->write = _write;
- camel_stream_class->flush = _flush;
- camel_stream_class->available = _available;
- camel_stream_class->eos = _eos;
- camel_stream_class->close = _close;
+ camel_stream_class->read = stream_read;
+ camel_stream_class->write = stream_write;
+ camel_stream_class->flush = stream_flush;
+ camel_stream_class->close = stream_close;
- camel_seekable_stream_class->seek = _seek;
-
- gtk_object_class->finalize = _finalize;
- gtk_object_class->destroy = _destroy;
+ camel_seekable_stream_class->seek = stream_seek;
+ gtk_object_class->finalize = finalize;
}
static void
@@ -92,10 +82,9 @@ camel_stream_fs_init (gpointer object, gpointer klass)
CamelStreamFs *stream = CAMEL_STREAM_FS (object);
stream->name = NULL;
- stream->eof = FALSE;
+ stream->fd = -1;
}
-
GtkType
camel_stream_fs_get_type (void)
{
@@ -120,164 +109,124 @@ camel_stream_fs_get_type (void)
return camel_stream_fs_type;
}
-
static void
-_destroy (GtkObject *object)
-{
- CamelStreamFs *stream_fs = CAMEL_STREAM_FS (object);
- gint close_error;
-
- close_error = close (stream_fs->fd);
- if (close_error) {
- g_warning ("CamelStreamFs::destroy Error while closing "
- "file descriptor\n Full error text is : %s\n",
- strerror (errno));
- }
- GTK_OBJECT_CLASS (parent_class)->destroy (object);
-}
-
-
-static void
-_finalize (GtkObject *object)
+finalize (GtkObject *object)
{
CamelStreamFs *stream_fs = CAMEL_STREAM_FS (object);
+ if (stream_fs->fd != -1) {
+ if (close (stream_fs->fd) == -1)
+ g_warning ("CamelStreamFs::finalise: Error closing file: %s", strerror (errno));
+ }
g_free (stream_fs->name);
GTK_OBJECT_CLASS (parent_class)->finalize (object);
}
-
-
-static void
-_set_bounds (CamelStreamFs *stream_fs, guint32 inf_bound, guint32 sup_bound)
-{
-
- /* store the bounds */
- stream_fs->inf_bound = inf_bound;
- stream_fs->sup_bound = sup_bound;
-
- /* go to the first position */
- lseek (stream_fs->fd, inf_bound, SEEK_SET);
-
- CAMEL_SEEKABLE_STREAM (stream_fs)->cur_pos = 0;
-}
-
-
-
-
static void
-_init_with_fd (CamelStreamFs *stream_fs, int fd)
+init_with_fd (CamelStreamFs *stream_fs, int fd)
{
+ off_t offset;
+
stream_fs->fd = fd;
- stream_fs->inf_bound = 0;
- stream_fs->sup_bound = -1;
- CAMEL_SEEKABLE_STREAM (stream_fs)->cur_pos = 0;
+ offset = lseek(fd, 0, SEEK_CUR);
+ if (offset == -1)
+ offset = 0;
+ ((CamelSeekableStream *)stream_fs)->position = offset;
}
-
-
-
static void
-_init_with_fd_and_bounds (CamelStreamFs *stream_fs, int fd, guint32 inf_bound, gint32 sup_bound)
+init_with_fd_and_bounds (CamelStreamFs *stream_fs, int fd, off_t start, off_t end)
{
CSFS_CLASS (stream_fs)->init_with_fd (stream_fs, fd);
- _set_bounds (stream_fs, inf_bound, sup_bound);
-
+ camel_seekable_stream_set_bounds((CamelSeekableStream *)stream_fs, start, end);
}
-
-
-static void
-_init_with_name (CamelStreamFs *stream_fs, const gchar *name, CamelStreamFsMode mode)
+static int
+init_with_name (CamelStreamFs *stream_fs, const gchar *name, int flags, int mode)
{
- struct stat s;
- int v, fd;
- int flags;
+ int fd;
- g_assert (name);
-
- v = stat (name, &s);
-
- if (mode & CAMEL_STREAM_FS_READ){
- if (mode & CAMEL_STREAM_FS_WRITE)
- flags = O_RDWR | O_CREAT | O_NONBLOCK;
- else
- flags = O_RDONLY | O_NONBLOCK;
- } else {
- if (mode & CAMEL_STREAM_FS_WRITE)
- flags = O_WRONLY | O_CREAT | O_NONBLOCK;
- else
- return;
- }
-
- if ( (mode & CAMEL_STREAM_FS_READ) && !(mode & CAMEL_STREAM_FS_WRITE) )
- if (v == -1) {
- stream_fs->fd = -1;
- return;
- }
+ g_assert(name);
+ g_assert(stream_fs);
-
- fd = open (name, flags, 0600);
+ fd = open (name, flags, mode);
if (fd==-1) {
- g_warning ("CamelStreamFs::new_with_name can not obtain "
- "fd for file \"%s\"\n", name);
- return;
+ g_warning ("CamelStreamFs::new_with_name cannot open file: %s: %s", name, strerror(errno));
+ return -1;
}
stream_fs->name = g_strdup (name);
CSFS_CLASS (stream_fs)->init_with_fd (stream_fs, fd);
-
- gtk_signal_emit_by_name (GTK_OBJECT (stream_fs), "data_available");
-
+ return 0;
}
-
-
-static void
-_init_with_name_and_bounds (CamelStreamFs *stream_fs, const gchar *name, CamelStreamFsMode mode,
- guint32 inf_bound, gint32 sup_bound)
+static int
+init_with_name_and_bounds (CamelStreamFs *stream_fs, const gchar *name, int flags, int mode,
+ off_t start, off_t end)
{
- CSFS_CLASS (stream_fs)->init_with_name (stream_fs, name, mode);
- _set_bounds (stream_fs, inf_bound, (gint32)sup_bound);
+ if (CSFS_CLASS (stream_fs)->init_with_name (stream_fs, name, flags, mode) == -1)
+ return -1;
+ camel_seekable_stream_set_bounds((CamelSeekableStream *)stream_fs, start, end);
+ return 0;
}
-
-
-
+/**
+ * camel_stream_fs_new_with_name:
+ * @name:
+ * @mode:
+ *
+ *
+ *
+ * Return value:
+ **/
CamelStream *
-camel_stream_fs_new_with_name (const gchar *name, CamelStreamFsMode mode)
+camel_stream_fs_new_with_name (const gchar *name, int flags, int mode)
{
CamelStreamFs *stream_fs;
stream_fs = gtk_type_new (camel_stream_fs_get_type ());
- CSFS_CLASS (stream_fs)->init_with_name (stream_fs, name, mode);
- if (stream_fs->fd == -1) {
- gtk_object_destroy (GTK_OBJECT (stream_fs));
+ if (CSFS_CLASS (stream_fs)->init_with_name (stream_fs, name, flags, mode) == -1) {
+ gtk_object_unref (GTK_OBJECT (stream_fs));
return NULL;
}
-
- return CAMEL_STREAM (stream_fs);
+
+ return (CamelStream *)stream_fs;
}
-
+/**
+ * camel_stream_fs_new_with_name_and_bounds:
+ * @name:
+ * @mode:
+ * @inf_bound:
+ * @sup_bound:
+ *
+ *
+ *
+ * Return value:
+ **/
CamelStream *
-camel_stream_fs_new_with_name_and_bounds (const gchar *name, CamelStreamFsMode mode,
- guint32 inf_bound, gint32 sup_bound)
+camel_stream_fs_new_with_name_and_bounds (const gchar *name, int flags, int mode,
+ off_t start, off_t end)
{
CamelStreamFs *stream_fs;
stream_fs = gtk_type_new (camel_stream_fs_get_type ());
- CSFS_CLASS (stream_fs)->init_with_name_and_bounds (stream_fs, name, mode, inf_bound, sup_bound);
-
- return CAMEL_STREAM (stream_fs);
+ if (CSFS_CLASS (stream_fs)->init_with_name_and_bounds (stream_fs, name, flags, mode, start, end) == -1) {
+ gtk_object_unref (GTK_OBJECT (stream_fs));
+ return NULL;
+ }
+ return (CamelStream *)stream_fs;
}
-
-
-
-
-
+/**
+ * camel_stream_fs_new_with_fd:
+ * @fd:
+ *
+ *
+ *
+ * Return value:
+ **/
CamelStream *
camel_stream_fs_new_with_fd (int fd)
{
@@ -289,225 +238,140 @@ camel_stream_fs_new_with_fd (int fd)
return CAMEL_STREAM (stream_fs);
}
-
-
+/**
+ * camel_stream_fs_new_with_fd_and_bounds:
+ * @fd:
+ * @inf_bound:
+ * @sup_bound:
+ *
+ *
+ *
+ * Return value:
+ **/
CamelStream *
-camel_stream_fs_new_with_fd_and_bounds (int fd, guint32 inf_bound, gint32 sup_bound)
+camel_stream_fs_new_with_fd_and_bounds (int fd, off_t start, off_t end)
{
CamelStreamFs *stream_fs;
stream_fs = gtk_type_new (camel_stream_fs_get_type ());
- CSFS_CLASS (stream_fs)->init_with_fd_and_bounds (stream_fs, fd, inf_bound, sup_bound);
+ CSFS_CLASS (stream_fs)->init_with_fd_and_bounds (stream_fs, fd, start, end);
return CAMEL_STREAM (stream_fs);
}
-
-
-/**
- * _read: read bytes from a stream
- * @stream: stream
- * @buffer: buffer where bytes are stored
- * @n: max number of bytes to read
- *
- *
- *
- * Return value: number of bytes actually read.
- **/
static gint
-_read (CamelStream *stream, gchar *buffer, gint n)
+stream_read (CamelStream *stream, gchar *buffer, gint n)
{
CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream);
- gint v = 0;
- gint nb_to_read;
-
+ CamelSeekableStream *seekable = (CamelSeekableStream *)stream;
+ gint v;
+
g_assert (n);
-
- if (stream_fs->sup_bound != -1)
- nb_to_read = MIN (stream_fs->sup_bound - CAMEL_SEEKABLE_STREAM (stream)->cur_pos - stream_fs->inf_bound , n);
- else
- nb_to_read = n;
-
+
+ if (seekable->bound_end != CAMEL_STREAM_UNBOUND)
+ n = MIN (seekable->bound_end - seekable->position, n);
+
do {
- v = read ( (CAMEL_STREAM_FS (stream))->fd, buffer, nb_to_read);
+ v = read ( stream_fs->fd, buffer, n);
} while (v == -1 && errno == EINTR);
if (v>0)
- CAMEL_SEEKABLE_STREAM (stream)->cur_pos += v;
+ seekable->position += v;
if (v == 0)
- stream_fs->eof = TRUE;
+ stream->eos = TRUE;
return v;
}
-
-/**
- * _write: write bytes to a stream
- * @stream: the stream
- * @buffer: byte buffer
- * @n: number of bytes to write
- *
- *
- *
- * Return value: the number of bytes actually written
- * in the stream.
- **/
static gint
-_write (CamelStream *stream, const gchar *buffer, gint n)
+stream_write (CamelStream *stream, const gchar *buffer, gint n)
{
CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream);
+ CamelSeekableStream *seekable = (CamelSeekableStream *)stream;
int v;
- gint nb_bytes_written = 0;
+ gint written = 0;
+
+ g_assert (stream);
+ g_assert (stream_fs->fd != -1);
if (n <= 0)
return 0;
- g_assert (stream);
- g_assert (stream_fs->fd);
+ if (seekable->bound_end != CAMEL_STREAM_UNBOUND)
+ n = MIN (seekable->bound_end - seekable->position, n);
- /* we do not take the end bounds into account as it does not
- really make any sense in the case of a write operation */
do {
v = write ( stream_fs->fd, buffer, n);
- if (v>0) nb_bytes_written += v;
+ if (v>0)
+ written += v;
} while (v == -1 && errno == EINTR);
- if (nb_bytes_written>0)
- CAMEL_SEEKABLE_STREAM (stream)->cur_pos += nb_bytes_written;
-
- return nb_bytes_written;
+ if (written>0)
+ seekable->position += written;
+ return written;
}
-
-
-/**
- * _flush: flush pending changes
- * @stream: the stream
- *
- *
- **/
static void
-_flush (CamelStream *stream)
+stream_flush (CamelStream *stream)
{
fsync ((CAMEL_STREAM_FS (stream))->fd);
}
-
-
-/**
- * _available: return the number of bytes available for reading
- * @stream: the stream
- *
- * Return the number of bytes available without blocking.
- *
- * Return value: the number of bytes available
- **/
-static gboolean
-_available (CamelStream *stream)
-{
- g_warning ("Not implemented yet");
- return FALSE;
-}
-
-
-/**
- * _eos: test if there are bytes left to read
- * @stream: the stream
- *
- *
- *
- * Return value: true if all stream has been read
- **/
-static gboolean
-_eos (CamelStream *stream)
-{
- CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream);
-
- g_assert (stream_fs);
- return stream_fs->eof;
-}
-
-
-/**
- * _close: close a stream
- * @stream: the stream
- *
- *
- **/
static void
-_close (CamelStream *stream)
+stream_close (CamelStream *stream)
{
- close ((CAMEL_STREAM_FS (stream))->fd);
+ CamelStreamFs *fs = (CamelStreamFs *)stream;
+ if (fs->fd != -1) {
+ close (fs->fd);
+ fs->fd = -1;
+ } else {
+ g_warning("StreamFs::close() on a closed or failed stream");
+ }
}
-
-static gint
-_seek (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy)
+static off_t
+stream_seek (CamelSeekableStream *stream, off_t offset, CamelStreamSeekPolicy policy)
{
- int whence;
- gint return_position;
- gint real_offset;
CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream);
-
+ off_t real = 0;
switch (policy) {
case CAMEL_STREAM_SET:
- real_offset = MAX (stream_fs->inf_bound + offset, stream_fs->inf_bound);
- if (stream_fs->sup_bound > 0)
- real_offset = MIN (real_offset, stream_fs->sup_bound);
- whence = SEEK_SET;
+ real = offset;
break;
-
case CAMEL_STREAM_CUR:
- if ((stream_fs->sup_bound != -1) && ((CAMEL_SEEKABLE_STREAM (stream)->cur_pos + stream_fs->inf_bound + offset) > stream_fs->sup_bound)) {
- real_offset = stream_fs->sup_bound;
- whence = SEEK_SET;
- } else if ((CAMEL_SEEKABLE_STREAM (stream)->cur_pos + stream_fs->inf_bound + offset) < stream_fs->inf_bound) {
- real_offset = stream_fs->inf_bound;
- whence = SEEK_SET;
- } else
- {
- real_offset = offset;
- whence = SEEK_CUR;
- }
+ real = stream->position + offset;
break;
-
case CAMEL_STREAM_END:
- if (stream_fs->sup_bound != -1) {
- real_offset = stream_fs->sup_bound - offset;
- whence = SEEK_SET;
- } else {
- real_offset = offset;
- whence = SEEK_END;
+ if (stream->bound_end != CAMEL_STREAM_UNBOUND) {
+ real = lseek(stream_fs->fd, offset, SEEK_END);
+ if (real != -1)
+ stream->position = real;
+ return real;
}
-
-
+ real = stream->bound_end + offset;
break;
default:
+ errno = EINVAL;
return -1;
}
-
-
-
- return_position = lseek (stream_fs->fd, real_offset, whence) - stream_fs->inf_bound;
- if (((CAMEL_SEEKABLE_STREAM (stream)->cur_pos) != return_position) && stream_fs->eof)
- stream_fs->eof = FALSE;
-
- CAMEL_SEEKABLE_STREAM (stream)->cur_pos = return_position;
-
-
- return return_position;
-}
-
-
-
-
-
-
+ if (stream->bound_end != CAMEL_STREAM_UNBOUND) {
+ real = MIN (real, stream->bound_end);
+ }
+ real = MAX (real, stream->bound_start);
+ real = lseek(stream_fs->fd, real, SEEK_SET);
+ if (real == -1)
+ return -1;
+ if (real != stream->position && ((CamelStream *)stream)->eos)
+ ((CamelStream *)stream)->eos = FALSE;
+ stream->position = real;
+
+ return real;
+}