Exemple #1
0
static int i_stream_metawrap_stat(struct istream_private *stream, bool exact)
{
	struct metawrap_istream *mstream = (struct metawrap_istream *)stream;
	const struct stat *st;
	int ret;

	if (i_stream_stat(stream->parent, exact, &st) < 0) {
		stream->istream.stream_errno = stream->parent->stream_errno;
		return -1;
	}
	stream->statbuf = *st;

	if (mstream->in_metadata) {
		ret = i_stream_read(&stream->istream);
		if (ret < 0 && stream->istream.stream_errno != 0)
			return -1;
		if (ret == 0) {
			stream->statbuf.st_size = -1;
			return 0;
		}
	}
	i_assert((uoff_t)stream->statbuf.st_size >= mstream->start_offset);
	stream->statbuf.st_size -= mstream->start_offset;
	return 0;
}
Exemple #2
0
static const struct stat *
i_stream_bzlib_stat(struct istream_private *stream, bool exact)
{
	struct bzlib_istream *zstream = (struct bzlib_istream *) stream;
	const struct stat *st;
	size_t size;

	st = i_stream_stat(stream->parent, exact);
	if (st == NULL)
		return NULL;

	if (zstream->eof_offset == (uoff_t)-1 && !exact)
		return st;

	stream->statbuf = *st;
	if (zstream->eof_offset == (uoff_t)-1) {
		uoff_t old_offset = stream->istream.v_offset;

		do {
			(void)i_stream_get_data(&stream->istream, &size);
			i_stream_skip(&stream->istream, size);
		} while (i_stream_read(&stream->istream) > 0);

		i_stream_seek(&stream->istream, old_offset);
		if (zstream->eof_offset == (uoff_t)-1)
			return NULL;
	}
	stream->statbuf.st_size = zstream->eof_offset;
	return &stream->statbuf;
}
Exemple #3
0
static int
i_stream_base64_encoder_stat(struct istream_private *stream,
	bool exact ATTR_UNUSED)
{
	struct base64_encoder_istream *bstream =
		(struct base64_encoder_istream *)stream;
	const struct stat *st;
	off_t newlines, size;

	if (i_stream_stat(stream->parent, exact, &st) < 0) {
		stream->istream.stream_errno = stream->parent->stream_errno;
		return -1;
	}

	stream->statbuf = *st;
	if (st->st_size == 0)
		return 0;
	
	/* calculate size of encoded data */
	size = (st->st_size / 3) * 4 +
		((st->st_size % 3) == 0 ? 0 : 4);

	/* update size with added newlines */
	newlines = (size / bstream->chars_per_line - 1) +
		((size % bstream->chars_per_line) == 0 ? 0 : 1);
	size += newlines * (bstream->crlf ? 2 : 1);

	stream->statbuf.st_size = size;
	return 0;
}
static int raw_mail_stat(struct mail *mail)
{
	struct raw_mailbox *mbox = (struct raw_mailbox *)mail->box;
	const struct stat *st;

	if (mail->lookup_abort == MAIL_LOOKUP_ABORT_NOT_IN_CACHE) {
		mail_set_aborted(mail);
		return -1;
	}

	mail->transaction->stats.fstat_lookup_count++;
	if (i_stream_stat(mail->box->input, TRUE, &st) < 0) {
		mail_storage_set_critical(mail->box->storage,
					  "stat(%s) failed: %m",
					  i_stream_get_name(mail->box->input));
		return -1;
	}

	if (mbox->mtime != (time_t)-1)
		mbox->mtime = st->st_mtime;
	if (mbox->ctime != (time_t)-1)
		mbox->ctime = st->st_ctime;
	mbox->size = st->st_size;
	return 0;
}
Exemple #5
0
static const struct stat *
i_stream_tee_stat(struct istream_private *stream, bool exact)
{
	struct tee_child_istream *tstream = (struct tee_child_istream *)stream;

	return i_stream_stat(tstream->tee->input, exact);
}
static int
i_stream_lzma_stat(struct istream_private *stream, bool exact)
{
	struct lzma_istream *zstream = (struct lzma_istream *) stream;
	const struct stat *st;
	size_t size;

	if (i_stream_stat(stream->parent, exact, &st) < 0) {
		stream->istream.stream_errno = stream->parent->stream_errno;
		return -1;
	}
	stream->statbuf = *st;

	/* when exact=FALSE always return the parent stat's size, even if we
	   know the exact value. this is necessary because otherwise e.g. mbox
	   code can see two different values and think that a compressed mbox
	   file keeps changing. */
	if (!exact)
		return 0;

	if (zstream->stream_size == (uoff_t)-1) {
		uoff_t old_offset = stream->istream.v_offset;

		do {
			size = i_stream_get_data_size(&stream->istream);
			i_stream_skip(&stream->istream, size);
		} while (i_stream_read(&stream->istream) > 0);

		i_stream_seek(&stream->istream, old_offset);
		if (zstream->stream_size == (uoff_t)-1)
			return -1;
	}
	stream->statbuf.st_size = zstream->stream_size;
	return 0;
}
Exemple #7
0
static bool fs_sis_try_link(struct sis_fs_file *file)
{
	const char *path = fs_file_path(&file->file);
	const struct stat *st;
	struct stat st2;

	st = i_stream_stat(file->hash_input, FALSE);

	/* we can use the existing file */
	if (fs_link(file->super->fs, file->hash_path, path) < 0) {
		if (errno != ENOENT && errno != EMLINK)
			i_error("fs-sis: %s", fs_last_error(file->super->fs));
		/* failed to use link(), continue as if it hadn't been equal */
		return FALSE;
	}
	if (fs_stat(file->super->fs, path, &st2) < 0) {
		i_error("fs-sis: %s", fs_last_error(file->super->fs));
		if (fs_unlink(file->super->fs, path) < 0)
			i_error("fs-sis: %s", fs_last_error(file->super->fs));
		return FALSE;
	}
	if (st->st_ino != st2.st_ino) {
		/* the hashes/ file was already replaced with something else */
		if (fs_unlink(file->super->fs, path) < 0)
			i_error("fs-sis: %s", fs_last_error(file->super->fs));
		return FALSE;
	}
	return TRUE;
}
static const struct stat *
i_stream_base64_encoder_stat(struct istream_private *stream, bool exact)
{
	if (exact) {
		/* too much trouble to implement until it's actually needed */
		i_panic("istream-base64-encoder: "
			"stat() doesn't support getting exact size");
	}
	return i_stream_stat(stream->parent, exact);
}
Exemple #9
0
static int
i_stream_tee_stat(struct istream_private *stream, bool exact)
{
	struct tee_child_istream *tstream = (struct tee_child_istream *)stream;
	const struct stat *st;

	if (i_stream_stat(tstream->tee->input, exact, &st) < 0)
		return -1;
	stream->statbuf = *st;
	return 0;
}
static int quoted_string_istream_stat
(struct istream_private *stream, bool exact)
{
	const struct stat *st;

	if (i_stream_stat(stream->parent, exact, &st) < 0)
		return -1;

	stream->statbuf = *st;
	return 0;
}
Exemple #11
0
static void
maildir_mail_remove_sizes_from_filename(struct mail *mail,
					enum mail_fetch_field field)
{
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
	struct mail_private *pmail = (struct mail_private *)mail;
	enum maildir_uidlist_rec_flag flags;
	const char *fname;
	uoff_t size;
	struct maildir_size_fix_ctx ctx;

