static CamelMimeMessage *
mbox_folder_get_message_sync (CamelFolder *folder,
                              const gchar *uid,
                              GCancellable *cancellable,
                              GError **error)
{
	CamelLocalFolder *lf = (CamelLocalFolder *) folder;
	CamelMimeMessage *message = NULL;
	CamelMboxMessageInfo *info;
	CamelMimeParser *parser = NULL;
	gint fd, retval;
	gint retried = FALSE;
	goffset frompos;

	d (printf ("Getting message %s\n", uid));

	/* lock the folder first, burn if we can't, need write lock for summary check */
	if (camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1)
		return NULL;

	/* check for new messages always */
	if (camel_local_summary_check ((CamelLocalSummary *) folder->summary, lf->changes, cancellable, error) == -1) {
		camel_local_folder_unlock (lf);
		return NULL;
	}

retry:
	/* get the message summary info */
	info = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid);

	if (info == NULL) {
		set_cannot_get_message_ex (
			error, CAMEL_FOLDER_ERROR_INVALID_UID,
			uid, lf->folder_path, _("No such message"));
		goto fail;
	}

	if (info->frompos == -1) {
		camel_message_info_unref (info);
		goto fail;
	}

	frompos = info->frompos;
	camel_message_info_unref (info);

	/* we use an fd instead of a normal stream here - the reason is subtle, camel_mime_part will cache
	 * the whole message in memory if the stream is non-seekable (which it is when built from a parser
	 * with no stream).  This means we dont have to lock the mbox for the life of the message, but only
	 * while it is being created. */

	fd = g_open (lf->folder_path, O_LARGEFILE | O_RDONLY | O_BINARY, 0);
	if (fd == -1) {
		set_cannot_get_message_ex (
			error, CAMEL_ERROR_GENERIC,
			uid, lf->folder_path, g_strerror (errno));
		goto fail;
	}

	/* we use a parser to verify the message is correct, and in the correct position */
	parser = camel_mime_parser_new ();
	camel_mime_parser_init_with_fd (parser, fd);
	camel_mime_parser_scan_from (parser, TRUE);

	camel_mime_parser_seek (parser, frompos, SEEK_SET);
	if (camel_mime_parser_step (parser, NULL, NULL) != CAMEL_MIME_PARSER_STATE_FROM
	    || camel_mime_parser_tell_start_from (parser) != frompos) {

		g_warning ("Summary doesn't match the folder contents!  eek!\n"
			"  expecting offset %ld got %ld, state = %d", (glong) frompos,
			(glong) camel_mime_parser_tell_start_from (parser),
			camel_mime_parser_state (parser));

		g_object_unref (parser);
		parser = NULL;

		if (!retried) {
			retried = TRUE;
			camel_local_summary_check_force ((CamelLocalSummary *) folder->summary);
			retval = camel_local_summary_check ((CamelLocalSummary *) folder->summary, lf->changes, cancellable, error);
			if (retval != -1)
				goto retry;
		}

		set_cannot_get_message_ex (
			error, CAMEL_FOLDER_ERROR_INVALID,
			uid, lf->folder_path,
			_("The folder appears to be irrecoverably corrupted."));
		goto fail;
	}

	message = camel_mime_message_new ();
	if (!camel_mime_part_construct_from_parser_sync (
		(CamelMimePart *) message, parser, cancellable, error)) {
		g_prefix_error (
			error, _("Cannot get message %s from folder %s: "),
			uid, lf->folder_path);
		g_object_unref (message);
		message = NULL;
		goto fail;
	}

	camel_medium_remove_header ((CamelMedium *) message, "X-Evolution");

fail:
	/* and unlock now we're finished with it */
	camel_local_folder_unlock (lf);

	if (parser)
		g_object_unref (parser);

	/* use the opportunity to notify of changes (particularly if we had a rebuild) */
	if (camel_folder_change_info_changed (lf->changes)) {
		camel_folder_changed (folder, lf->changes);
		camel_folder_change_info_clear (lf->changes);
	}

	return message;
}
/* Well, since Solaris is a tad broken wrt its 'mbox' folder format,
 * we must convert it to a real mbox format.  Thankfully this is
 * mostly pretty easy */
static gint
camel_movemail_solaris (gint oldsfd,
                        gint dfd,
                        GError **error)
{
    CamelMimeParser *mp;
    gchar *buffer;
    gint len;
    gint sfd;
    CamelMimeFilter *ffrom;
    gint ret = 1;
    gchar *from = NULL;

    /* need to dup as the mime parser will close on finish */
    sfd = dup (oldsfd);
    if (sfd == -1) {
        g_set_error (
            error, G_IO_ERROR,
            g_io_error_from_errno (errno),
            _("Error copying mail temp file: %s"),
            g_strerror (errno));
        return -1;
    }

    mp = camel_mime_parser_new ();
    camel_mime_parser_scan_from (mp, TRUE);
    camel_mime_parser_init_with_fd (mp, sfd);

    ffrom = camel_mime_filter_from_new ();

    while (camel_mime_parser_step (mp, &buffer, &len) == CAMEL_MIME_PARSER_STATE_FROM) {
        g_return_val_if_fail (camel_mime_parser_from_line (mp), -1);
        from = g_strdup (camel_mime_parser_from_line (mp));
        if (camel_mime_parser_step (mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_FROM_END) {
            CamelNameValueArray *headers;
            const gchar *cl;
            gint length;
            gint start, body;
            goffset newpos;

            ret = 0;

            start = camel_mime_parser_tell_start_from (mp);
            body = camel_mime_parser_tell (mp);

            if (write (dfd, from, strlen (from)) != strlen (from))
                goto fail;

            /* write out headers, but NOT content-length header */
            headers = camel_mime_parser_dup_headers (mp);
            if (solaris_header_write (dfd, headers) == -1) {
                camel_name_value_array_free (headers);
                goto fail;
            }

            camel_name_value_array_free (headers);
            cl = camel_mime_parser_header (mp, "content-length", NULL);
            if (cl == NULL) {
                g_warning ("Required Content-Length header is missing from solaris mail box @ %d", (gint) camel_mime_parser_tell (mp));
                camel_mime_parser_drop_step (mp);
                camel_mime_parser_drop_step (mp);
                camel_mime_parser_step (mp, &buffer, &len);
                camel_mime_parser_unstep (mp);
                length = camel_mime_parser_tell_start_from (mp) - body;
                newpos = -1;
            } else {
                length = atoi (cl);
                camel_mime_parser_drop_step (mp);
                camel_mime_parser_drop_step (mp);
                newpos = length + body;
            }
            /* copy body->length converting From lines */
            if (camel_movemail_copy_filter (sfd, dfd, body, length, ffrom) == -1)
                goto fail;
            if (newpos != -1)
                camel_mime_parser_seek (mp, newpos, SEEK_SET);
        } else {
            g_error ("Inalid parser state: %d", camel_mime_parser_state (mp));
        }
        g_free (from);
    }

    g_object_unref (mp);
    g_object_unref (ffrom);

    return ret;

fail:
    g_free (from);

    g_set_error (
        error, G_IO_ERROR,
        g_io_error_from_errno (errno),
        _("Error copying mail temp file: %s"),
        g_strerror (errno));

    g_object_unref (mp);
    g_object_unref (ffrom);

    return -1;
}