From 65ec43cb553420890c8d14b6c76ce2606674d893 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 8 May 2000 22:27:59 +0000 Subject: Use CamelException to signal failure. (camel_stream_write_strings): * camel-stream.c (camel_stream_read, camel_stream_write, camel_stream_flush, camel_stream_reset, camel_stream_printf, camel_stream_write_to_stream): Use CamelException to signal failure. (camel_stream_write_strings): Remove. camel_stream_printf is more useful in most of the places that used this. (camel_stream_write_string): Change from macro to function to prevent problems with double-evaluation. * camel-seekable-stream.c (camel_seekable_stream_seek, camel_seekable_stream_set_bounds): Use CamelException. (reset): Update. * camel-seekable-substream.c, camel-stream-buffer.c, camel-stream-filter.c, camel-stream-fs.c, camel-stream-mem.c: Update. * camel-stream-fs.c: Remove the virtual init functions and move the code into the creator functions. Add CamelExceptions to creation functions that could fail. * camel-data-wrapper.c (camel_data_wrapper_write_to_stream): Use CamelException. * camel-mime-message.c, camel-mime-part.c, camel-multipart.c (write_to_stream): Update. * camel-mime-parser.c: add an exception to the mime parser private data and pass that to stream functions as needed. * gmime-content-field.c, md5-utils.c: Update (badly) for stream changes. * camel-exception.h (camel_exception_is_set): convenience macro. * providers/Makefile.am: disable SMTP for now * providers/mbox/camel-mbox-folder.c (mbox_append_message): Pass CamelException to the functions that now need it. Check the exception after calling camel_stream_flush, and fail if it fails. (mbox_get_message_by_uid): More updates. * providers/pop/camel-pop3-folder.c, providers/pop/camel-pop3-store.c, providers/sendmail/camel-sendmail/transport.c: Update. svn path=/trunk/; revision=2924 --- camel/ChangeLog | 48 +++ camel/camel-data-wrapper.c | 27 +- camel/camel-data-wrapper.h | 6 +- camel/camel-exception.c | 6 +- camel/camel-exception.h | 2 +- camel/camel-mime-message.c | 10 +- camel/camel-mime-parser.c | 26 +- camel/camel-mime-part.c | 28 +- camel/camel-multipart.c | 44 +-- camel/camel-seekable-stream.c | 115 +++---- camel/camel-seekable-stream.h | 33 +- camel/camel-seekable-substream.c | 157 +++++----- camel/camel-seekable-substream.h | 11 +- camel/camel-stream-buffer.c | 127 ++++---- camel/camel-stream-buffer.h | 40 +-- camel/camel-stream-filter.c | 53 ++-- camel/camel-stream-fs.c | 344 ++++++++++----------- camel/camel-stream-fs.h | 48 ++- camel/camel-stream-mem.c | 141 +++++---- camel/camel-stream-mem.h | 16 +- camel/camel-stream.c | 270 ++++++++-------- camel/camel-stream.h | 68 ++-- camel/gmime-content-field.c | 3 +- camel/md5-utils.c | 5 +- camel/providers/Makefile.am | 4 +- camel/providers/mbox/camel-mbox-folder.c | 46 +-- camel/providers/pop3/camel-pop3-folder.c | 5 +- camel/providers/pop3/camel-pop3-store.c | 34 +- camel/providers/pop3/camel-pop3-store.h | 3 +- .../providers/sendmail/camel-sendmail-transport.c | 12 +- 30 files changed, 920 insertions(+), 812 deletions(-) diff --git a/camel/ChangeLog b/camel/ChangeLog index cfb0984c30..7a5bb2537f 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,51 @@ +2000-05-08 Dan Winship + + * camel-stream.c (camel_stream_read, camel_stream_write, + camel_stream_flush, camel_stream_reset, camel_stream_printf, + camel_stream_write_to_stream): Use CamelException to signal + failure. + (camel_stream_write_strings): Remove. camel_stream_printf is more + useful in most of the places that used this. + (camel_stream_write_string): Change from macro to function to + prevent problems with double-evaluation. + + * camel-seekable-stream.c (camel_seekable_stream_seek, + camel_seekable_stream_set_bounds): Use CamelException. + (reset): Update. + + * camel-seekable-substream.c, camel-stream-buffer.c, + camel-stream-filter.c, camel-stream-fs.c, camel-stream-mem.c: + Update. + + * camel-stream-fs.c: Remove the virtual init functions and move + the code into the creator functions. Add CamelExceptions to + creation functions that could fail. + + * camel-data-wrapper.c (camel_data_wrapper_write_to_stream): Use + CamelException. + * camel-mime-message.c, camel-mime-part.c, camel-multipart.c + (write_to_stream): Update. + + * camel-mime-parser.c: add an exception to the mime parser private + data and pass that to stream functions as needed. + + * gmime-content-field.c, md5-utils.c: Update (badly) for stream + changes. + + * camel-exception.h (camel_exception_is_set): convenience macro. + + * providers/Makefile.am: disable SMTP for now + + * providers/mbox/camel-mbox-folder.c (mbox_append_message): Pass + CamelException to the functions that now need it. Check the + exception after calling camel_stream_flush, and fail if it fails. + (mbox_get_message_by_uid): More updates. + + * providers/pop/camel-pop3-folder.c, + providers/pop/camel-pop3-store.c, + providers/sendmail/camel-sendmail/transport.c: Update. + + 2000-05-08 NotZed * camel-mime-message.c (process_header): Format From and Reply-To diff --git a/camel/camel-data-wrapper.c b/camel/camel-data-wrapper.c index fb0a161300..fcd7abb812 100644 --- a/camel/camel-data-wrapper.c +++ b/camel/camel-data-wrapper.c @@ -24,6 +24,7 @@ */ #include #include "camel-data-wrapper.h" +#include "camel-exception.h" #include @@ -41,7 +42,7 @@ static CamelStream *get_output_stream (CamelDataWrapper *data_wrapper); static int construct_from_stream(CamelDataWrapper *, CamelStream *); static int write_to_stream (CamelDataWrapper *data_wrapper, - CamelStream *stream); + CamelStream *stream, CamelException *ex); static void set_mime_type (CamelDataWrapper *data_wrapper, const gchar *mime_type); static gchar *get_mime_type (CamelDataWrapper *data_wrapper); @@ -204,44 +205,44 @@ camel_data_wrapper_get_output_stream (CamelDataWrapper *data_wrapper) static int -write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) +write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream, + CamelException *ex) { CamelStream *output_stream; d(printf("data_wrapper::write_to_stream\n")); output_stream = camel_data_wrapper_get_output_stream (data_wrapper); - if (!output_stream) { - g_warning("write to stream with no stream"); - errno = EBADF; - return -1; - } + g_return_val_if_fail (CAMEL_IS_STREAM (output_stream), -1); - camel_stream_reset (output_stream); - - return camel_stream_write_to_stream(output_stream, stream); + camel_stream_reset (output_stream, ex); + if (camel_exception_is_set (ex)) + return -1; + return camel_stream_write_to_stream (output_stream, stream, ex); } /** * camel_data_wrapper_write_to_stream: * @data_wrapper: a data wrapper * @stream: stream for data to be written to + * @ex: a CamelException * * Writes the data content to @stream in a machine-independent format * appropriate for the data. It should be possible to construct an * equivalent data wrapper object later by passing this stream to * camel_data_construct_from_stream(). * - * Returns the number of bytes written, and -1 for error. + * Return value: the number of bytes written, or -1 if an error occurs. **/ int camel_data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper, - CamelStream *stream) + CamelStream *stream, CamelException *ex) { g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1); g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); - return CDW_CLASS (data_wrapper)->write_to_stream (data_wrapper, stream); + return CDW_CLASS (data_wrapper)->write_to_stream (data_wrapper, + stream, ex); } static int diff --git a/camel/camel-data-wrapper.h b/camel/camel-data-wrapper.h index 8daf7a84db..da44a60233 100644 --- a/camel/camel-data-wrapper.h +++ b/camel/camel-data-wrapper.h @@ -71,7 +71,8 @@ typedef struct { GMimeContentField *mime_type_field); int (*write_to_stream) (CamelDataWrapper *data_wrapper, - CamelStream *stream); + CamelStream *stream, + CamelException *ex); int (*construct_from_stream) (CamelDataWrapper *data_wrapper, CamelStream *); @@ -87,7 +88,8 @@ GtkType camel_data_wrapper_get_type (void); CamelDataWrapper *camel_data_wrapper_new (void); int camel_data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper, - CamelStream *stream); + CamelStream *stream, + CamelException *ex); void camel_data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper, const gchar *mime_type); gchar * camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper); diff --git a/camel/camel-exception.c b/camel/camel-exception.c index 9a20dd2838..cf5daff9d3 100644 --- a/camel/camel-exception.c +++ b/camel/camel-exception.c @@ -153,7 +153,8 @@ camel_exception_set (CamelException *ex, * camel_exception_setv: set an exception * @ex: exception object * @id: exception id - * @format: format of the description string. The format string is used as in printf(). + * @format: format of the description string. The format string is + * used as in printf(). * * Set the value of an exception. The exception id is * a unique number representing the exception. The @@ -162,6 +163,9 @@ camel_exception_set (CamelException *ex, * In this version, the string is created from the format * string and the variable argument list. * + * It is safe to say: + * camel_exception_setv (ex, ..., camel_exception_get_description (ex), ...); + * * When @ex is NULL, nothing is done, this routine * simply returns. * diff --git a/camel/camel-exception.h b/camel/camel-exception.h index 0f4772e7ce..d5c93e5941 100644 --- a/camel/camel-exception.h +++ b/camel/camel-exception.h @@ -79,7 +79,7 @@ void camel_exception_xfer (CamelException *ex_dst, ExceptionId camel_exception_get_id (CamelException *ex); const gchar * camel_exception_get_description (CamelException *ex); - +#define camel_exception_is_set(ex) (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE) #ifdef __cplusplus } diff --git a/camel/camel-mime-message.c b/camel/camel-mime-message.c index aa6cbeee4c..73d21e7735 100644 --- a/camel/camel-mime-message.c +++ b/camel/camel-mime-message.c @@ -66,7 +66,8 @@ static guint signals[LAST_SIGNAL] = { 0 }; static void set_message_number (CamelMimeMessage *mime_message, guint number); static guint get_message_number (CamelMimeMessage *mime_message); -static int write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream); +static int write_to_stream (CamelDataWrapper *data_wrapper, + CamelStream *stream, CamelException *ex); static void finalize (GtkObject *object); static void add_header (CamelMedium *medium, const char *header_name, const void *header_value); static void set_header (CamelMedium *medium, const char *header_name, const void *header_value); @@ -536,7 +537,8 @@ construct_from_parser(CamelMimePart *dw, CamelMimeParser *mp) } static int -write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) +write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream, + CamelException *ex) { CamelMimeMessage *mm = CAMEL_MIME_MESSAGE (data_wrapper); @@ -554,11 +556,11 @@ write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) camel_mime_message_set_subject(mm, "No Subject"); } - /* FIXME: "To" header needs to be set explcitly as well ... */ + /* FIXME: "To" header needs to be set explicitly as well ... */ camel_medium_set_header((CamelMedium *)mm, "Mime-Version", "1.0"); - return CAMEL_DATA_WRAPPER_CLASS (parent_class)->write_to_stream (data_wrapper, stream); + return CAMEL_DATA_WRAPPER_CLASS (parent_class)->write_to_stream (data_wrapper, stream, ex); } static char * diff --git a/camel/camel-mime-parser.c b/camel/camel-mime-parser.c index ef4434e97a..3db6adfe83 100644 --- a/camel/camel-mime-parser.c +++ b/camel/camel-mime-parser.c @@ -41,6 +41,7 @@ #include "camel-mime-filter.h" #include "camel-stream.h" #include "camel-seekable-stream.h" +#include "camel-exception.h" #define r(x) #define h(x) @@ -208,6 +209,7 @@ struct _header_scan_state { int fd; /* input for a fd input */ CamelStream *stream; /* or for a stream */ + CamelException *ex; /* exception for the stream */ /* for scanning input buffers */ char *realbuf; /* the real buffer, SCAN_HEAD*2 + SCAN_BUF bytes */ @@ -824,7 +826,8 @@ folder_read(struct _header_scan_state *s) memcpy(s->inbuf, s->inptr, inoffset); } if (s->stream) { - len = camel_stream_read(s->stream, s->inbuf+inoffset, SCAN_BUF-inoffset); + len = camel_stream_read(s->stream, s->inbuf+inoffset, + SCAN_BUF-inoffset, s->ex); } else { len = read(s->fd, s->inbuf+inoffset, SCAN_BUF-inoffset); } @@ -869,7 +872,7 @@ folder_seek(struct _header_scan_state *s, off_t offset, int whence) if (CAMEL_IS_SEEKABLE_STREAM(s->stream)) { /* NOTE: assumes whence seekable stream == whence libc, which is probably the case (or bloody well should've been) */ - newoffset = camel_seekable_stream_seek((CamelSeekableStream *)s->stream, offset, whence); + newoffset = camel_seekable_stream_seek((CamelSeekableStream *)s->stream, offset, whence, s->ex); } else { newoffset = -1; errno = EINVAL; @@ -886,7 +889,7 @@ folder_seek(struct _header_scan_state *s, off_t offset, int whence) s->inptr = s->inbuf; s->inend = s->inbuf; if (s->stream) - len = camel_stream_read(s->stream, s->inbuf, SCAN_BUF); + len = camel_stream_read(s->stream, s->inbuf, SCAN_BUF, s->ex); else len = read(s->fd, s->inbuf, SCAN_BUF); if (len>=0) { @@ -1353,8 +1356,10 @@ folder_scan_close(struct _header_scan_state *s) folder_pull_part(s); if (s->fd != -1) close(s->fd); - if (s->stream) + if (s->stream) { gtk_object_unref((GtkObject *)s->stream); + camel_exception_free(s->ex); + } g_free(s); } @@ -1368,6 +1373,7 @@ folder_scan_init(void) s->fd = -1; s->stream = NULL; + s->ex = NULL; s->outbuf = g_malloc(1024); s->outptr = s->outbuf; @@ -1415,6 +1421,8 @@ folder_scan_init_with_fd(struct _header_scan_state *s, int fd) if (s->stream) { gtk_object_unref((GtkObject *)s->stream); s->stream = NULL; + camel_exception_free(s->ex); + s->ex = NULL; } return 0; } else { @@ -1426,9 +1434,11 @@ static int folder_scan_init_with_stream(struct _header_scan_state *s, CamelStream *stream) { int len; + CamelException *ex; - len = camel_stream_read(stream, s->inbuf, SCAN_BUF); - if (len>=0) { + ex = camel_exception_new(); + len = camel_stream_read(stream, s->inbuf, SCAN_BUF, ex); + if (!camel_exception_is_set (ex)) { s->inend = s->inbuf+len; s->inptr = s->inbuf; s->inend[0] = '\n'; @@ -1436,12 +1446,16 @@ folder_scan_init_with_stream(struct _header_scan_state *s, CamelStream *stream) gtk_object_unref((GtkObject *)s->stream); s->stream = stream; gtk_object_ref((GtkObject *)stream); + if (s->ex) + camel_exception_free(s->ex); + s->ex = ex; if (s->fd != -1) { close(s->fd); s->fd = -1; } return 0; } else { + camel_exception_free (ex); return -1; } } diff --git a/camel/camel-mime-part.c b/camel/camel-mime-part.c index 1688168737..cd6362f8d3 100644 --- a/camel/camel-mime-part.c +++ b/camel/camel-mime-part.c @@ -36,6 +36,7 @@ #include "camel-stream-mem.h" #include "camel-stream-filter.h" #include "camel-mime-filter-basic.h" +#include "camel-exception.h" #define d(x) @@ -66,7 +67,8 @@ static void finalize (GtkObject *object); /* from CamelDataWrapper */ static int write_to_stream (CamelDataWrapper *data_wrapper, - CamelStream *stream); + CamelStream *stream, + CamelException *ex); static int construct_from_stream (CamelDataWrapper *dw, CamelStream *s); /* from CamelMedia */ @@ -478,12 +480,13 @@ set_content_object (CamelMedium *medium, CamelDataWrapper *content) /**********************************************************************/ static int -write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) +write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream, + CamelException *ex) { CamelMimePart *mp = CAMEL_MIME_PART (data_wrapper); CamelMedium *medium = CAMEL_MEDIUM (data_wrapper); CamelDataWrapper *content; - int total = 0, count; + int total = 0; d(printf("mime_part::write_to_stream\n")); @@ -494,16 +497,19 @@ write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) if (mp->headers) { struct _header_raw *h = mp->headers; while (h) { - if ( (count = camel_stream_write_strings (stream, h->name, isspace(h->value[0])?":":": ", h->value, "\n", NULL) ) == -1 ) + total += camel_stream_printf (stream, ex, "%s%s%s\n", + h->name, + isspace(h->value[0]) ? ":" : ": ", + h->value); + if (camel_exception_is_set (ex)) return -1; - total += count; h = h->next; } } - if ( (count = camel_stream_write_string(stream,"\n")) == -1) + total += camel_stream_write (stream, "\n", 1, ex); + if (camel_exception_is_set (ex)) return -1; - total += count; content = camel_medium_get_content_object (medium); if (content) { @@ -531,13 +537,11 @@ write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) } #endif - if ( (count = camel_data_wrapper_write_to_stream(content, stream)) == -1 ) - total = -1; - else - total += count; - + total += camel_data_wrapper_write_to_stream (content, stream, ex); if (filter_stream) gtk_object_unref((GtkObject *)filter_stream); + if (camel_exception_is_set (ex)) + return -1; } else { g_warning("No content for medium, nothing to write"); } diff --git a/camel/camel-multipart.c b/camel/camel-multipart.c index c0f50eb331..347eb3bdcc 100644 --- a/camel/camel-multipart.c +++ b/camel/camel-multipart.c @@ -31,6 +31,7 @@ #include "camel-stream-mem.h" #include "camel-multipart.h" #include "camel-mime-part.h" +#include "camel-exception.h" #define d(x) @@ -50,7 +51,8 @@ static void set_boundary (CamelMultipart *multipart, gchar *boundary); static const gchar * get_boundary (CamelMultipart *multipart); static int write_to_stream (CamelDataWrapper *data_wrapper, - CamelStream *stream); + CamelStream *stream, + CamelException *ex); static void finalize (GtkObject *object); static CamelDataWrapperClass *parent_class = NULL; @@ -404,18 +406,19 @@ camel_multipart_get_boundary (CamelMultipart *multipart) /* this is MIME specific, doesn't belong here really */ static int -write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) +write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream, + CamelException *ex) { CamelMultipart *multipart = CAMEL_MULTIPART (data_wrapper); const gchar *boundary; - int total = 0, count; + int total = 0; GList *node; /* get the bundary text */ boundary = camel_multipart_get_boundary (multipart); /* we cannot write a multipart without a boundary string */ - g_return_val_if_fail (boundary, -1); + g_return_val_if_fail (boundary && *boundary, -1); /* * write the preface text (usually something like @@ -423,39 +426,40 @@ write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) * your mail client probably doesn't support ...." */ if (multipart->preface) { - count = camel_stream_write_strings (stream, multipart->preface, NULL); - if (count == -1) + total += camel_stream_write_string (stream, + multipart->preface, ex); + if (camel_exception_is_set (ex)) return -1; - total += count; } /* * Now, write all the parts, separated by the boundary * delimiter */ - if (boundary==NULL || (boundary[0] == '\0')) - g_warning ("Multipart boundary is zero length\n"); - node = multipart->parts; while (node) { - if ( (count = camel_stream_write_strings (stream, "\n--", boundary?boundary:"", "\n", NULL) ) == -1 ) + total += camel_stream_printf (stream, ex, "\n--%s\n", + boundary); + if (camel_exception_is_set (ex)) return -1; - total += count; - if ( (count = camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (node->data), stream)) == -1 ) + + total += camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (node->data), stream, ex); + if (camel_exception_is_set (ex)); return -1; - total += count; node = node->next; } /* write the terminating boudary delimiter */ - if ( ( count = camel_stream_write_strings (stream, "\n--", boundary, "--\n", NULL) ) == -1 ) + total += camel_stream_printf (stream, ex, "\n--%s--\n", boundary); + if (camel_exception_is_set (ex)) return -1; - total += count; - - /* and finally the postface - it is NOT fatal if this fails */ + + /* and finally the postface */ if (multipart->postface) { - if ( ( count = camel_stream_write_strings (stream, multipart->postface, NULL) ) != -1 ) - total += count; + total += camel_stream_write_string (stream, + multipart->postface, ex); + if (camel_exception_is_set (ex)) + return -1; } return total; diff --git a/camel/camel-seekable-stream.c b/camel/camel-seekable-stream.c index 6d51c6c554..a62ae9544f 100644 --- a/camel/camel-seekable-stream.c +++ b/camel/camel-seekable-stream.c @@ -1,14 +1,13 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * - * Author : +/* + * Author: * Bertrand Guiheneuf * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * @@ -24,31 +23,31 @@ */ - #include #include "camel-seekable-stream.h" -static CamelStreamClass *parent_class=NULL; - +static CamelStreamClass *parent_class = NULL; /* Returns the class for a CamelSeekableStream */ #define CSS_CLASS(so) CAMEL_SEEKABLE_STREAM_CLASS (GTK_OBJECT(so)->klass) -static off_t seek (CamelSeekableStream *stream, - off_t offset, - CamelStreamSeekPolicy policy); -static off_t stream_tell (CamelSeekableStream *stream); -static void reset (CamelStream *stream); -static void set_bounds (CamelSeekableStream *stream, off_t start, off_t end); +static off_t seek (CamelSeekableStream *stream, off_t offset, + CamelStreamSeekPolicy policy, + CamelException *ex); +static off_t stream_tell (CamelSeekableStream *stream); +static void reset (CamelStream *stream, CamelException *ex); +static void set_bounds (CamelSeekableStream *stream, off_t start, off_t end, + CamelException *ex); static void camel_seekable_stream_class_init (CamelSeekableStreamClass *camel_seekable_stream_class) { - CamelStreamClass *camel_stream_class = CAMEL_STREAM_CLASS (camel_seekable_stream_class); + CamelStreamClass *camel_stream_class = + CAMEL_STREAM_CLASS (camel_seekable_stream_class); parent_class = gtk_type_class (camel_stream_get_type ()); - + /* seekable stream methods */ camel_seekable_stream_class->seek = seek; camel_seekable_stream_class->tell = stream_tell; @@ -71,9 +70,9 @@ GtkType camel_seekable_stream_get_type (void) { static GtkType camel_seekable_stream_type = 0; - - if (!camel_seekable_stream_type) { - GtkTypeInfo camel_seekable_stream_info = + + if (!camel_seekable_stream_type) { + GtkTypeInfo camel_seekable_stream_info = { "CamelSeekableStream", sizeof (CamelSeekableStream), @@ -84,19 +83,20 @@ camel_seekable_stream_get_type (void) /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; - + camel_seekable_stream_type = gtk_type_unique (camel_stream_get_type (), &camel_seekable_stream_info); } - + return camel_seekable_stream_type; } + static off_t -seek (CamelSeekableStream *stream, - off_t offset, - CamelStreamSeekPolicy policy) +seek (CamelSeekableStream *stream, off_t offset, + CamelStreamSeekPolicy policy, CamelException *ex) { - g_warning ("CamelSeekableStream::seek called on default implementation \n"); + g_warning ("CamelSeekableStream::seek called on default " + "implementation\n"); return -1; } @@ -105,7 +105,8 @@ seek (CamelSeekableStream *stream, * @stream: a CamelStream object. * @offset: offset value * @policy: what to do with the offset - * + * @ex: a CamelException + * * Seek to the specified position in @stream. * * If @policy is CAMEL_STREAM_SET, seeks to @offset. @@ -117,78 +118,88 @@ seek (CamelSeekableStream *stream, * @offset. * * Regardless of @policy, the stream's final position will be clamped - * to the range specified by its lower and upper bounds. - * + * to the range specified by its lower and upper bounds, and the + * stream's eos state will be updated. + * * Return value: new position, -1 if operation failed. **/ off_t -camel_seekable_stream_seek (CamelSeekableStream *stream, - off_t offset, - CamelStreamSeekPolicy policy) +camel_seekable_stream_seek (CamelSeekableStream *stream, off_t offset, + CamelStreamSeekPolicy policy, + CamelException *ex) { - return CSS_CLASS (stream)->seek (stream, offset, policy); + g_return_val_if_fail (CAMEL_IS_SEEKABLE_STREAM (stream), -1); + + return CSS_CLASS (stream)->seek (stream, offset, policy, ex); } + static off_t -stream_tell(CamelSeekableStream *stream) +stream_tell (CamelSeekableStream *stream) { return stream->position; } /** - * camel_seekable_stream_tell: get the position of a stream - * @stream: seekable stream object - * + * camel_seekable_stream_tell: + * @stream: seekable stream object + * * Get the current position of a seekable stream. - * + * * Return value: the position. **/ off_t camel_seekable_stream_tell (CamelSeekableStream *stream) { + g_return_val_if_fail (CAMEL_IS_SEEKABLE_STREAM (stream), -1); + return CSS_CLASS (stream)->tell (stream); } + static void -set_bounds (CamelSeekableStream *stream, off_t start, off_t end) +set_bounds (CamelSeekableStream *stream, off_t start, off_t end, + CamelException *ex) { /* store the bounds */ stream->bound_start = start; stream->bound_end = end; - /* FIXME: this is probably to be reset by seek ... */ - ((CamelStream *)stream)->eos = FALSE; - if (start > stream->position) - camel_seekable_stream_seek(stream, start, CAMEL_STREAM_SET); + camel_seekable_stream_seek (stream, start, CAMEL_STREAM_SET, ex); } /** * camel_seekable_stream_set_bounds: - * @stream: - * @start: - * @end: - * + * @stream: a seekable stream + * @start: the first valid position + * @end: the first invalid position, or CAMEL_STREAM_UNBOUND + * * Set the range of valid data this stream is allowed to cover. If * there is to be no @end value, then @end should be set to * #CAMEL_STREAM_UNBOUND. **/ void -camel_seekable_stream_set_bounds(CamelSeekableStream *stream, off_t start, off_t end) +camel_seekable_stream_set_bounds (CamelSeekableStream *stream, + off_t start, off_t end, CamelException *ex) { - CSS_CLASS (stream)->set_bounds (stream, start, end); + g_return_if_fail (CAMEL_IS_SEEKABLE_STREAM (stream)); + g_return_if_fail (end == CAMEL_STREAM_UNBOUND || end >= start); + + CSS_CLASS (stream)->set_bounds (stream, start, end, ex); } /* a default implementation of reset for seekable streams */ -static void -reset (CamelStream *stream) +static void +reset (CamelStream *stream, CamelException *ex) { CamelSeekableStream *seekable_stream; - g_assert (stream); seekable_stream = CAMEL_SEEKABLE_STREAM (stream); - camel_seekable_stream_seek (seekable_stream, seekable_stream->bound_start, CAMEL_STREAM_SET); + camel_seekable_stream_seek (seekable_stream, + seekable_stream->bound_start, + CAMEL_STREAM_SET, ex); } diff --git a/camel/camel-seekable-stream.h b/camel/camel-seekable-stream.h index f9eb86636d..24333bcfa0 100644 --- a/camel/camel-seekable-stream.h +++ b/camel/camel-seekable-stream.h @@ -1,15 +1,14 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* camel-stream-fs.h :stream based on unix filesystem */ -/* - * - * Author : +/* + * Author: * Bertrand Guiheneuf * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * @@ -64,22 +63,28 @@ struct _CamelSeekableStream typedef struct { CamelStreamClass parent_class; - - /* Virtual methods */ - off_t (*seek) (CamelSeekableStream *stream, off_t offset, CamelStreamSeekPolicy policy); + + /* Virtual methods */ + off_t (*seek) (CamelSeekableStream *stream, off_t offset, + CamelStreamSeekPolicy policy, + CamelException *ex); off_t (*tell) (CamelSeekableStream *stream); - void (*set_bounds) (CamelSeekableStream *stream, off_t start, off_t end); + void (*set_bounds) (CamelSeekableStream *stream, + off_t start, off_t end, CamelException *ex); } CamelSeekableStreamClass; /* Standard Gtk function */ GtkType camel_seekable_stream_get_type (void); /* public methods */ -off_t camel_seekable_stream_seek (CamelSeekableStream *stream, - off_t offset, - CamelStreamSeekPolicy policy); -off_t camel_seekable_stream_tell (CamelSeekableStream *stream); -void camel_seekable_stream_set_bounds (CamelSeekableStream *, off_t, off_t); +off_t camel_seekable_stream_seek (CamelSeekableStream *stream, + off_t offset, + CamelStreamSeekPolicy policy, + CamelException *ex); +off_t camel_seekable_stream_tell (CamelSeekableStream *stream); +void camel_seekable_stream_set_bounds (CamelSeekableStream *, + off_t, off_t, + CamelException *); #ifdef __cplusplus } diff --git a/camel/camel-seekable-substream.c b/camel/camel-seekable-substream.c index 37d6acab9d..5c9ea6ebe7 100644 --- a/camel/camel-seekable-substream.c +++ b/camel/camel-seekable-substream.c @@ -23,34 +23,39 @@ */ #include #include "camel-seekable-substream.h" +#include "camel-exception.h" static CamelSeekableStreamClass *parent_class = NULL; /* Returns the class for a CamelSeekableSubStream */ #define CSS_CLASS(so) CAMEL_SEEKABLE_SUBSTREAM_CLASS (GTK_OBJECT(so)->klass) -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 int stream_read (CamelStream *stream, + char *buffer, unsigned int n, + CamelException *ex); +static int stream_write (CamelStream *stream, + const char *buffer, + unsigned int n, + CamelException *ex); +static void stream_flush (CamelStream *stream, + CamelException *ex); static gboolean eos (CamelStream *stream); static off_t stream_seek (CamelSeekableStream *stream, off_t offset, - CamelStreamSeekPolicy policy); + CamelStreamSeekPolicy policy, + CamelException *ex); static void finalize (GtkObject *object); -static void init_with_seekable_stream_and_bounds (CamelSeekableSubstream *seekable_substream, - CamelSeekableStream *parent_stream, - off_t start, off_t end); static void camel_seekable_substream_class_init (CamelSeekableSubstreamClass *camel_seekable_substream_class) { - CamelSeekableStreamClass *camel_seekable_stream_class = CAMEL_SEEKABLE_STREAM_CLASS (camel_seekable_substream_class); - CamelStreamClass *camel_stream_class = CAMEL_STREAM_CLASS (camel_seekable_substream_class); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_seekable_substream_class); + CamelSeekableStreamClass *camel_seekable_stream_class = + CAMEL_SEEKABLE_STREAM_CLASS (camel_seekable_substream_class); + CamelStreamClass *camel_stream_class = + CAMEL_STREAM_CLASS (camel_seekable_substream_class); + GtkObjectClass *gtk_object_class = + GTK_OBJECT_CLASS (camel_seekable_substream_class); parent_class = gtk_type_class (camel_seekable_stream_get_type ()); @@ -104,19 +109,6 @@ finalize (GtkObject *object) GTK_OBJECT_CLASS (parent_class)->finalize (object); } -static void -init_with_seekable_stream_and_bounds (CamelSeekableSubstream *seekable_substream, - CamelSeekableStream *parent_stream, - off_t start, off_t end) -{ - /* Store the parent stream. */ - seekable_substream->parent_stream = parent_stream; - gtk_object_ref (GTK_OBJECT (parent_stream)); - - /* Set the bound of the substream. */ - camel_seekable_stream_set_bounds ((CamelSeekableStream *)seekable_substream, start, end); -} - /** * camel_seekable_substream_new_with_seekable_stream_and_bounds: * @parent_stream: a seekable parent stream @@ -139,6 +131,7 @@ camel_seekable_substream_new_with_seekable_stream_and_bounds (CamelSeekableStrea off_t start, off_t end) { CamelSeekableSubstream *seekable_substream; + CamelException ex; g_return_val_if_fail (CAMEL_IS_SEEKABLE_STREAM (parent_stream), NULL); @@ -146,46 +139,56 @@ camel_seekable_substream_new_with_seekable_stream_and_bounds (CamelSeekableStrea seekable_substream = gtk_type_new (camel_seekable_substream_get_type ()); /* Initialize it. */ - init_with_seekable_stream_and_bounds (seekable_substream, - parent_stream, - start, end); + seekable_substream->parent_stream = parent_stream; + gtk_object_ref (GTK_OBJECT (parent_stream)); + + /* Set the bound of the substream. We can ignore any possible error + * here, because if we fail to seek now, it will try again later. + */ + camel_exception_init (&ex); + camel_seekable_stream_set_bounds ((CamelSeekableStream *)seekable_substream, start, end, &ex); + camel_exception_clear (&ex); + return CAMEL_STREAM (seekable_substream); } static gboolean -parent_reset (CamelSeekableSubstream *seekable_substream) +parent_reset (CamelSeekableSubstream *seekable_substream, + CamelSeekableStream *parent, CamelException *ex) { - CamelSeekableStream *parent, *seekable_stream = CAMEL_SEEKABLE_STREAM (seekable_substream); - - parent = seekable_substream->parent_stream; + CamelSeekableStream *seekable_stream = + CAMEL_SEEKABLE_STREAM (seekable_substream); - g_return_val_if_fail (parent != NULL, FALSE); - - if (camel_seekable_stream_tell(parent) != seekable_stream->position) { - return camel_seekable_stream_seek(parent, seekable_stream->position, CAMEL_STREAM_SET) - == seekable_stream->position; - } else { + if (camel_seekable_stream_tell (parent) == seekable_stream->position) return TRUE; - } + + camel_seekable_stream_seek (parent, seekable_stream->position, + CAMEL_STREAM_SET, ex); + return !camel_exception_is_set (ex); } -static gint -stream_read (CamelStream *stream, gchar *buffer, gint n) +static int +stream_read (CamelStream *stream, char *buffer, unsigned int n, + CamelException *ex) { + CamelSeekableStream *parent; CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream); - CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream); + CamelSeekableSubstream *seekable_substream = + CAMEL_SEEKABLE_SUBSTREAM (stream); int v; if (n == 0) return 0; + parent = seekable_substream->parent_stream; + /* Go to our position in the parent stream. */ - if (!parent_reset (seekable_substream)) { + if (!parent_reset (seekable_substream, parent, ex)) { stream->eos = TRUE; return 0; } - /* Compute how much byte should be read. */ + /* Compute how many bytes should be read. */ if (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND) n = MIN (seekable_stream->bound_end - seekable_stream->position, n); @@ -194,7 +197,7 @@ stream_read (CamelStream *stream, gchar *buffer, gint n) return 0; } - v = camel_stream_read (CAMEL_STREAM (seekable_substream->parent_stream), buffer, n); + v = camel_stream_read (CAMEL_STREAM (parent), buffer, n, ex); /* ignore <0 - its an error, let the caller deal */ if (v > 0) @@ -203,8 +206,9 @@ stream_read (CamelStream *stream, gchar *buffer, gint n) return v; } -static gint -stream_write (CamelStream *stream, const gchar *buffer, gint n) +static int +stream_write (CamelStream *stream, const char *buffer, unsigned int n, + CamelException *ex) { /* NOT VALID ON SEEKABLE SUBSTREAM */ /* Well, its entirely valid, just not implemented */ @@ -214,7 +218,7 @@ stream_write (CamelStream *stream, const gchar *buffer, gint n) } static void -stream_flush (CamelStream *stream) +stream_flush (CamelStream *stream, CamelException *ex) { /* NOT VALID ON SEEKABLE SUBSTREAM */ g_warning ("CamelSeekableSubstream:: seekable substream doesn't " @@ -224,37 +228,41 @@ stream_flush (CamelStream *stream) static gboolean eos (CamelStream *stream) { - CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream); + CamelSeekableSubstream *seekable_substream = + CAMEL_SEEKABLE_SUBSTREAM (stream); CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream); - guint32 substream_len; + CamelSeekableStream *parent; + CamelException ex; gboolean eos; - g_assert (stream); - - if (stream->eos) { + if (stream->eos) eos = TRUE; - } else { - parent_reset (seekable_substream); + else { + parent = seekable_substream->parent_stream; + camel_exception_init (&ex); + parent_reset (seekable_substream, parent, &ex); + if (camel_exception_is_set (&ex)) { + camel_exception_clear (&ex); + return TRUE; + } - eos = camel_stream_eos (CAMEL_STREAM (seekable_substream->parent_stream)); - if ((!eos) && (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND)) { - substream_len = seekable_stream->bound_start - seekable_stream->bound_end; - eos = ( seekable_stream->position >= substream_len); + eos = camel_stream_eos (CAMEL_STREAM (parent)); + if (!eos && (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND)) { + eos = seekable_stream->position >= seekable_stream->bound_end; } } return eos; } -/* seeks within a seekable substream follow the bound limits ... dont start at 0 */ static off_t stream_seek (CamelSeekableStream *seekable_stream, off_t offset, - CamelStreamSeekPolicy policy) + CamelStreamSeekPolicy policy, CamelException *ex) { - CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (seekable_stream); - CamelStream *stream = (CamelStream *)seekable_stream; + CamelSeekableSubstream *seekable_substream = + CAMEL_SEEKABLE_SUBSTREAM (seekable_stream); + CamelStream *stream = CAMEL_STREAM (seekable_stream); off_t real_offset = 0; - off_t parent_pos; stream->eos = FALSE; @@ -268,20 +276,13 @@ stream_seek (CamelSeekableStream *seekable_stream, off_t offset, break; case CAMEL_STREAM_END: - if (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND) - real_offset = seekable_stream->bound_end + offset; - else { - parent_pos = camel_seekable_stream_seek (seekable_substream->parent_stream, - offset, - CAMEL_STREAM_END); - if (parent_pos == -1) - return -1; - real_offset = parent_pos; - } + real_offset = camel_seekable_stream_seek (seekable_substream->parent_stream, + offset, + CAMEL_STREAM_END, + ex); + if (camel_exception_is_set (ex)) + return -1; break; - - default: - return -1; } if (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND) diff --git a/camel/camel-seekable-substream.h b/camel/camel-seekable-substream.h index 81e36b9fe2..721d33380a 100644 --- a/camel/camel-seekable-substream.h +++ b/camel/camel-seekable-substream.h @@ -1,7 +1,8 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-seekable-substream.h : stream - * - * Author : +/* camel-seekable-substream.h: stream that piggybacks on another stream */ + +/* + * Author: * Bertrand Guiheneuf * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) @@ -50,10 +51,6 @@ struct _CamelSeekableSubstream typedef struct { CamelSeekableStreamClass parent_class; - /* Virtual methods */ - void (*init_with_seekable_stream_and_bounds) (CamelSeekableSubstream *seekable_substream, - CamelSeekableStream *parent_stream, - off_t start, off_t end); } CamelSeekableSubstreamClass; /* Standard Gtk function */ diff --git a/camel/camel-stream-buffer.c b/camel/camel-stream-buffer.c index 7cc1754ad6..8475cab2c0 100644 --- a/camel/camel-stream-buffer.c +++ b/camel/camel-stream-buffer.c @@ -6,8 +6,8 @@ * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * @@ -25,12 +25,13 @@ #include #include "camel-stream-buffer.h" +#include "camel-exception.h" #include #include #include #include -static CamelStreamBufferClass *parent_class=NULL; +static CamelStreamBufferClass *parent_class = NULL; enum { BUF_USER = 1<<0, /* user-supplied buffer, do not free */ @@ -38,9 +39,11 @@ enum { #define BUF_SIZE 1024 -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 int stream_read (CamelStream *stream, char *buffer, + unsigned int n, CamelException *ex); +static int stream_write (CamelStream *stream, const char *buffer, + unsigned int n, CamelException *ex); +static void stream_flush (CamelStream *stream, CamelException *ex); static gboolean stream_eos (CamelStream *stream); static void finalize (GtkObject *object); @@ -56,7 +59,7 @@ camel_stream_buffer_class_init (CamelStreamBufferClass *camel_stream_buffer_clas GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_stream_buffer_class); parent_class = gtk_type_class (camel_stream_get_type ()); - + /* virtual method definition */ camel_stream_buffer_class->init = init; camel_stream_buffer_class->init_vbuf = init_vbuf; @@ -90,10 +93,10 @@ GtkType camel_stream_buffer_get_type (void) { static GtkType camel_stream_buffer_type = 0; - + gdk_threads_enter (); if (!camel_stream_buffer_type) { - GtkTypeInfo camel_stream_buffer_info = + GtkTypeInfo camel_stream_buffer_info = { "CamelStreamBuffer", sizeof (CamelStreamBuffer), @@ -104,7 +107,7 @@ camel_stream_buffer_get_type (void) /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; - + camel_stream_buffer_type = gtk_type_unique (camel_stream_get_type (), &camel_stream_buffer_info); } gdk_threads_leave (); @@ -112,19 +115,19 @@ camel_stream_buffer_get_type (void) } -static void +static void destroy (GtkObject *object) { CamelStreamBuffer *stream_buffer = CAMEL_STREAM_BUFFER (object); - + /* NOP to remove warnings */ stream_buffer->buf = stream_buffer->buf; - + GTK_OBJECT_CLASS (parent_class)->destroy (object); } -static void +static void finalize (GtkObject *object) { CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (object); @@ -134,7 +137,7 @@ finalize (GtkObject *object) } if (sbf->stream) gtk_object_unref(GTK_OBJECT(sbf->stream)); - + GTK_OBJECT_CLASS (parent_class)->finalize (object); } @@ -176,14 +179,14 @@ init(CamelStreamBuffer *sbuf, CamelStream *s, CamelStreamBufferMode mode) * camel_stream_buffer_new: * @stream: Existing stream to buffer. * @mode: Operational mode of buffered stream. - * + * * Create a new buffered stream of another stream. A default * buffer size (1024 bytes), automatically managed will be used * for buffering. * * See camel_stream_buffer_new_with_vbuf() for details on the * @mode parameter. - * + * * Return value: A newly created buffered stream. **/ CamelStream * @@ -192,7 +195,7 @@ camel_stream_buffer_new (CamelStream *stream, CamelStreamBufferMode mode) CamelStreamBuffer *sbf; sbf = gtk_type_new (camel_stream_buffer_get_type ()); CAMEL_STREAM_BUFFER_CLASS (GTK_OBJECT(sbf)->klass)->init (sbf, stream, mode); - + return CAMEL_STREAM (sbf); } @@ -202,7 +205,7 @@ camel_stream_buffer_new (CamelStream *stream, CamelStreamBufferMode mode) * @mode: Mode to buffer in. * @buf: Memory to use for buffering. * @size: Size of buffer to use. - * + * * Create a new stream which buffers another stream, @stream. * * The following values are available for @mode: @@ -219,10 +222,10 @@ camel_stream_buffer_new (CamelStream *stream, CamelStreamBufferMode mode) * * CAMEL_STREAM_BUFFER_WRITE, Buffer in write mode. * CAMEL_STREAM_BUFFER_READ, Buffer in read mode. - * + * * Buffering can only be done in one direction for any * buffer instance. - * + * * If @buf is non-NULL, then use the memory pointed to * (for upto @size bytes) as the buffer for all buffering * operations. It is upto the application to free this buffer. @@ -236,34 +239,25 @@ CamelStream *camel_stream_buffer_new_with_vbuf (CamelStream *stream, CamelStream CamelStreamBuffer *sbf; sbf = gtk_type_new (camel_stream_buffer_get_type ()); CAMEL_STREAM_BUFFER_CLASS (GTK_OBJECT(sbf)->klass)->init_vbuf (sbf, stream, mode, buf, size); - - return CAMEL_STREAM (sbf); + + return CAMEL_STREAM (sbf); } -/** - * _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 -stream_read (CamelStream *stream, gchar *buffer, gint n) +static int +stream_read (CamelStream *stream, char *buffer, unsigned int n, + CamelException *ex) { CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (stream); - int bytes_read=1; + int bytes_read = 1; int bytes_left; - gchar *bptr = buffer; + char *bptr = buffer; g_return_val_if_fail( (sbf->mode & CAMEL_STREAM_BUFFER_MODE) == CAMEL_STREAM_BUFFER_READ, 0); - while (n && bytes_read>0) { + while (n && bytes_read > 0) { bytes_left = sbf->end - sbf->ptr; - if (bytes_left0) { + if (bytes_left < n) { + if (bytes_left > 0) { memcpy(bptr, sbf->ptr, bytes_left); n -= bytes_left; bptr += bytes_left; @@ -271,13 +265,13 @@ stream_read (CamelStream *stream, gchar *buffer, gint n) } /* if we are reading a lot, then read directly to the destination buffer */ if (n >= sbf->size/3) { - bytes_read = camel_stream_read(sbf->stream, bptr, n); + bytes_read = camel_stream_read(sbf->stream, bptr, n, ex); if (bytes_read>0) { n -= bytes_read; bptr += bytes_read; } } else { - bytes_read = camel_stream_read(sbf->stream, sbf->buf, sbf->size); + bytes_read = camel_stream_read(sbf->stream, sbf->buf, sbf->size, ex); if (bytes_read>0) { sbf->ptr = sbf->buf; sbf->end = sbf->buf+bytes_read; @@ -287,6 +281,8 @@ stream_read (CamelStream *stream, gchar *buffer, gint n) n -= bytes_read; } } + if (camel_exception_is_set (ex)) + return -1; } else { memcpy(bptr, sbf->ptr, bytes_left); sbf->ptr += n; @@ -299,11 +295,12 @@ stream_read (CamelStream *stream, gchar *buffer, gint n) } -static gint -stream_write (CamelStream *stream, const gchar *buffer, gint n) +static int +stream_write (CamelStream *stream, const char *buffer, + unsigned int n, CamelException *ex) { CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (stream); - const gchar *bptr = buffer; + const char *bptr = buffer; int bytes_written = 1; int bytes_left; @@ -315,11 +312,11 @@ stream_write (CamelStream *stream, const gchar *buffer, gint n) memcpy(sbf->ptr, bptr, bytes_left); n -= bytes_left; bptr += bytes_left; - bytes_written = camel_stream_write(sbf->stream, sbf->buf, sbf->size); + bytes_written = camel_stream_write(sbf->stream, sbf->buf, sbf->size, ex); sbf->ptr = sbf->buf; /* if we are writing a lot, write directly to the stream */ if (n >= sbf->size/3) { - bytes_written = camel_stream_write(sbf->stream, bptr, n); + bytes_written = camel_stream_write(sbf->stream, bptr, n, ex); bytes_written = n; n -= bytes_written; bptr += bytes_written; @@ -329,6 +326,8 @@ stream_write (CamelStream *stream, const gchar *buffer, gint n) bptr += n; n = 0; } + if (camel_exception_is_set (ex)) + return -1; } else { memcpy(sbf->ptr, bptr, n); sbf->ptr += n; @@ -342,12 +341,12 @@ stream_write (CamelStream *stream, const gchar *buffer, gint n) static void -stream_flush (CamelStream *stream) +stream_flush (CamelStream *stream, CamelException *ex) { CamelStreamBuffer *sbf = CAMEL_STREAM_BUFFER (stream); if ((sbf->mode & CAMEL_STREAM_BUFFER_MODE) == CAMEL_STREAM_BUFFER_WRITE) { - int written = camel_stream_write(sbf->stream, sbf->buf, sbf->ptr-sbf->buf); + int written = camel_stream_write(sbf->stream, sbf->buf, sbf->ptr-sbf->buf, ex); if (written > 0) { sbf->ptr += written; } @@ -355,7 +354,8 @@ stream_flush (CamelStream *stream) /* nothing to do for read mode 'flush' */ } - camel_stream_flush(sbf->stream); + if (!camel_exception_is_set (ex)) + camel_stream_flush(sbf->stream, ex); } static gboolean @@ -371,17 +371,19 @@ stream_eos (CamelStream *stream) * @sbf: A CamelStreamBuffer. * @buf: Memory to write the string to. * @max: Maxmimum number of characters to store. - * + * @ex: a CamelException + * * Read a line of characters up to the next newline character or * @max characters. * * If the newline character is encountered, then it will be * included in the buffer @buf. The buffer will be #NUL terminated. - * - * Return value: The number of characters read, or 0 for end of file or - * file error. + * + * Return value: The number of characters read, or 0 for end of file. + * If an error occurs, @ex will be set. **/ -int camel_stream_buffer_gets(CamelStreamBuffer *sbf, char *buf, int max) +int camel_stream_buffer_gets(CamelStreamBuffer *sbf, char *buf, + unsigned int max, CamelException *ex) { register char *outptr, *inptr, *inend, c, *outend; int bytes_read; @@ -404,12 +406,13 @@ int camel_stream_buffer_gets(CamelStreamBuffer *sbf, char *buf, int max) if (outptr == outend) break; - bytes_read = camel_stream_read(sbf->stream, sbf->buf, sbf->size); + bytes_read = camel_stream_read(sbf->stream, sbf->buf, + sbf->size, ex); if (bytes_read>0) { inptr = sbf->ptr = sbf->buf; inend = sbf->end = sbf->buf + bytes_read; } - } while (bytes_read>0); + } while (bytes_read>0 && !camel_exception_is_set (ex)); sbf->ptr = inptr; if (outptr<=outend) @@ -421,16 +424,17 @@ int camel_stream_buffer_gets(CamelStreamBuffer *sbf, char *buf, int max) /** * camel_stream_buffer_read_line: read a complete line from the stream * @sbf: A CamelStreamBuffer + * @ex: a CamelException * * This function reads a complete newline-terminated line from the stream * and returns it in allocated memory. The trailing newline (and carriage * return if any) are not included in the returned string. * * Return value: the line read, which the caller must free when done with, - * or NULL on eof or error. + * or NULL on eof. If an error occurs, @ex will be set. **/ char * -camel_stream_buffer_read_line (CamelStreamBuffer *sbf) +camel_stream_buffer_read_line (CamelStreamBuffer *sbf, CamelException *ex) { char *buf, *p; int bufsiz, nread; @@ -439,8 +443,9 @@ camel_stream_buffer_read_line (CamelStreamBuffer *sbf) p = buf = g_malloc (bufsiz); while (1) { - nread = camel_stream_buffer_gets (sbf, p, bufsiz - (p - buf)); - if (nread == 0) { + nread = camel_stream_buffer_gets (sbf, p, + bufsiz - (p - buf), ex); + if (nread == 0 || camel_exception_is_set (ex)) { g_free (buf); return NULL; } diff --git a/camel/camel-stream-buffer.h b/camel/camel-stream-buffer.h index 8f926cd231..33132e39a4 100644 --- a/camel/camel-stream-buffer.h +++ b/camel/camel-stream-buffer.h @@ -1,15 +1,15 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* camel-stream-buffer.h :stream which buffers another stream */ -/* +/* * - * Author : + * Author : * Michael Zucchi * * Copyright 2000 Helix Code Inc. (http://www.helixcode.com) . * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * @@ -42,7 +42,7 @@ extern "C" { #define CAMEL_STREAM_BUFFER_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), CAMEL_STREAM_BUFFER_TYPE, CamelStreamBufferClass)) #define CAMEL_IS_STREAM_BUFFER(o) (GTK_CHECK_TYPE((o), CAMEL_STREAM_BUFFER_TYPE)) -typedef enum +typedef enum { CAMEL_STREAM_BUFFER_BUFFER = 0, CAMEL_STREAM_BUFFER_NEWLINE, @@ -59,9 +59,7 @@ struct _CamelStreamBuffer /* these are all of course, private */ CamelStream *stream; - unsigned char *buf, - *ptr, - *end; + unsigned char *buf, *ptr, *end; int size; CamelStreamBufferMode mode; @@ -69,16 +67,17 @@ struct _CamelStreamBuffer }; - typedef struct { CamelStreamClass parent_class; - - /* Virtual methods */ - void (*init) (CamelStreamBuffer *stream_buffer, CamelStream *stream, CamelStreamBufferMode mode); - void (*init_vbuf) (CamelStreamBuffer *stream_buffer, CamelStream *stream, CamelStreamBufferMode mode, char *buf, guint32 size); -} CamelStreamBufferClass; + /* Virtual methods */ + void (*init) (CamelStreamBuffer *stream_buffer, CamelStream *stream, + CamelStreamBufferMode mode); + void (*init_vbuf) (CamelStreamBuffer *stream_buffer, + CamelStream *stream, CamelStreamBufferMode mode, + char *buf, guint32 size); +} CamelStreamBufferClass; /* Standard Gtk function */ @@ -86,16 +85,21 @@ GtkType camel_stream_buffer_get_type (void); /* public methods */ -CamelStream *camel_stream_buffer_new (CamelStream *s, CamelStreamBufferMode mode); -CamelStream *camel_stream_buffer_new_with_vbuf (CamelStream *s, CamelStreamBufferMode mode, char *buf, guint32 size); +CamelStream *camel_stream_buffer_new (CamelStream *s, + CamelStreamBufferMode mode); +CamelStream *camel_stream_buffer_new_with_vbuf (CamelStream *s, + CamelStreamBufferMode mode, + char *buf, guint32 size); /* unimplemented CamelStream *camel_stream_buffer_set_vbuf (CamelStreamBuffer *b, CamelStreamBufferMode mode, char *buf, guint32 size); */ /* read a line of characters */ -int camel_stream_buffer_gets(CamelStreamBuffer *b, char *buf, int max); +int camel_stream_buffer_gets (CamelStreamBuffer *b, char *buf, + unsigned int max, CamelException *ex); -char *camel_stream_buffer_read_line (CamelStreamBuffer *sbf); +char *camel_stream_buffer_read_line (CamelStreamBuffer *sbf, + CamelException *ex); #ifdef __cplusplus } diff --git a/camel/camel-stream-filter.c b/camel/camel-stream-filter.c index 03fb2fc566..389390caaf 100644 --- a/camel/camel-stream-filter.c +++ b/camel/camel-stream-filter.c @@ -19,6 +19,7 @@ */ #include "camel-stream-filter.h" +#include "camel-exception.h" struct _filter { struct _filter *next; @@ -47,11 +48,13 @@ struct _CamelStreamFilterPrivate { static void camel_stream_filter_class_init (CamelStreamFilterClass *klass); static void camel_stream_filter_init (CamelStreamFilter *obj); -static gint do_read (CamelStream *stream, gchar *buffer, gint n); -static gint do_write (CamelStream *stream, const gchar *buffer, gint n); -static void do_flush (CamelStream *stream); +static int do_read (CamelStream *stream, char *buffer, + unsigned int n, CamelException *ex); +static int do_write (CamelStream *stream, const char *buffer, + unsigned int n, CamelException *ex); +static void do_flush (CamelStream *stream, CamelException *ex); static gboolean do_eos (CamelStream *stream); -static void do_reset (CamelStream *stream); +static void do_reset (CamelStream *stream, CamelException *ex); static CamelStreamClass *camel_stream_filter_parent; @@ -212,7 +215,8 @@ camel_stream_filter_remove(CamelStreamFilter *filter, int id) } } -static gint do_read (CamelStream *stream, gchar *buffer, gint n) +static int +do_read (CamelStream *stream, char *buffer, unsigned int n, CamelException *ex) { CamelStreamFilter *filter = (CamelStreamFilter *)stream; struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); @@ -224,7 +228,7 @@ static gint do_read (CamelStream *stream, gchar *buffer, gint n) if (p->filteredlen<=0) { int presize = READ_SIZE; - size = camel_stream_read(filter->source, p->buffer, READ_SIZE); + size = camel_stream_read(filter->source, p->buffer, READ_SIZE, ex); if (size<=0) { /* this is somewhat untested */ if (camel_stream_eos(filter->source)) { @@ -258,7 +262,8 @@ static gint do_read (CamelStream *stream, gchar *buffer, gint n) return size; } -static gint do_write (CamelStream *stream, const gchar *buf, gint n) +static int +do_write (CamelStream *stream, const char *buf, unsigned int n, CamelException *ex) { CamelStreamFilter *filter = (CamelStreamFilter *)stream; struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); @@ -275,10 +280,11 @@ static gint do_write (CamelStream *stream, const gchar *buf, gint n) f = f->next; } - return camel_stream_write(filter->source, buffer, n); + return camel_stream_write(filter->source, buffer, n, ex); } -static void do_flush (CamelStream *stream) +static void +do_flush (CamelStream *stream, CamelException *ex) { CamelStreamFilter *filter = (CamelStreamFilter *)stream; struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); @@ -299,14 +305,13 @@ static void do_flush (CamelStream *stream) camel_mime_filter_complete(f->filter, buffer, len, presize, &buffer, &len, &presize); f = f->next; } - if (camel_stream_write(filter->source, buffer, len) == -1) { - g_warning("Flushing filter failed to write, no way to signal failure ..."); - } - - return camel_stream_flush(filter->source); + camel_stream_write(filter->source, buffer, len, ex); + if (!camel_exception_is_set(ex)) + camel_stream_flush(filter->source, ex); } -static gboolean do_eos (CamelStream *stream) +static gboolean +do_eos (CamelStream *stream) { CamelStreamFilter *filter = (CamelStreamFilter *)stream; struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); @@ -317,27 +322,15 @@ static gboolean do_eos (CamelStream *stream) return camel_stream_eos(filter->source); } -static void do_close (CamelStream *stream) -{ - CamelStreamFilter *filter = (CamelStreamFilter *)stream; - struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); - - if (p->last_was_read == 0) { - camel_stream_flush(stream); - } - - p->filteredlen = 0; -/* camel_stream_close(filter->source);*/ -} - -static void do_reset (CamelStream *stream) +static void +do_reset (CamelStream *stream, CamelException *ex) { CamelStreamFilter *filter = (CamelStreamFilter *)stream; struct _CamelStreamFilterPrivate *p = _PRIVATE(filter); struct _filter *f; p->filteredlen = 0; - camel_stream_reset(filter->source); + camel_stream_reset(filter->source, ex); /* and reset filters */ f = p->filters; diff --git a/camel/camel-stream-fs.c b/camel/camel-stream-fs.c index 4bd506b143..3f53b5907a 100644 --- a/camel/camel-stream-fs.c +++ b/camel/camel-stream-fs.c @@ -1,14 +1,14 @@ /* -*- 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 */ -/* + +/* * Authors: Bertrand Guiheneuf * Michael Zucchi * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * @@ -22,8 +22,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ + #include #include "camel-stream-fs.h" +#include "camel-exception.h" #include #include #include @@ -31,39 +33,34 @@ #include #include -static CamelSeekableStreamClass *parent_class=NULL; +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 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 off_t stream_seek (CamelSeekableStream *stream, off_t offset, CamelStreamSeekPolicy policy); +static int stream_read (CamelStream *stream, char *buffer, unsigned int n, + CamelException *ex); +static int stream_write (CamelStream *stream, const char *buffer, + unsigned int n, CamelException *ex); +static void stream_flush (CamelStream *stream, CamelException *ex); +static off_t stream_seek (CamelSeekableStream *stream, off_t offset, + CamelStreamSeekPolicy policy, + CamelException *ex); 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, 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) { - CamelSeekableStreamClass *camel_seekable_stream_class = CAMEL_SEEKABLE_STREAM_CLASS (camel_stream_fs_class); - CamelStreamClass *camel_stream_class = CAMEL_STREAM_CLASS (camel_stream_fs_class); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_stream_fs_class); + CamelSeekableStreamClass *camel_seekable_stream_class = + CAMEL_SEEKABLE_STREAM_CLASS (camel_stream_fs_class); + CamelStreamClass *camel_stream_class = + CAMEL_STREAM_CLASS (camel_stream_fs_class); + GtkObjectClass *gtk_object_class = + GTK_OBJECT_CLASS (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; - + /* virtual method overload */ camel_stream_class->read = stream_read; camel_stream_class->write = stream_write; @@ -75,11 +72,10 @@ camel_stream_fs_class_init (CamelStreamFsClass *camel_stream_fs_class) } static void -camel_stream_fs_init (gpointer object, gpointer klass) +camel_stream_fs_init (gpointer object, gpointer klass) { CamelStreamFs *stream = CAMEL_STREAM_FS (object); - stream->name = NULL; stream->fd = -1; } @@ -87,9 +83,9 @@ GtkType camel_stream_fs_get_type (void) { static GtkType camel_stream_fs_type = 0; - - if (!camel_stream_fs_type) { - GtkTypeInfo camel_stream_fs_info = + + if (!camel_stream_fs_type) { + GtkTypeInfo camel_stream_fs_info = { "CamelStreamFs", sizeof (CamelStreamFs), @@ -100,225 +96,210 @@ camel_stream_fs_get_type (void) /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; - + camel_stream_fs_type = gtk_type_unique (camel_seekable_stream_get_type (), &camel_stream_fs_info); } - + return camel_stream_fs_type; } -static void +static void 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); + if (stream_fs->fd != -1) + close (stream_fs->fd); GTK_OBJECT_CLASS (parent_class)->finalize (object); } -static void -init_with_fd (CamelStreamFs *stream_fs, int fd) +/** + * camel_stream_fs_new_with_fd: + * @fd: a file descriptor + * + * Returns a stream associated with the given file descriptor. + * When the stream is destroyed, the file descriptor will be closed. + * + * Return value: the stream + **/ +CamelStream * +camel_stream_fs_new_with_fd (int fd) { + CamelStreamFs *stream_fs; off_t offset; + stream_fs = gtk_type_new (camel_stream_fs_get_type ()); stream_fs->fd = fd; - offset = lseek(fd, 0, SEEK_CUR); + offset = lseek (fd, 0, SEEK_CUR); if (offset == -1) offset = 0; - ((CamelSeekableStream *)stream_fs)->position = offset; -} + CAMEL_SEEKABLE_STREAM (stream_fs)->position = offset; -static void -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); - camel_seekable_stream_set_bounds((CamelSeekableStream *)stream_fs, start, end); + return CAMEL_STREAM (stream_fs); } -static int -init_with_name (CamelStreamFs *stream_fs, const gchar *name, int flags, int mode) +/** + * camel_stream_fs_new_with_fd_and_bounds: + * @fd: a file descriptor + * @start: the first valid position in the file + * @end: the first invalid position in the file, or CAMEL_STREAM_UNBOUND + * + * Returns a stream associated with the given file descriptor and bounds. + * When the stream is destroyed, the file descriptor will be closed. + * + * Return value: the stream + **/ +CamelStream * +camel_stream_fs_new_with_fd_and_bounds (int fd, off_t start, off_t end, + CamelException *ex) { - int fd; - - g_assert(name); - g_assert(stream_fs); - - fd = open (name, flags, mode); - if (fd==-1) { - 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); - return 0; -} + CamelStream *stream; -static int -init_with_name_and_bounds (CamelStreamFs *stream_fs, const gchar *name, int flags, int mode, - off_t start, off_t end) -{ - 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; + stream = camel_stream_fs_new_with_fd (fd); + camel_seekable_stream_set_bounds (CAMEL_SEEKABLE_STREAM (stream), + start, end, ex); + + return stream; } /** * camel_stream_fs_new_with_name: - * @name: - * @mode: - * - * - * - * Return value: + * @name: a local filename + * @flags: flags as in open(2) + * @mode: a file mode + * @ex: a CamelException. + * + * Creates a new CamelStream corresponding to the named file, flags, + * and mode. If an error occurs, @ex will be set. + * + * Return value: the stream **/ CamelStream * -camel_stream_fs_new_with_name (const gchar *name, int flags, int mode) +camel_stream_fs_new_with_name (const char *name, int flags, mode_t mode, + CamelException *ex) { - CamelStreamFs *stream_fs; - stream_fs = gtk_type_new (camel_stream_fs_get_type ()); - if (CSFS_CLASS (stream_fs)->init_with_name (stream_fs, name, flags, mode) == -1) { - gtk_object_unref (GTK_OBJECT (stream_fs)); + CamelStream *stream; + int fd; + + fd = open (name, flags, mode); + if (fd == -1) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Could not open file %s: %s.", + name, g_strerror (errno)); return NULL; } - return (CamelStream *)stream_fs; + stream = camel_stream_fs_new_with_fd (fd); + + return stream; } /** * camel_stream_fs_new_with_name_and_bounds: - * @name: - * @mode: - * @inf_bound: - * @sup_bound: - * - * - * - * Return value: + * @name: a local filename + * @flags: flags as in open(2) + * @mode: a file mode + * @start: the first valid position in the file + * @end: the first invalid position in the file, or CAMEL_STREAM_UNBOUND + * @ex: a CamelException. + * + * Creates a new CamelStream corresponding to the given arguments. If + * an error occurs, @ex will be set. + * + * Return value: the stream **/ CamelStream * -camel_stream_fs_new_with_name_and_bounds (const gchar *name, int flags, int mode, - off_t start, off_t end) +camel_stream_fs_new_with_name_and_bounds (const char *name, int flags, + mode_t mode, off_t start, off_t end, + CamelException *ex) { - CamelStreamFs *stream_fs; - stream_fs = gtk_type_new (camel_stream_fs_get_type ()); - 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)); + CamelStream *stream; + + stream = camel_stream_fs_new_with_name (name, flags, mode, ex); + if (camel_exception_is_set (ex)) + return NULL; + + camel_seekable_stream_set_bounds (CAMEL_SEEKABLE_STREAM (stream), + start, end, ex); + if (camel_exception_is_set (ex)) { + gtk_object_unref (GTK_OBJECT (stream)); return NULL; } - - return (CamelStream *)stream_fs; -} -/** - * camel_stream_fs_new_with_fd: - * @fd: - * - * - * - * Return value: - **/ -CamelStream * -camel_stream_fs_new_with_fd (int fd) -{ - CamelStreamFs *stream_fs; - - stream_fs = gtk_type_new (camel_stream_fs_get_type ()); - CSFS_CLASS (stream_fs)->init_with_fd (stream_fs, fd); - - return CAMEL_STREAM (stream_fs); + return stream; } -/** - * 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, 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, start, end); - - return CAMEL_STREAM (stream_fs); -} -static gint -stream_read (CamelStream *stream, gchar *buffer, gint n) +static int +stream_read (CamelStream *stream, char *buffer, unsigned int n, + CamelException *ex) { CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream); - CamelSeekableStream *seekable = (CamelSeekableStream *)stream; - gint v; - - g_assert (n); + CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream); + int nread; if (seekable->bound_end != CAMEL_STREAM_UNBOUND) n = MIN (seekable->bound_end - seekable->position, n); do { - v = read ( stream_fs->fd, buffer, n); - } while (v == -1 && errno == EINTR); - - if (v>0) - seekable->position += v; + nread = read (stream_fs->fd, buffer, n); + } while (nread == -1 && errno == EINTR); - if (v == 0) + if (nread > 0) + seekable->position += nread; + else if (nread == 0) stream->eos = TRUE; + else { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Could not read from stream: %s", + g_strerror (errno)); + } - return v; + return nread; } -static gint -stream_write (CamelStream *stream, const gchar *buffer, gint n) +static int +stream_write (CamelStream *stream, const char *buffer, unsigned int n, + CamelException *ex) { CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream); - CamelSeekableStream *seekable = (CamelSeekableStream *)stream; - int v; - gint written = 0; - - g_assert (stream); - g_assert (stream_fs->fd != -1); - - if (n <= 0) - return 0; + CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream); + int v, written = 0; if (seekable->bound_end != CAMEL_STREAM_UNBOUND) n = MIN (seekable->bound_end - seekable->position, n); do { - v = write ( stream_fs->fd, buffer, n); - if (v>0) + v = write (stream_fs->fd, buffer, n); + if (v > 0) written += v; } while (v == -1 && errno == EINTR); - - if (written>0) + + if (written > 0) seekable->position += written; + else if (v == -1) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Could not write to stream: %s", + g_strerror (errno)); + } return written; } static void -stream_flush (CamelStream *stream) +stream_flush (CamelStream *stream, CamelException *ex) { - fsync ((CAMEL_STREAM_FS (stream))->fd); + if (fsync (CAMEL_STREAM_FS (stream)->fd) == -1) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Could not flush stream data: %s", + g_strerror (errno)); + } } static off_t -stream_seek (CamelSeekableStream *stream, off_t offset, CamelStreamSeekPolicy policy) +stream_seek (CamelSeekableStream *stream, off_t offset, + CamelStreamSeekPolicy policy, CamelException *ex) { CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream); off_t real = 0; @@ -335,29 +316,34 @@ stream_seek (CamelSeekableStream *stream, off_t offset, CamelStreamSeekPolicy po real = lseek(stream_fs->fd, offset, SEEK_END); if (real != -1) stream->position = real; + else { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Could not seek to " + "given offset: %s", + g_strerror (errno)); + } return real; } real = stream->bound_end + offset; break; - default: - errno = EINVAL; - return -1; } - if (stream->bound_end != CAMEL_STREAM_UNBOUND) { + 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) + if (real == -1) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Could not seek to given offset: %s", + g_strerror (errno)); return -1; + } if (real != stream->position && ((CamelStream *)stream)->eos) ((CamelStream *)stream)->eos = FALSE; stream->position = real; - + return real; } diff --git a/camel/camel-stream-fs.h b/camel/camel-stream-fs.h index 48428c58bd..1c40855143 100644 --- a/camel/camel-stream-fs.h +++ b/camel/camel-stream-fs.h @@ -1,15 +1,14 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* camel-stream-fs.h :stream based on unix filesystem */ -/* - * - * Author : +/* + * Author: * Bertrand Guiheneuf * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * @@ -50,26 +49,12 @@ struct _CamelStreamFs { CamelSeekableStream parent_object; - gchar *name; /* name of the underlying file */ - gint fd; /* file descriptor on the underlying file */ + int fd; /* file descriptor on the underlying file */ }; typedef struct { CamelSeekableStreamClass parent_class; - - /* Virtual methods */ - void (*init_with_fd) (CamelStreamFs *stream_fs, - int fd); - void (*init_with_fd_and_bounds) (CamelStreamFs *stream_fs, - int fd, off_t start, off_t end); - - int (*init_with_name) (CamelStreamFs *stream_fs, - const gchar *name, - int flags, int mode); - int (*init_with_name_and_bounds) (CamelStreamFs *stream_fs, - const gchar *name, - int flags, int mode, - off_t start, off_t end); + } CamelStreamFsClass; /* Standard Gtk function */ @@ -77,13 +62,20 @@ GtkType camel_stream_fs_get_type (void); /* public methods */ -CamelStream * camel_stream_fs_new_with_name (const gchar *name, int flags, int mode); -CamelStream * camel_stream_fs_new_with_name_and_bounds (const gchar *name, - int flags, int mode, - off_t start, off_t end); - -CamelStream * camel_stream_fs_new_with_fd (int fd); -CamelStream * camel_stream_fs_new_with_fd_and_bounds (int fd, off_t start, off_t end); +CamelStream * camel_stream_fs_new_with_name (const char *name, + int flags, + mode_t mode, + CamelException *ex); +CamelStream * camel_stream_fs_new_with_name_and_bounds (const char *name, + int flags, mode_t mode, + off_t start, + off_t end, + CamelException *ex); + +CamelStream * camel_stream_fs_new_with_fd (int fd); +CamelStream * camel_stream_fs_new_with_fd_and_bounds (int fd, off_t start, + off_t end, + CamelException *ex); #ifdef __cplusplus } diff --git a/camel/camel-stream-mem.c b/camel/camel-stream-mem.c index e34b274380..5d0fa7a39b 100644 --- a/camel/camel-stream-mem.c +++ b/camel/camel-stream-mem.c @@ -1,14 +1,14 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-stream-mem.c : memory buffer based stream - * inspired by gnome-stream-mem.c in bonobo by Miguel de Icaza - * +/* camel-stream-mem.c: memory buffer based stream */ + +/* * Authors: Bertrand Guiheneuf * Michael Zucchi * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * @@ -22,6 +22,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ + #include #include "camel-stream-mem.h" #include @@ -31,43 +32,47 @@ static CamelStreamClass *parent_class = NULL; -/* Returns the class for a CamelStreamMEM */ +/* Returns the class for a CamelStreamMem */ #define CSM_CLASS(so) CAMEL_STREAM_MEM_CLASS (GTK_OBJECT(so)->klass) -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 int stream_read (CamelStream *stream, char *buffer, unsigned int n, + CamelException *ex); +static int stream_write (CamelStream *stream, const char *buffer, + unsigned int n, CamelException *ex); static gboolean stream_eos (CamelStream *stream); -static off_t stream_seek (CamelSeekableStream *stream, off_t offset, CamelStreamSeekPolicy policy); +static off_t stream_seek (CamelSeekableStream *stream, off_t offset, + CamelStreamSeekPolicy policy, + CamelException *ex); static void finalize (GtkObject *object); static void camel_stream_mem_class_init (CamelStreamMemClass *camel_stream_mem_class) { - CamelSeekableStreamClass *camel_seekable_stream_class = CAMEL_SEEKABLE_STREAM_CLASS (camel_stream_mem_class); - CamelStreamClass *camel_stream_class = CAMEL_STREAM_CLASS (camel_stream_mem_class); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_stream_mem_class); - + CamelSeekableStreamClass *camel_seekable_stream_class = + CAMEL_SEEKABLE_STREAM_CLASS (camel_stream_mem_class); + CamelStreamClass *camel_stream_class = + CAMEL_STREAM_CLASS (camel_stream_mem_class); + GtkObjectClass *gtk_object_class = + GTK_OBJECT_CLASS (camel_stream_mem_class); + parent_class = gtk_type_class (camel_stream_get_type ()); - - /* virtual method definition */ - + /* virtual method overload */ camel_stream_class->read = stream_read; camel_stream_class->write = stream_write; - camel_stream_class->flush = stream_flush; camel_stream_class->eos = stream_eos; camel_seekable_stream_class->seek = stream_seek; - + gtk_object_class->finalize = finalize; } static void -camel_stream_mem_init (gpointer object, gpointer klass) +camel_stream_mem_init (gpointer object, gpointer klass) { CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (object); + stream_mem->owner = FALSE; stream_mem->buffer = 0; } @@ -76,9 +81,9 @@ GtkType camel_stream_mem_get_type (void) { static GtkType camel_stream_mem_type = 0; - - if (!camel_stream_mem_type) { - GtkTypeInfo camel_stream_mem_info = + + if (!camel_stream_mem_type) { + GtkTypeInfo camel_stream_mem_info = { "CamelStreamMem", sizeof (CamelStreamMem), @@ -89,10 +94,10 @@ camel_stream_mem_get_type (void) /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; - + camel_stream_mem_type = gtk_type_unique (camel_seekable_stream_get_type (), &camel_stream_mem_info); } - + return camel_stream_mem_type; } @@ -117,11 +122,11 @@ CamelStream * camel_stream_mem_new_with_byte_array (GByteArray *byte_array) { CamelStreamMem *stream_mem; - + stream_mem = gtk_type_new (camel_stream_mem_get_type ()); stream_mem->buffer = byte_array; stream_mem->owner = TRUE; - + return CAMEL_STREAM (stream_mem); } @@ -134,7 +139,8 @@ void camel_stream_mem_set_byte_array (CamelStreamMem *s, GByteArray *buffer) s->buffer = buffer; } -void camel_stream_mem_set_buffer (CamelStreamMem *s, const char *buffer, size_t len) +void camel_stream_mem_set_buffer (CamelStreamMem *s, const char *buffer, + size_t len) { GByteArray *ba; @@ -143,7 +149,7 @@ void camel_stream_mem_set_buffer (CamelStreamMem *s, const char *buffer, size_t camel_stream_mem_set_byte_array(s, ba); } -static void +static void finalize (GtkObject *object) { CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (object); @@ -154,71 +160,68 @@ finalize (GtkObject *object) GTK_OBJECT_CLASS (parent_class)->finalize (object); } -static gint -stream_read (CamelStream *stream, gchar *buffer, gint n) +static int +stream_read (CamelStream *stream, char *buffer, unsigned int n, + CamelException *ex) { CamelStreamMem *camel_stream_mem = CAMEL_STREAM_MEM (stream); - CamelSeekableStream *seekable = (CamelSeekableStream *)stream; - - g_assert (stream); + CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream); - if (seekable->bound_end != CAMEL_STREAM_UNBOUND) { + if (seekable->bound_end != CAMEL_STREAM_UNBOUND) n = MIN(seekable->bound_end - seekable->position, n); - } n = MIN (n, camel_stream_mem->buffer->len - seekable->position); - if (n>0) { - memcpy (buffer, (camel_stream_mem->buffer)->data + seekable->position, n); + if (n > 0) { + memcpy (buffer, camel_stream_mem->buffer->data + + seekable->position, n); seekable->position += n; - } else { + } else n = -1; - } return n; } -static gint -stream_write (CamelStream *stream, const gchar *buffer, gint n) +static int +stream_write (CamelStream *stream, const char *buffer, unsigned int n, + CamelException *ex) { CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (stream); - CamelSeekableStream *seekable = (CamelSeekableStream *)stream; + CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream); - g_assert (stream); - - if (seekable->bound_end != CAMEL_STREAM_UNBOUND) { + if (seekable->bound_end != CAMEL_STREAM_UNBOUND) n = MIN(seekable->bound_end - seekable->position, n); - } #warning "g_byte_arrays use g_malloc and so are totally unsuitable for this object" if (seekable->position == stream_mem->buffer->len) { - stream_mem->buffer = g_byte_array_append (stream_mem->buffer, (const guint8 *)buffer, n); + stream_mem->buffer = + g_byte_array_append (stream_mem->buffer, + (const guint8 *)buffer, n); } else { - g_byte_array_set_size(stream_mem->buffer, n+stream_mem->buffer->len); - memcpy(stream_mem->buffer->data + seekable->position, buffer, n); + g_byte_array_set_size (stream_mem->buffer, + n+stream_mem->buffer->len); + memcpy (stream_mem->buffer->data + seekable->position, + buffer, n); } seekable->position += n; - - return n; -} -static void -stream_flush (CamelStream *stream) -{ - /* Nothing to do. */ - return; + return n; } static gboolean stream_eos (CamelStream *stream) { - return ((CamelStreamMem *)stream)->buffer->len <= ((CamelSeekableStream *)stream)->position; + CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (stream); + CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream); + + return stream_mem->buffer->len <= seekable_stream->position; } static off_t -stream_seek (CamelSeekableStream *stream, off_t offset, CamelStreamSeekPolicy policy) +stream_seek (CamelSeekableStream *stream, off_t offset, + CamelStreamSeekPolicy policy, CamelException *ex) { off_t position; - CamelStreamMem *stream_mem = (CamelStreamMem *)stream; + CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (stream); switch (policy) { case CAMEL_STREAM_SET: @@ -230,24 +233,20 @@ stream_seek (CamelSeekableStream *stream, off_t offset, CamelStreamSeekPolicy po case CAMEL_STREAM_END: position = (stream_mem->buffer)->len + offset; break; - default: - errno = EINVAL; - return -1; } - if (stream->bound_end == CAMEL_STREAM_UNBOUND) { + if (stream->bound_end == CAMEL_STREAM_UNBOUND) position = MIN (position, stream->bound_end); - } - if (stream->bound_start == CAMEL_STREAM_UNBOUND) { + if (stream->bound_start == CAMEL_STREAM_UNBOUND) position = MAX (position, 0); - } else { + else position = MAX (position, stream->bound_start); - } if (position > stream_mem->buffer->len) { int oldlen = stream_mem->buffer->len; - g_byte_array_set_size(stream_mem->buffer, position); - memset(stream_mem->buffer->data + oldlen, 0, position - oldlen); + g_byte_array_set_size (stream_mem->buffer, position); + memset (stream_mem->buffer->data + oldlen, 0, + position - oldlen); } stream->position = position; diff --git a/camel/camel-stream-mem.h b/camel/camel-stream-mem.h index 6d108f111f..21f9a62e29 100644 --- a/camel/camel-stream-mem.h +++ b/camel/camel-stream-mem.h @@ -1,13 +1,14 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-stream-mem.h :stream based on memory buffer - * +/* camel-stream-mem.h: stream based on memory buffer */ + +/* * Authors: Bertrand Guiheneuf * Michael Zucchi * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * @@ -50,8 +51,8 @@ struct _CamelStreamMem typedef struct { CamelSeekableStreamClass parent_class; - - /* Virtual methods */ + + /* Virtual methods */ } CamelStreamMemClass; /* Standard Gtk function */ @@ -64,7 +65,8 @@ CamelStream *camel_stream_mem_new_with_buffer (const char *buffer, size_t len); /* these are really only here for implementing classes */ void camel_stream_mem_set_byte_array (CamelStreamMem *, GByteArray *buffer); -void camel_stream_mem_set_buffer (CamelStreamMem *, const char *buffer, size_t len); +void camel_stream_mem_set_buffer (CamelStreamMem *, const char *buffer, + size_t len); #ifdef __cplusplus } diff --git a/camel/camel-stream.c b/camel/camel-stream.c index 082789733d..07578a7848 100644 --- a/camel/camel-stream.c +++ b/camel/camel-stream.c @@ -1,16 +1,14 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* camel-stream.c : abstract class for a stream */ - -/* - * - * Author : +/* + * Author: * Bertrand Guiheneuf * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * @@ -24,71 +22,36 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ + #include #include "camel-stream.h" - -enum { - DATA_AVAILABLE, - LAST_SIGNAL -}; - -static guint camel_stream_signals[LAST_SIGNAL] = { 0 }; - static CamelObjectClass *parent_class = NULL; - /* Returns the class for a CamelStream */ #define CS_CLASS(so) CAMEL_STREAM_CLASS (GTK_OBJECT(so)->klass) -static void -default_camel_flush (CamelStream *stream) -{ - /* nothing */ -} - -static gboolean -eos (CamelStream *stream) -{ - return stream->eos; -} +static void stream_flush (CamelStream *stream, CamelException *ex); +static gboolean stream_eos (CamelStream *stream); static void camel_stream_class_init (CamelStreamClass *camel_stream_class) { - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_stream_class); - parent_class = gtk_type_class (camel_object_get_type ()); /* virtual method definition */ - camel_stream_class->read = NULL; - camel_stream_class->write = NULL; - camel_stream_class->flush = default_camel_flush; - camel_stream_class->eos = eos; - - /* virtual method overload */ - - /* signal definition */ - camel_stream_signals[DATA_AVAILABLE] = - gtk_signal_new ("data_available", - GTK_RUN_LAST, - gtk_object_class->type, - GTK_SIGNAL_OFFSET (CamelStreamClass, data_available), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (gtk_object_class, camel_stream_signals, LAST_SIGNAL); - + camel_stream_class->flush = stream_flush; + camel_stream_class->eos = stream_eos; } GtkType camel_stream_get_type (void) { static GtkType camel_stream_type = 0; - + if (!camel_stream_type) { - GtkTypeInfo camel_stream_info = + GtkTypeInfo camel_stream_info = { "CamelStream", sizeof (CamelStream), @@ -99,71 +62,103 @@ camel_stream_get_type (void) /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; - - camel_stream_type = gtk_type_unique (camel_object_get_type (), &camel_stream_info); + + camel_stream_type = gtk_type_unique (camel_object_get_type (), + &camel_stream_info); } - + return camel_stream_type; } /** - * camel_stream_read: + * camel_stream_read: * @stream: a CamelStream. * @buffer: buffer where bytes pulled from the stream are stored. * @n: max number of bytes to read. - * + * @ex: a CamelException + * * Read at most @n bytes from the @stream object and stores them * in the buffer pointed at by @buffer. - * - * Return value: number of bytes actually read. + * + * Return value: number of bytes actually read. If an error occurs, + * @ex will contain a description of the error. **/ -gint -camel_stream_read (CamelStream *stream, gchar *buffer, gint n) +int +camel_stream_read (CamelStream *stream, char *buffer, unsigned int n, + CamelException *ex) { - return CS_CLASS (stream)->read (stream, buffer, n); + g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); + g_return_val_if_fail (n == 0 || buffer, -1); + + return CS_CLASS (stream)->read (stream, buffer, n, ex); } /** - * camel_stream_write: + * camel_stream_write: * @stream: a CamelStream object. * @buffer: buffer to write. * @n: number of bytes to write + * @ex: a CamelException * * Write @n bytes from the buffer pointed at by @buffer into @stream. * - * Return value: the number of bytes actually written - * in the stream. + * Return value: the number of bytes actually written to the stream. If + * an error occurs, @ex will contain a description of the error. **/ -gint -camel_stream_write (CamelStream *stream, const gchar *buffer, gint n) +int +camel_stream_write (CamelStream *stream, const char *buffer, unsigned int n, + CamelException *ex) +{ + g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); + g_return_val_if_fail (n == 0 || buffer, -1); + + return CS_CLASS (stream)->write (stream, buffer, n, ex); +} + + +static void +stream_flush (CamelStream *stream, CamelException *ex) { - return CS_CLASS (stream)->write (stream, buffer, n); + /* nothing */ } /** * camel_stream_flush: * @stream: a CamelStream object - * - * Flushes the contents of the stream to its backing store. + * @ex: a CamelException + * + * Flushes the contents of the stream to its backing store. Only meaningful + * on writable streams. If an error occurs, @ex will be set. **/ void -camel_stream_flush (CamelStream *stream) +camel_stream_flush (CamelStream *stream, CamelException *ex) { - CS_CLASS (stream)->flush (stream); + g_return_if_fail (CAMEL_IS_STREAM (stream)); + + CS_CLASS (stream)->flush (stream, ex); +} + + +static gboolean +stream_eos (CamelStream *stream) +{ + return stream->eos; } /** - * camel_stream_eos: + * camel_stream_eos: * @stream: a CamelStream object - * + * * Test if there are bytes left to read on the @stream object. - * + * * Return value: %TRUE if all the contents on the stream has been read, or * %FALSE if information is still available. **/ gboolean camel_stream_eos (CamelStream *stream) { + g_return_val_if_fail (CAMEL_IS_STREAM (stream), TRUE); + return CS_CLASS (stream)->eos (stream); } @@ -171,67 +166,69 @@ camel_stream_eos (CamelStream *stream) /** * camel_stream_reset: reset a stream * @stream: the stream object - * - * Reset a stream, that is put it in a state - * where it can be read from the begining. - * All streams in camel are not seekable, - * but they must all be resettable. - * + * @ex: a CamelException + * + * Reset a stream. That is, put it in a state where it can be read + * from the beginning again. Not all streams in Camel are seekable, + * but they must all be resettable. **/ -void -camel_stream_reset (CamelStream *stream) -{ - CS_CLASS (stream)->reset (stream); +void +camel_stream_reset (CamelStream *stream, CamelException *ex) +{ + g_return_if_fail (CAMEL_IS_STREAM (stream)); + + CS_CLASS (stream)->reset (stream, ex); } /***************** Utility functions ********************/ /** - * came_stream_write_strings: - * @stream: a CamelStream object. - * @...: A %NULL terminated list of strings. + * camel_stream_write_string: + * @stream: a stream object + * @string: a string + * @ex: a CamelException * - * This is a utility function that writes the list of - * strings into the @stream object. + * Writes the string to the stream. * - * Returns number of successfully written bytes. - */ + * Return value: the number of characters output. + **/ int -camel_stream_write_strings (CamelStream *stream, ... ) +camel_stream_write_string (CamelStream *stream, const char *string, + CamelException *ex) { - va_list args; - const char *string; - int total = 0; - - va_start(args, stream); - string = va_arg (args, const char *); - - while (string) { - int ret = camel_stream_write_string (stream, string); - if (ret == -1) - return -1; - total += ret; - string = va_arg (args, char *); - } - va_end (args); - return total; + return camel_stream_write (stream, string, strlen (string), ex); } -int camel_stream_printf (CamelStream *stream, const char *fmt, ... ) +/** + * camel_stream_printf: + * @stream: a stream object + * @ex: a CamelException + * @fmt: a printf-style format string + * + * This printfs the given data to @stream. If an error occurs, @ex + * will be set. + * + * Return value: the number of characters output. + **/ +int +camel_stream_printf (CamelStream *stream, CamelException *ex, + const char *fmt, ... ) { va_list args; char *string; - int ret = 0; - - va_start(args, fmt); - /* sigh, this allocates ... */ - string = g_strdup_vprintf(fmt, args); - if (string) { - ret = camel_stream_write_string(stream, string); - g_free(string); - } - va_end(args); + int ret; + g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); + + va_start (args, fmt); + string = g_strdup_vprintf (fmt, args); + va_end (args); + + if (!string) + return -1; + + ret = camel_stream_write (stream, string, strlen (string), ex); + g_free (string); return ret; } @@ -239,40 +236,37 @@ int camel_stream_printf (CamelStream *stream, const char *fmt, ... ) * camel_stream_write_to_stream: * @stream: Source CamelStream. * @output_stream: Destination CamelStream. - * + * @ex: a CamelException. + * * Write all of a stream (until eos) into another stream, in a blocking * fashion. * - * Return Value: Returns -1 on error, or the number of bytes succesfully + * Return value: Returns -1 on error, or the number of bytes succesfully * copied across streams. **/ int -camel_stream_write_to_stream (CamelStream *stream, - CamelStream *output_stream) +camel_stream_write_to_stream (CamelStream *stream, CamelStream *output_stream, + CamelException *ex) { - gchar tmp_buf[4096]; + char tmp_buf[4096]; int total = 0; - gint nb_read; - gint nb_written; - - /* - * default implementation that uses the input - * stream and stream it in a blocking way - * to an output stream. - */ - g_assert (output_stream); - g_assert (stream); - - while (!camel_stream_eos (CAMEL_STREAM (stream))) { - nb_read = camel_stream_read (CAMEL_STREAM (stream), tmp_buf, 4096); + int nb_read; + int nb_written; + + g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); + g_return_val_if_fail (CAMEL_IS_STREAM (output_stream), -1); + + while (!camel_stream_eos (stream)) { + nb_read = camel_stream_read (stream, tmp_buf, + sizeof (tmp_buf), ex); if (nb_read < 0) return -1; - else if (nb_read>0) { + else if (nb_read > 0) { nb_written = 0; - + while (nb_written < nb_read) { - int len = camel_stream_write (output_stream, tmp_buf + nb_written, nb_read - nb_written); - if (len<0) + int len = camel_stream_write (output_stream, tmp_buf + nb_written, nb_read - nb_written, ex); + if (len < 0) return -1; nb_written += len; } diff --git a/camel/camel-stream.h b/camel/camel-stream.h index c2b91d0e6a..c1a044e68f 100644 --- a/camel/camel-stream.h +++ b/camel/camel-stream.h @@ -1,15 +1,14 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* camel-stream.h : class for an abstract stream */ -/* - * - * Author : +/* + * Author: * Bertrand Guiheneuf * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * @@ -35,6 +34,7 @@ extern "C" { #endif /* __cplusplus }*/ #include +#include #define CAMEL_STREAM_TYPE (camel_stream_get_type ()) #define CAMEL_STREAM(obj) (GTK_CHECK_CAST((obj), CAMEL_STREAM_TYPE, CamelStream)) @@ -45,49 +45,53 @@ struct _CamelStream { CamelObject parent_object; - gboolean eos; /* end of stream indicator, for use by implementing classes */ + gboolean eos; }; typedef struct { CamelObjectClass parent_class; - - /* Virtual methods */ - - void (*data_available) (CamelStream *stream); /* default "data_available" signal handler */ - - gint (*read) (CamelStream *stream, gchar *buffer, gint n); - gint (*write) (CamelStream *stream, const gchar *buffer, gint n); - void (*flush) (CamelStream *stream); + + /* Virtual methods */ + + int (*read) (CamelStream *stream, char *buffer, + unsigned int n, CamelException *ex); + int (*write) (CamelStream *stream, const char *buffer, + unsigned int n, CamelException *ex); + void (*flush) (CamelStream *stream, CamelException *ex); gboolean (*eos) (CamelStream *stream); - void (*reset) (CamelStream *stream); + void (*reset) (CamelStream *stream, CamelException *ex); + } CamelStreamClass; /* Standard Gtk function */ GtkType camel_stream_get_type (void); /* public methods */ -gint camel_stream_read (CamelStream *stream, gchar *buffer, gint n); -gint camel_stream_write (CamelStream *stream, const gchar *buffer, gint n); -void camel_stream_flush (CamelStream *stream); -gboolean camel_stream_eos (CamelStream *stream); -void camel_stream_reset (CamelStream *stream); +int camel_stream_read (CamelStream *stream, char *buffer, + unsigned int n, CamelException *ex); +int camel_stream_write (CamelStream *stream, const char *buffer, + unsigned int n, CamelException *ex); +void camel_stream_flush (CamelStream *stream, CamelException *ex); +gboolean camel_stream_eos (CamelStream *stream); +void camel_stream_reset (CamelStream *stream, CamelException *ex); /* utility macros and funcs */ -#define camel_stream_write_string(stream, string) (camel_stream_write ((stream), (string), strlen (string))) -int camel_stream_write_strings (CamelStream *stream, ... ); -int camel_stream_printf (CamelStream *stream, const char *fmt, ... ) G_GNUC_PRINTF (2, 3); - -/* write a whole stream to another stream, until eof or error on either stream */ -int camel_stream_write_to_stream (CamelStream *stream, CamelStream *output_stream); +int camel_stream_write_string (CamelStream *stream, const char *string, + CamelException *ex); +int camel_stream_printf (CamelStream *stream, CamelException *ex, + const char *fmt, ... ) G_GNUC_PRINTF (3, 4); +int camel_stream_vprintf (CamelStream *stream, CamelException *ex, + const char *fmt, va_list ap); + +/* Write a whole stream to another stream, until eof or error on + * either stream. + */ +int camel_stream_write_to_stream (CamelStream *stream, + CamelStream *output_stream, + CamelException *ex); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* CAMEL_STREAM_H */ - - - - - - diff --git a/camel/gmime-content-field.c b/camel/gmime-content-field.c index 53d5135c23..ce61cf2a84 100644 --- a/camel/gmime-content-field.c +++ b/camel/gmime-content-field.c @@ -130,7 +130,8 @@ gmime_content_field_write_to_stream (GMimeContentField *content_field, CamelStre txt = header_content_type_format(content_field->content_type); if (txt) { - camel_stream_write_strings (stream, "Content-Type: ", txt, "\n", NULL); + /* FIXME. Shouldn't pass NULL for CamelException. */ + camel_stream_printf (stream, NULL, "Content-Type: %s\n", txt); g_free(txt); } } diff --git a/camel/md5-utils.c b/camel/md5-utils.c index 7363eaec40..382aadffec 100644 --- a/camel/md5-utils.c +++ b/camel/md5-utils.c @@ -335,10 +335,11 @@ md5_get_digest_from_stream (CamelStream *stream, guchar digest[16]) md5_init (&ctx); - nb_bytes_read = camel_stream_read (stream, tmp_buf, 1024); + /* FIXME (the NULL) */ + nb_bytes_read = camel_stream_read (stream, tmp_buf, 1024, NULL); while (nb_bytes_read) { md5_update (&ctx, tmp_buf, nb_bytes_read); - nb_bytes_read = camel_stream_read (stream, tmp_buf, 1024); + nb_bytes_read = camel_stream_read (stream, tmp_buf, 1024, NULL); } md5_final (&ctx, digest); diff --git a/camel/providers/Makefile.am b/camel/providers/Makefile.am index 7c520a8b8b..a1af905e6b 100644 --- a/camel/providers/Makefile.am +++ b/camel/providers/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = mbox pop3 sendmail smtp +SUBDIRS = mbox pop3 sendmail # these ones are disabled for the moment. -# MH maildir imap smtp +# MH maildir nntp smtp diff --git a/camel/providers/mbox/camel-mbox-folder.c b/camel/providers/mbox/camel-mbox-folder.c index 255753b140..5cc4cb3efd 100644 --- a/camel/providers/mbox/camel-mbox-folder.c +++ b/camel/providers/mbox/camel-mbox-folder.c @@ -721,11 +721,11 @@ mbox_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelExcept if (stat(mbox_folder->folder_file_path, &st) != 0) goto fail; - output_stream = camel_stream_fs_new_with_name (mbox_folder->folder_file_path, O_RDWR, 0600); + output_stream = camel_stream_fs_new_with_name (mbox_folder->folder_file_path, O_RDWR, 0600, ex); if (output_stream == NULL) goto fail; - seek = camel_seekable_stream_seek((CamelSeekableStream *)output_stream, st.st_size, SEEK_SET); + seek = camel_seekable_stream_seek((CamelSeekableStream *)output_stream, st.st_size, SEEK_SET, ex); if (seek != st.st_size) goto fail; @@ -737,23 +737,21 @@ mbox_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelExcept g_free(xev); /* we must write this to the non-filtered stream ... */ - if (camel_stream_write_string (output_stream, "From - \n") == -1) + if (camel_stream_write_string (output_stream, "From - \n", ex) == -1) goto fail; /* and write the content to the filtering stream, that translated '\nFrom' into '\n>From' */ filter_stream = (CamelStream *)camel_stream_filter_new_with_stream(output_stream); filter_from = (CamelMimeFilter *)camel_mime_filter_from_new(); camel_stream_filter_add((CamelStreamFilter *)filter_stream, filter_from); - if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), filter_stream) == -1) - goto fail; + camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), + filter_stream, ex); + if (!camel_exception_is_set (ex)) + camel_stream_flush (filter_stream, ex); -#warning WE NEED A STREAM CLOSE OR THIS WILL FAIL TO WORK -#warning WE NEED A STREAM CLOSE OR THIS WILL FAIL TO WORK -#warning WE NEED A STREAM CLOSE OR THIS WILL FAIL TO WORK -#warning WE NEED A STREAM CLOSE OR THIS WILL FAIL TO WORK + if (camel_exception_is_set (ex)) + goto fail; - /* FIXME: stream_close doesn't return anything */ -/* camel_stream_close (filter_stream);*/ gtk_object_unref (GTK_OBJECT (filter_stream)); /* force a summary update - will only update from the new position, if it can */ @@ -761,9 +759,15 @@ mbox_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelExcept return; fail: - camel_exception_setv (ex, - CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, /* FIXME: what code? */ - "Cannot append to mbox file: %s", strerror (errno)); + if (camel_exception_is_set (ex)) { + camel_exception_setv (ex, camel_exception_get_id (ex), + "Cannot append message to mbox file: %s", + camel_exception_get_description (ex)); + } else { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Cannot append message to mbox file: %s", + g_strerror (errno)); + } if (filter_stream) { /*camel_stream_close (filter_stream);*/ gtk_object_unref ((GtkObject *)filter_stream); @@ -861,7 +865,7 @@ mbox_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException * g_assert(info->frompos != -1); /* where we read from */ - message_stream = camel_stream_fs_new_with_name (mbox_folder->folder_file_path, O_RDONLY, 0); + message_stream = camel_stream_fs_new_with_name (mbox_folder->folder_file_path, O_RDONLY, 0, ex); if (message_stream == NULL) goto fail; @@ -900,9 +904,15 @@ mbox_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException * return message; fail: - camel_exception_setv (ex, - CAMEL_EXCEPTION_FOLDER_INVALID_UID, - "Cannot get message: %s", strerror(errno)); + if (camel_exception_is_set (ex)) { + camel_exception_setv (ex, camel_exception_get_id (ex), + "Cannot get message: %s", + camel_exception_get_description (ex)); + } else { + camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, + "Cannot get message: %s", + g_strerror(errno)); + } if (parser) gtk_object_unref((GtkObject *)parser); if (message_stream) diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c index bb2c7de6e1..838f247ac6 100644 --- a/camel/providers/pop3/camel-pop3-folder.c +++ b/camel/providers/pop3/camel-pop3-folder.c @@ -196,12 +196,13 @@ get_message_by_number (CamelFolder *folder, gint number, CamelException *ex) } g_free (result); - body = camel_pop3_command_get_additional_data (CAMEL_POP3_STORE (folder->parent_store)); + body = camel_pop3_command_get_additional_data (CAMEL_POP3_STORE (folder->parent_store), ex); if (!body) { CamelService *service = CAMEL_SERVICE (folder->parent_store); camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, "Could not retrieve message from POP " - "server %s.", service->url->host); + "server %s: %s", service->url->host, + camel_exception_get_description (ex)); return NULL; } diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c index 9ae87ad420..ddddf9f59f 100644 --- a/camel/providers/pop3/camel-pop3-store.c +++ b/camel/providers/pop3/camel-pop3-store.c @@ -376,14 +376,15 @@ pop3_connect (CamelService *service, CamelException *ex) CAMEL_STREAM_BUFFER_READ); /* Read the greeting, note APOP timestamp, if any. */ - buf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream)); + buf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream), ex); if (!buf) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - "Could not read greeting from POP " - "server."); - return FALSE; + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + "Could not read greeting from POP " + "server: %s", + camel_exception_get_description (ex)); gtk_object_unref (GTK_OBJECT (store->ostream)); gtk_object_unref (GTK_OBJECT (store->istream)); + return FALSE; } apoptime = strchr (buf, '<'); apopend = apoptime ? strchr (apoptime, '>') : NULL; @@ -512,18 +513,30 @@ camel_pop3_command (CamelPop3Store *store, char **ret, char *fmt, ...) char *cmdbuf, *respbuf; va_list ap; int status; + CamelException *ex = camel_exception_new (); va_start (ap, fmt); cmdbuf = g_strdup_vprintf (fmt, ap); va_end (ap); /* Send the command */ - camel_stream_write (store->ostream, cmdbuf, strlen (cmdbuf)); + camel_stream_printf (store->ostream, ex, "%s\r\n", cmdbuf); g_free (cmdbuf); - camel_stream_write (store->ostream, "\r\n", 2); + if (camel_exception_is_set (ex)) { + if (*ret) + *ret = g_strdup (camel_exception_get_description (ex)); + camel_exception_free (ex); + return CAMEL_POP3_FAIL; + } /* Read the response */ - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream)); + respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream), ex); + if (camel_exception_is_set (ex)) { + if (*ret) + *ret = g_strdup (camel_exception_get_description (ex)); + camel_exception_free (ex); + return CAMEL_POP3_FAIL; + } if (!strncmp (respbuf, "+OK", 3)) status = CAMEL_POP3_OK; else if (!strncmp (respbuf, "-ERR", 4)) @@ -559,7 +572,8 @@ camel_pop3_command (CamelPop3Store *store, char **ret, char *fmt, ...) * Return value: the data, which the caller must free. **/ char * -camel_pop3_command_get_additional_data (CamelPop3Store *store) +camel_pop3_command_get_additional_data (CamelPop3Store *store, + CamelException *ex) { CamelStreamBuffer *stream = CAMEL_STREAM_BUFFER (store->istream); GPtrArray *data; @@ -568,7 +582,7 @@ camel_pop3_command_get_additional_data (CamelPop3Store *store) data = g_ptr_array_new (); while (1) { - buf = camel_stream_buffer_read_line (stream); + buf = camel_stream_buffer_read_line (stream, ex); if (!buf) { status = CAMEL_POP3_FAIL; break; diff --git a/camel/providers/pop3/camel-pop3-store.h b/camel/providers/pop3/camel-pop3-store.h index a4373a884a..e68f0fd142 100644 --- a/camel/providers/pop3/camel-pop3-store.h +++ b/camel/providers/pop3/camel-pop3-store.h @@ -66,7 +66,8 @@ void camel_pop3_store_close (CamelPop3Store *store, gboolean expunge, /* support functions */ enum { CAMEL_POP3_OK, CAMEL_POP3_ERR, CAMEL_POP3_FAIL }; int camel_pop3_command (CamelPop3Store *store, char **ret, char *fmt, ...); -char *camel_pop3_command_get_additional_data (CamelPop3Store *store); +char *camel_pop3_command_get_additional_data (CamelPop3Store *store, + CamelException *ex); /* Standard Gtk function */ GtkType camel_pop3_store_get_type (void); diff --git a/camel/providers/sendmail/camel-sendmail-transport.c b/camel/providers/sendmail/camel-sendmail-transport.c index fad9d9681d..1352d652a7 100644 --- a/camel/providers/sendmail/camel-sendmail-transport.c +++ b/camel/providers/sendmail/camel-sendmail-transport.c @@ -139,9 +139,17 @@ _send_internal (CamelMedium *message, char **argv, CamelException *ex) /* Parent process. Write the message out. */ close (fd[0]); out = camel_stream_fs_new_with_fd (fd[1]); - camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), out); - camel_stream_flush (out); + camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), + out, ex); + if (!camel_exception_is_set (ex)) + camel_stream_flush (out, ex); gtk_object_unref (GTK_OBJECT (out)); + if (camel_exception_is_set (ex)) { + camel_exception_setv (ex, camel_exception_get_id (ex), + "Could not send message: %s", + camel_exception_get_description (ex)); + return FALSE; + } /* Wait for sendmail to exit. */ while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR) -- cgit v1.2.3