	if (mbox->storage->set->maildir_broken_filename_sizes) {
		/* never try to fix sizes in maildir filenames */
		return;
	}

	if (maildir_sync_lookup(mbox, mail->uid, &flags, &fname) <= 0)
		return;
	if (strchr(fname, MAILDIR_EXTRA_SEP) == NULL)
		return;

	memset(&ctx, 0, sizeof(ctx));
	ctx.physical_size = (uoff_t)-1;
	if (field == MAIL_FETCH_VIRTUAL_SIZE &&
	    maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
				      &size)) {
		ctx.wrong_key = 'W';
	} else if (field == MAIL_FETCH_PHYSICAL_SIZE &&
		   maildir_filename_get_size(fname, MAILDIR_EXTRA_FILE_SIZE,
					     &size)) {
		ctx.wrong_key = 'S';
	} else {
		/* the broken size isn't in filename */
		return;
	}

	if (pmail->v.istream_opened != NULL) {
		/* the mail could be e.g. compressed. get the physical size
		   the slow way by actually reading the mail. */
		struct istream *input;
		const struct stat *stp;

		if (mail_get_stream(mail, NULL, NULL, &input) < 0)
			return;
		if (i_stream_stat(input, TRUE, &stp) < 0)
			return;
		ctx.physical_size = stp->st_size;
	}

	(void)maildir_file_do(mbox, mail->uid, do_fix_size, &ctx);
}
int subsfile_list_fstat(struct subsfile_list_context *ctx, struct stat *st_r)
{
	const struct stat *st;

	if (ctx->failed)
		return -1;

	if (i_stream_stat(ctx->input, FALSE, &st) < 0) {
		ctx->failed = TRUE;
		return -1;
	}
	*st_r = *st;
	return 0;
}
Exemple #13
0
static int
i_stream_limit_stat(struct istream_private *stream, bool exact)
{
	struct limit_istream *lstream = (struct limit_istream *) stream;
	const struct stat *st;

	if (i_stream_stat(stream->parent, exact, &st) < 0)
		return -1;

	stream->statbuf = *st;
	if (lstream->v_size != (uoff_t)-1)
		stream->statbuf.st_size = lstream->v_size;
	return 0;
}
static int
i_stream_mail_filter_stat(struct istream_private *stream, bool exact)
{
	const struct stat *st;

	i_assert(!exact);

	if (i_stream_stat(stream->parent, exact, &st) < 0) {
		stream->istream.stream_errno = stream->parent->stream_errno;
		return -1;
	}
	stream->statbuf = *st;
	return 0;
}
static int
i_stream_seekable_stat(struct istream_private *stream, bool exact)
{
    struct seekable_istream *sstream = (struct seekable_istream *)stream;
    const struct stat *st;
    uoff_t old_offset;
    ssize_t ret;

    if (sstream->size != (uoff_t)-1) {
        /* we've already reached EOF and know the size */
        stream->statbuf.st_size = sstream->size;
        return 0;
    }

    if (sstream->membuf != NULL) {
        /* we want to know the full size of the file, so read until
           we're finished */
        old_offset = stream->istream.v_offset;
        do {
            i_stream_skip(&stream->istream,
                          stream->pos - stream->skip);
        } while ((ret = i_stream_seekable_read(stream)) > 0);

        if (ret == 0) {
            i_panic("i_stream_stat() used for non-blocking "
                    "seekable stream %s offset %"PRIuUOFF_T,
                    i_stream_get_name(sstream->cur_input),
                    sstream->cur_input->v_offset);
        }
        i_stream_skip(&stream->istream, stream->pos - stream->skip);
        i_stream_seek(&stream->istream, old_offset);
        unref_streams(sstream);
    }
    if (stream->istream.stream_errno != 0)
        return -1;

    if (sstream->fd_input != NULL) {
        /* using a file backed buffer, we can use real fstat() */
        if (i_stream_stat(sstream->fd_input, exact, &st) < 0)
            return -1;
        stream->statbuf = *st;
    } else {
        /* buffer is completely in memory */
        i_assert(sstream->membuf != NULL);

        stream->statbuf.st_size = sstream->membuf->used;
    }
    return 0;
}
Exemple #16
0
static int
i_stream_raw_mbox_stat(struct istream_private *stream, bool exact)
{
	const struct stat *st;
	struct raw_mbox_istream *rstream = (struct raw_mbox_istream *)stream;

	if (i_stream_stat(stream->parent, exact, &st) < 0)
		return -1;

	stream->statbuf = *st;
	stream->statbuf.st_size =
		!exact && rstream->seeked && rstream->mail_size != (uoff_t)-1 ?
		(off_t)rstream->mail_size : -1;
	return 0;
}
Exemple #17
0
static const struct stat *
i_stream_limit_stat(struct istream_private *stream, bool exact)
{
	struct limit_istream *lstream = (struct limit_istream *) stream;
	const struct stat *st;

	st = i_stream_stat(stream->parent, exact);
	if (st == NULL)
		return NULL;

	stream->statbuf = *st;
	if (lstream->v_size != (uoff_t)-1)
		stream->statbuf.st_size = lstream->v_size;
	return &stream->statbuf;
}
Exemple #18
0
static void i_stream_lzma_sync(struct istream_private *stream)
{
	struct lzma_istream *zstream = (struct lzma_istream *) stream;
	const struct stat *st;

	if (i_stream_stat(stream->parent, FALSE, &st) < 0) {
		if (memcmp(&zstream->last_parent_statbuf,
			   st, sizeof(*st)) == 0) {
			/* a compressed file doesn't change unexpectedly,
			   don't clear our caches unnecessarily */
			return;
		}
		zstream->last_parent_statbuf = *st;
	}
	i_stream_lzma_reset(zstream);
}
Exemple #19
0
static int
i_stream_default_stat(struct istream_private *stream, bool exact)
{
	const struct stat *st;

	if (stream->parent == NULL)
		return stream->istream.stream_errno == 0 ? 0 : -1;

	if (i_stream_stat(stream->parent, exact, &st) < 0)
		return -1;
	stream->statbuf = *st;
	if (exact && !stream->stream_size_passthrough) {
		/* exact size is not known, even if parent returned something */
		stream->statbuf.st_size = -1;
	}
	return 0;
}
Exemple #20
0
static int maildir_mail_stat(struct mail *mail, struct stat *st_r)
{
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
	struct index_mail *imail = (struct index_mail *)mail;
	const struct stat *stp;
	const char *path;
	int ret;

	if (mail->lookup_abort == MAIL_LOOKUP_ABORT_NOT_IN_CACHE) {
		mail_set_aborted(mail);
		return -1;
	}

	if (imail->data.access_part != 0 &&
	    imail->data.stream == NULL) {
		/* we're going to open the mail anyway */
		struct istream *input;

		(void)mail_get_stream(mail, NULL, NULL, &input);
	}

	if (imail->data.stream != NULL) {
		mail->transaction->stats.fstat_lookup_count++;
		if (i_stream_stat(imail->data.stream, FALSE, &stp) < 0)
			return -1;
		*st_r = *stp;
	} else if (!mail->saving) {
		mail->transaction->stats.stat_lookup_count++;
		ret = maildir_file_do(mbox, mail->uid, do_stat, st_r);
		if (ret <= 0) {
			if (ret == 0)
				mail_set_expunged(mail);
			return -1;
		}
	} else {
		mail->transaction->stats.stat_lookup_count++;
		path = maildir_save_file_get_path(mail->transaction, mail->seq);
		if (stat(path, st_r) < 0) {
			mail_storage_set_critical(mail->box->storage,
						  "stat(%s) failed: %m", path);
			return -1;
		}
	}
	return 0;
}
static int
sieve_attribute_retrieve_script(struct mail_storage *storage,
			   struct sieve_storage *svstorage, struct sieve_script *script,
			   bool add_type_prefix,
			   struct mail_attribute_value *value_r, const char **errorstr_r)
{
	static char type = MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT;
	struct istream *input, *inputs[3];
	const struct stat *st;
	enum sieve_error error;

