Пример #1
0
static int maildir_sync_flags(struct maildir_mailbox *mbox, const char *path,
			      struct maildir_index_sync_context *ctx)
{
	struct mailbox *box = &mbox->box;
	struct stat st;
	const char *dir, *fname, *newfname, *newpath;
	enum mail_index_sync_type sync_type;
	uint8_t flags8;

	ctx->flag_change_count++;

	fname = strrchr(path, '/');
	i_assert(fname != NULL);
	fname++;
	dir = t_strdup_until(path, fname);

	i_assert(*fname != '\0');

	/* get the current flags and keywords */
	maildir_filename_flags_get(ctx->keywords_sync_ctx,
				   fname, &ctx->flags, &ctx->keywords);

	/* apply changes */
	flags8 = ctx->flags;
	index_sync_changes_apply(ctx->sync_changes, NULL,
				 &flags8, &ctx->keywords, &sync_type);
	ctx->flags = flags8;

	/* and try renaming with the new name */
	newfname = maildir_filename_flags_kw_set(ctx->keywords_sync_ctx, fname,
						 ctx->flags, &ctx->keywords);
	newpath = t_strconcat(dir, newfname, NULL);
	if (strcmp(path, newpath) == 0) {
		/* just make sure that the file still exists. avoid rename()
		   here because it's slow on HFS. */
		if (stat(path, &st) < 0) {
			if (errno == ENOENT)
				return 0;
			mail_storage_set_critical(box->storage,
				"stat(%s) failed: %m", path);
			return -1;
		}
	} else {
		if (rename(path, newpath) < 0) {
			if (errno == ENOENT)
				return 0;
			if (!ENOSPACE(errno) && errno != EACCES) {
				mail_storage_set_critical(box->storage,
					"rename(%s, %s) failed: %m",
					path, newpath);
			}
			return -1;
		}
	}
	if (box->v.sync_notify != NULL) {
		box->v.sync_notify(box, ctx->uid,
				   index_sync_type_convert(sync_type));
	}
	return 1;
}
Пример #2
0
static const char *
maildir_filename_guess(struct maildir_mailbox *mbox, uint32_t uid,
		       const char *fname,
		       enum maildir_uidlist_rec_flag *uidlist_flags,
		       bool *have_flags_r)

{
	struct mail_index_view *view = mbox->flags_view;
	struct maildir_keywords_sync_ctx *kw_ctx;
	enum mail_flags flags;
	ARRAY_TYPE(keyword_indexes) keywords;
	const char *p;
	uint32_t seq;

	if (view == NULL || !mail_index_lookup_seq(view, uid, &seq)) {
		*have_flags_r = FALSE;
		return fname;
	}

	t_array_init(&keywords, 32);
	mail_index_lookup_view_flags(view, seq, &flags, &keywords);
	if (array_count(&keywords) == 0) {
		*have_flags_r = (flags & MAIL_FLAGS_NONRECENT) != 0;
		fname = maildir_filename_flags_set(fname, flags);
	} else {
		*have_flags_r = TRUE;
		kw_ctx = maildir_keywords_sync_init_readonly(mbox->keywords,
							     mbox->box.index);
		fname = maildir_filename_flags_kw_set(kw_ctx, fname,
						      flags, &keywords);
		maildir_keywords_sync_deinit(&kw_ctx);
	}

	if (*have_flags_r) {
		/* don't even bother looking into new/ dir */
		*uidlist_flags &= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
	} else if ((*uidlist_flags & MAILDIR_UIDLIST_REC_FLAG_MOVED) == 0 &&
		   ((*uidlist_flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0 ||
		    mailbox_recent_flags_have_uid(&mbox->box, uid))) {
		/* probably in new/ dir, drop ":2," from fname */
		*uidlist_flags |= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
		p = strrchr(fname, MAILDIR_INFO_SEP);
		if (p != NULL)
			fname = t_strdup_until(fname, p);
	}

	return fname;
}
Пример #3
0
static bool
maildir_get_dest_filename(struct maildir_save_context *ctx,
			  struct maildir_filename *mf,
			  const char **fname_r)
{
	const char *basename = mf->dest_basename;

	if (mf->size != (uoff_t)-1 && !mf->preserve_filename) {
		basename = t_strdup_printf("%s,%c=%"PRIuUOFF_T, basename,
					   MAILDIR_EXTRA_FILE_SIZE, mf->size);
	}

	if (mf->vsize != (uoff_t)-1 && !mf->preserve_filename) {
		basename = t_strdup_printf("%s,%c=%"PRIuUOFF_T, basename,
					   MAILDIR_EXTRA_VIRTUAL_SIZE,
					   mf->vsize);
	}

	if (mf->keywords_count == 0) {
		if ((mf->flags & MAIL_FLAGS_MASK) == MAIL_RECENT) {
			*fname_r = basename;
			return TRUE;
		}

		*fname_r = maildir_filename_flags_set(basename,
					mf->flags & MAIL_FLAGS_MASK);
		return FALSE;
	}

	i_assert(ctx->keywords_sync_ctx != NULL || mf->keywords_count == 0);
	buffer_create_from_const_data(&ctx->keywords_buffer, mf + 1,
				      mf->keywords_count * sizeof(unsigned int));
	*fname_r = maildir_filename_flags_kw_set(ctx->keywords_sync_ctx,
						 basename,
						 mf->flags & MAIL_FLAGS_MASK,
						 &ctx->keywords_array);
	return FALSE;
}