<commit_before>/* Copyright (c) 2003-2008 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "istream.h"
#include "index-mail.h"
#include "maildir-storage.h"
#include "maildir-filename.h"
#include "maildir-uidlist.h"
#include "maildir-sync.h"

#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

static int
do_open(struct maildir_mailbox *mbox, const char *path, int *fd)
{
	*fd = open(path, O_RDONLY);
	if (*fd != -1)
		return 1;
	if (errno == ENOENT)
		return 0;

	mail_storage_set_critical(&mbox->storage->storage,
				  "open(%s) failed: %m", path);
	return -1;
}

static int
do_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st)
{
	if (stat(path, st) == 0)
		return 1;
	if (errno == ENOENT)
		return 0;

	mail_storage_set_critical(&mbox->storage->storage,
				  "stat(%s) failed: %m", path);
	return -1;
}

static struct istream *
maildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
		  bool *deleted_r)
{
	const char *path;
	int fd = -1;

	*deleted_r = FALSE;

	if (mail->uid != 0) {
		if (maildir_file_do(mbox, mail->uid, do_open, &fd) < 0)
			return NULL;
	} else {
		path = maildir_save_file_get_path(mail->transaction, mail->seq);
		if (do_open(mbox, path, &fd) <= 0)
			return NULL;
	}

	if (fd == -1) {
		*deleted_r = TRUE;
		return NULL;
	}

	return i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
}

static int maildir_mail_stat(struct mail *mail, struct stat *st)
{
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
	struct index_mail_data *data = &((struct index_mail *)mail)->data;
	const char *path;
	int fd, ret;

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

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

	if (data->stream != NULL) {
		fd = i_stream_get_fd(data->stream);
		i_assert(fd != -1);

		if (fstat(fd, st) < 0) {
			mail_storage_set_critical(&mbox->storage->storage,
						  "fstat(maildir) failed: %m");
			return -1;
		}
	} else if (mail->uid != 0) {
		ret = maildir_file_do(mbox, mail->uid, do_stat, st);
		if (ret <= 0) {
			if (ret == 0)
				mail_set_expunged(mail);
			return -1;
		}
	} else {
		path = maildir_save_file_get_path(mail->transaction, mail->seq);
		if (stat(path, st) < 0) {
			mail_storage_set_critical(mail->box->storage,
						  "stat(%s) failed: %m", path);
			return -1;
		}
	}
	return 0;
}

static int maildir_mail_get_received_date(struct mail *_mail, time_t *date_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct index_mail_data *data = &mail->data;
	struct stat st;

	if (index_mail_get_received_date(_mail, date_r) == 0)
		return 0;

	if (maildir_mail_stat(_mail, &st) < 0)
		return -1;

	*date_r = data->received_date = st.st_mtime;
	return 0;
}

static int maildir_mail_get_save_date(struct mail *_mail, time_t *date_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct index_mail_data *data = &mail->data;
	struct stat st;

	if (index_mail_get_save_date(_mail, date_r) == 0)
		return 0;

	if (maildir_mail_stat(_mail, &st) < 0)
		return -1;

	*date_r = data->save_date = st.st_ctime;
	return data->save_date;
}

static bool
maildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail,
		       const char **fname_r)
{
	enum maildir_uidlist_rec_flag flags;
	struct mail_index_view *view;
	uint32_t seq;
	bool exists;

	*fname_r = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags);
	if (*fname_r != NULL)
		return TRUE;

	/* file exists in index file, but not in dovecot-uidlist anymore. */
	mail_set_expunged(mail);

	/* one reason this could happen is if we delayed opening
	   dovecot-uidlist and we're trying to open a mail that got recently
	   expunged. Let's test this theory first: */
	(void)mail_index_refresh(mbox->ibox.index);
	view = mail_index_view_open(mbox->ibox.index);
	exists = mail_index_lookup_seq(view, mail->uid, &seq);
	mail_index_view_close(&view);

	if (exists) {
		/* the message still exists in index. this means there's some<commit_msg>If file isn't found from uidlist, refresh the file and look again in case it was added after the previous mailbox sync (but after the previous view sync that found new messages).<commit_after>/* Copyright (c) 2003-2008 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "istream.h"
#include "index-mail.h"
#include "maildir-storage.h"
#include "maildir-filename.h"
#include "maildir-uidlist.h"
#include "maildir-sync.h"

#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

static int
do_open(struct maildir_mailbox *mbox, const char *path, int *fd)
{
	*fd = open(path, O_RDONLY);
	if (*fd != -1)
		return 1;
	if (errno == ENOENT)
		return 0;

	mail_storage_set_critical(&mbox->storage->storage,
				  "open(%s) failed: %m", path);
	return -1;
}

static int
do_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st)
{
	if (stat(path, st) == 0)
		return 1;
	if (errno == ENOENT)
		return 0;

	mail_storage_set_critical(&mbox->storage->storage,
				  "stat(%s) failed: %m", path);
	return -1;
}

static struct istream *
maildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
		  bool *deleted_r)
{
	const char *path;
	int fd = -1;

	*deleted_r = FALSE;

	if (mail->uid != 0) {
		if (maildir_file_do(mbox, mail->uid, do_open, &fd) < 0)
			return NULL;
	} else {
		path = maildir_save_file_get_path(mail->transaction, mail->seq);
		if (do_open(mbox, path, &fd) <= 0)
			return NULL;
	}

	if (fd == -1) {
		*deleted_r = TRUE;
		return NULL;
	}

	return i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
}

static int maildir_mail_stat(struct mail *mail, struct stat *st)
{
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
	struct index_mail_data *data = &((struct index_mail *)mail)->data;
	const char *path;
	int fd, ret;

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

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

	if (data->stream != NULL) {
		fd = i_stream_get_fd(data->stream);
		i_assert(fd != -1);

		if (fstat(fd, st) < 0) {
			mail_storage_set_critical(&mbox->storage->storage,
						  "fstat(maildir) failed: %m");
			return -1;
		}
	} else if (mail->uid != 0) {
		ret = maildir_file_do(mbox, mail->uid, do_stat, st);
		if (ret <= 0) {
			if (ret == 0)
				mail_set_expunged(mail);
			return -1;
		}
	} else {
		path = maildir_save_file_get_path(mail->transaction, mail->seq);
		if (stat(path, st) < 0) {
			mail_storage_set_critical(mail->box->storage,
						  "stat(%s) failed: %m", path);
			return -1;
		}
	}
	return 0;
}

static int maildir_mail_get_received_date(struct mail *_mail, time_t *date_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct index_mail_data *data = &mail->data;
	struct stat st;

	if (index_mail_get_received_date(_mail, date_r) == 0)
		return 0;

	if (maildir_mail_stat(_mail, &st) < 0)
		return -1;

	*date_r = data->received_date = st.st_mtime;
	return 0;
}

static int maildir_mail_get_save_date(struct mail *_mail, time_t *date_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct index_mail_data *data = &mail->data;
	struct stat st;

	if (index_mail_get_save_date(_mail, date_r) == 0)
		return 0;

	if (maildir_mail_stat(_mail, &st) < 0)
		return -1;

	*date_r = data->save_date = st.st_ctime;
	return data->save_date;
}

static bool
maildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail,
		       const char **fname_r)
{
	enum maildir_uidlist_rec_flag flags;
	struct mail_index_view *view;
	uint32_t seq;
	bool exists;

	*fname_r = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags);
	if (*fname_r != NULL)
		return TRUE;

	/* refresh uidlist and check again in case it was added after the last
	   mailbox sync */
	if (maildir_uidlist_refresh(mbox->uidlist) < 0)
		return FALSE;
	*fname_r = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags);
	if (*fname_r != NULL)
		return TRUE;

	/* file exists in index file, but not in dovecot-uidlist anymore. */
	mail_set_expunged(mail);

	/* one reason this could happen is if we delayed opening
	   dovecot-uidlist and we're trying to open a mail that got recently
	   expunged. Let's test this theory first: */
	(void)mail_index_refresh(mbox->ibox.index);
	view = mail_index_view_open(mbox->ibox.index);
	exists = mail_index_lookup_seq(view, mail->uid, &seq);
	mail_index_view_close(&view);

	if (exists) {
		/* the message still exists in index. this means there's some
{'fraction_non_alphanumeric': 0.1382644146767618, 'fraction_numerical': 0.010133954571927782, 'mean_word_length': 4.175406871609403, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 78, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2264026', 'n_tokens_mistral': 3538, 'n_tokens_neox': 3261, 'n_words': 865}