	if (script == NULL)
		*errorstr_r = sieve_storage_get_last_error(svstorage, &error);
	else if (sieve_script_get_stream(script, &input, &error) < 0)
		sieve_script_unref(&script);
	
	if (script == NULL) {
		if (error == SIEVE_ERROR_NOT_FOUND) {
			/* already deleted, but return the last_change */
			(void)sieve_storage_get_last_change(svstorage,
							    &value_r->last_change);
			return 0;
		}
		*errorstr_r = sieve_storage_get_last_error(svstorage, &error);
		return -1;
	}
	if (i_stream_stat(input, FALSE, &st) < 0) {
		mail_storage_set_critical(storage,
			"stat(%s) failed: %m", i_stream_get_name(input));
	} else {
		value_r->last_change = st->st_mtime;
	}
	if (!add_type_prefix) {
		i_stream_ref(input);
		value_r->value_stream = input;
	} else {
		inputs[0] = i_stream_create_from_data(&type, 1);
		inputs[1] = input;
		inputs[2] = NULL;
		value_r->value_stream = i_stream_create_concat(inputs);
		i_stream_unref(&inputs[0]);
	}
	sieve_script_unref(&script);
	return 1;
}
Exemple #22
0
static int i_stream_limit_get_size(struct istream_private *stream,
				   bool exact, uoff_t *size_r)
{
	struct limit_istream *lstream = (struct limit_istream *) stream;
	const struct stat *st;

	if (lstream->v_size != (uoff_t)-1) {
		*size_r = lstream->v_size;
		return 1;
	}

	if (i_stream_stat(&stream->istream, exact, &st) < 0)
		return -1;
	if (st->st_size == -1)
		return 0;

	*size_r = st->st_size;
	return 1;
}
Exemple #23
0
static int raw_mail_stat(struct mail *mail)
{
	struct raw_mailbox *mbox = (struct raw_mailbox *)mail->box;
	struct mail_private *p = (struct mail_private *)mail;
	const struct stat *st;

	if (mail->lookup_abort == MAIL_LOOKUP_ABORT_NOT_IN_CACHE)
		return mail_set_aborted(mail);

	p->stats_fstat_lookup_count++;
	st = i_stream_stat(mail->box->input, TRUE);
	if (st == NULL) {
		mail_storage_set_critical(mail->box->storage,
			"stat(%s) failed: %m", mail->box->path);
		return -1;
	}

	if (mbox->mtime != (time_t)-1)
		mbox->mtime = st->st_mtime;
	if (mbox->ctime != (time_t)-1)
		mbox->ctime = st->st_ctime;
	mbox->size = st->st_size;
	return 0;
}
Exemple #24
0
static const struct stat *
i_stream_mail_stats_stat(struct istream_private *stream, bool exact)
{
	return i_stream_stat(stream->parent, exact);
}