bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "lib.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "eacces-error.h"
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen#include "fdatasync-path.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "mkdir-parents.h"
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen#include "istream.h"
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen#include "ostream.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "str.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "fs-api.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "dbox-attachment.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "sdbox-storage.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "sdbox-file.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include <stdio.h>
cf77eee4f485c152886e12bc3aa288da81c68532Timo Sirainen#include <utime.h>
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void sdbox_file_init_paths(struct sdbox_file *file, const char *fname)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
686bc4ea97a86333316182865be3fcfe465a5827Timo Sirainen struct mailbox *box = &file->mbox->box;
686bc4ea97a86333316182865be3fcfe465a5827Timo Sirainen const char *alt_path;
686bc4ea97a86333316182865be3fcfe465a5827Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_free(file->file.primary_path);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_free(file->file.alt_path);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen file->file.primary_path =
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen i_strdup_printf("%s/%s", mailbox_get_path(box), fname);
d1808f883d0da0e9740616695618924e8278fce1Timo Sirainen file->file.cur_path = file->file.primary_path;
686bc4ea97a86333316182865be3fcfe465a5827Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &alt_path) > 0)
686bc4ea97a86333316182865be3fcfe465a5827Timo Sirainen file->file.alt_path = i_strdup_printf("%s/%s", alt_path, fname);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct dbox_file *sdbox_file_init(struct sdbox_mailbox *mbox, uint32_t uid)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct sdbox_file *file;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *fname;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen file = i_new(struct sdbox_file, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen file->file.storage = &mbox->storage->storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen file->mbox = mbox;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen T_BEGIN {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (uid != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen fname = t_strdup_printf(SDBOX_MAIL_FILE_FORMAT, uid);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen sdbox_file_init_paths(file, fname);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen file->uid = uid;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
2a77044395c864cc791cecd34b03002094f4973bTimo Sirainen sdbox_file_init_paths(file, dbox_generate_tmp_filename());
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } T_END;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_file_init(&file->file);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return &file->file;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainenstruct dbox_file *sdbox_file_create(struct sdbox_mailbox *mbox)
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen{
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen struct dbox_file *file;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen file = sdbox_file_init(mbox, 0);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen file->fd = file->storage->v.
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen file_create_fd(file, file->primary_path, FALSE);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen return file;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen}
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenvoid sdbox_file_free(struct dbox_file *file)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct sdbox_file *sfile = (struct sdbox_file *)file;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
c69a177207ed18d0f0210347430a60957136bd6cJosef 'Jeff' Sipek pool_unref(&sfile->attachment_pool);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen dbox_file_free(file);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenint sdbox_file_get_attachments(struct dbox_file *file, const char **extrefs_r)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const char *line;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen bool deleted;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen int ret;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen *extrefs_r = NULL;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* read the metadata */
4ca83616715c3bd417e34ced2c1d61852513e427Timo Sirainen ret = dbox_file_open(file, &deleted);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (ret > 0) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (deleted)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if ((ret = dbox_file_seek(file, 0)) > 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = dbox_file_metadata_read(file);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (ret <= 0) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (ret < 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* corrupted file. we're deleting it anyway. */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen line = NULL;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen } else {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen line = dbox_file_metadata_get(file, DBOX_METADATA_EXT_REF);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (line == NULL) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* no attachments */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen *extrefs_r = line;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return 1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenconst char *
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainensdbox_file_attachment_relpath(struct sdbox_file *file, const char *srcpath)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const char *p;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen p = strchr(srcpath, '-');
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (p == NULL) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&file->mbox->box,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen "sdbox attachment path in invalid format: %s", srcpath);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen } else {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen p = strchr(p+1, '-');
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return t_strdup_printf("%s-%s-%u",
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen p == NULL ? srcpath : t_strdup_until(srcpath, p),
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_to_string(file->mbox->mailbox_guid),
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen file->uid);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic int sdbox_file_rename_attachments(struct sdbox_file *file)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct dbox_storage *storage = file->file.storage;
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen struct fs_file *src_file, *dest_file;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const char *const *pathp, *src, *dest;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen int ret = 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_foreach(&file->attachment_paths, pathp) T_BEGIN {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen src = t_strdup_printf("%s/%s", storage->attachment_dir, *pathp);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen dest = t_strdup_printf("%s/%s", storage->attachment_dir,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen sdbox_file_attachment_relpath(file, *pathp));
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen src_file = fs_file_init(storage->attachment_fs, src,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen FS_OPEN_MODE_READONLY);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen dest_file = fs_file_init(storage->attachment_fs, dest,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen FS_OPEN_MODE_READONLY);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen if (fs_rename(src_file, dest_file) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&file->mbox->box, "%s",
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen fs_last_error(storage->attachment_fs));
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen fs_file_deinit(&src_file);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen fs_file_deinit(&dest_file);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen } T_END;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return ret;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
172b6edea36e425b0d0c35a854721ae63f57c289Timo Sirainenint sdbox_file_assign_uid(struct sdbox_file *file, uint32_t uid,
172b6edea36e425b0d0c35a854721ae63f57c289Timo Sirainen bool ignore_if_exists)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
2a77044395c864cc791cecd34b03002094f4973bTimo Sirainen const char *p, *old_path, *dir, *new_fname, *new_path;
dbc6f14323a634ce39f15dd7fef9ee773551dcf0Timo Sirainen struct stat st;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(file->uid == 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(uid != 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen old_path = file->file.cur_path;
2a77044395c864cc791cecd34b03002094f4973bTimo Sirainen p = strrchr(old_path, '/');
2a77044395c864cc791cecd34b03002094f4973bTimo Sirainen i_assert(p != NULL);
2a77044395c864cc791cecd34b03002094f4973bTimo Sirainen dir = t_strdup_until(old_path, p);
2a77044395c864cc791cecd34b03002094f4973bTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen new_fname = t_strdup_printf(SDBOX_MAIL_FILE_FORMAT, uid);
2a77044395c864cc791cecd34b03002094f4973bTimo Sirainen new_path = t_strdup_printf("%s/%s", dir, new_fname);
dbc6f14323a634ce39f15dd7fef9ee773551dcf0Timo Sirainen
172b6edea36e425b0d0c35a854721ae63f57c289Timo Sirainen if (!ignore_if_exists && stat(new_path, &st) == 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&file->mbox->box,
dbc6f14323a634ce39f15dd7fef9ee773551dcf0Timo Sirainen "sdbox: %s already exists, rebuilding index", new_path);
dbc6f14323a634ce39f15dd7fef9ee773551dcf0Timo Sirainen sdbox_set_mailbox_corrupted(&file->mbox->box);
dbc6f14323a634ce39f15dd7fef9ee773551dcf0Timo Sirainen return -1;
dbc6f14323a634ce39f15dd7fef9ee773551dcf0Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (rename(old_path, new_path) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&file->mbox->box,
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi "rename(%s, %s) failed: %m",
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi old_path, new_path);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen sdbox_file_init_paths(file, new_fname);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen file->uid = uid;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (array_is_created(&file->attachment_paths)) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (sdbox_file_rename_attachments(file) < 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic int sdbox_file_unlink_aborted_save_attachments(struct sdbox_file *file)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct dbox_storage *storage = file->file.storage;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct fs *fs = storage->attachment_fs;
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen struct fs_file *fs_file;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const char *const *pathp, *path;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen int ret = 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_foreach(&file->attachment_paths, pathp) T_BEGIN {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* we don't know if we aborted before renaming this attachment,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen so try deleting both source and dest path. the source paths
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen point to temporary files (not to source messages'
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen attachment paths), so it's safe to delete them. */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen path = t_strdup_printf("%s/%s", storage->attachment_dir,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen *pathp);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen fs_file = fs_file_init(fs, path, FS_OPEN_MODE_READONLY);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen if (fs_delete(fs_file) < 0 &&
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen errno != ENOENT) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&file->mbox->box, "%s",
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi fs_last_error(fs));
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen fs_file_deinit(&fs_file);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen path = t_strdup_printf("%s/%s", storage->attachment_dir,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen sdbox_file_attachment_relpath(file, *pathp));
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen fs_file = fs_file_init(fs, path, FS_OPEN_MODE_READONLY);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen if (fs_delete(fs_file) < 0 &&
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen errno != ENOENT) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&file->mbox->box, "%s",
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi fs_last_error(fs));
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen fs_file_deinit(&fs_file);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen } T_END;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return ret;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenint sdbox_file_unlink_aborted_save(struct sdbox_file *file)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen int ret = 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (unlink(file->file.cur_path) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&file->mbox->box,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen "unlink(%s) failed: %m", file->file.cur_path);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (array_is_created(&file->attachment_paths)) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (sdbox_file_unlink_aborted_save_attachments(file) < 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return ret;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint sdbox_file_create_fd(struct dbox_file *file, const char *path, bool parents)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct sdbox_file *sfile = (struct sdbox_file *)file;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mailbox *box = &sfile->mbox->box;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen const struct mailbox_permissions *perm = mailbox_get_permissions(box);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *p, *dir;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mode_t old_mask;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen int fd;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen old_mask = umask(0666 & ~perm->file_create_mode);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen umask(old_mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (fd == -1 && errno == ENOENT && parents &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (p = strrchr(path, '/')) != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dir = t_strdup_until(path, p);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (mkdir_parents_chgrp(dir, perm->dir_create_mode,
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen perm->file_create_gid,
a4828c444096564c9f6759fa71b2de21cda73164Timo Sirainen perm->file_create_gid_origin) < 0 &&
a4828c444096564c9f6759fa71b2de21cda73164Timo Sirainen errno != EEXIST) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "mkdir_parents(%s) failed: %m", dir);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* try again */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen old_mask = umask(0666 & ~perm->file_create_mode);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen umask(old_mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (fd == -1) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "open(%s, O_CREAT) failed: %m", path);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen } else if (perm->file_create_gid == (gid_t)-1) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* no group change */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen } else if (fchown(fd, (uid_t)-1, perm->file_create_gid) < 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (errno == EPERM) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "%s",
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen eperm_error_get_chgrp("fchown", path,
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen perm->file_create_gid,
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen perm->file_create_gid_origin));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "fchown(%s, -1, %ld) failed: %m",
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen path, (long)perm->file_create_gid);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* continue anyway */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return fd;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainenint sdbox_file_move(struct dbox_file *file, bool alt_path)
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen{
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen struct mail_storage *storage = &file->storage->storage;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen struct ostream *output;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen const char *dest_dir, *temp_path, *dest_path, *p;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen struct stat st;
cf77eee4f485c152886e12bc3aa288da81c68532Timo Sirainen struct utimbuf ut;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen bool deleted;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen int out_fd, ret = 0;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen i_assert(file->input != NULL);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (dbox_file_is_in_alt(file) == alt_path)
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen return 0;
901f49833183c9360fd04002fa94a47f8f7129edTimo Sirainen if (file->alt_path == NULL)
901f49833183c9360fd04002fa94a47f8f7129edTimo Sirainen return 0;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (stat(file->cur_path, &st) < 0 && errno == ENOENT) {
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen /* already expunged/moved by another session */
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen return 0;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen dest_path = !alt_path ? file->primary_path : file->alt_path;
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi i_assert(dest_path != NULL);
316cbe323513a0f20d1cf519fe9405e231d633e2Aki Tuomi
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen p = strrchr(dest_path, '/');
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen i_assert(p != NULL);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen dest_dir = t_strdup_until(dest_path, p);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen temp_path = t_strdup_printf("%s/%s", dest_dir,
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen dbox_generate_tmp_filename());
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen /* first copy the file. make sure to catch every possible error
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen since we really don't want to break the file. */
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen out_fd = file->storage->v.file_create_fd(file, temp_path, TRUE);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (out_fd == -1)
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen return -1;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen output = o_stream_create_fd_file(out_fd, 0, FALSE);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen i_stream_seek(file->input, 0);
6f187ae85911f63cb87271246c68f3c13a0adb7bTimo Sirainen o_stream_nsend_istream(output, file->input);
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen if (o_stream_finish(output) < 0) {
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen mail_storage_set_critical(storage, "write(%s) failed: %s",
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen temp_path, o_stream_get_error(output));
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen ret = -1;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen o_stream_unref(&output);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER && ret == 0) {
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (fsync(out_fd) < 0) {
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen mail_storage_set_critical(storage,
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen "fsync(%s) failed: %m", temp_path);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen ret = -1;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (close(out_fd) < 0) {
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen mail_storage_set_critical(storage,
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen "close(%s) failed: %m", temp_path);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen ret = -1;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (ret < 0) {
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen i_unlink(temp_path);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen return -1;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
cf77eee4f485c152886e12bc3aa288da81c68532Timo Sirainen /* preserve the original atime/mtime. this isn't necessary for Dovecot,
cf77eee4f485c152886e12bc3aa288da81c68532Timo Sirainen but could be useful for external reasons. */
cf77eee4f485c152886e12bc3aa288da81c68532Timo Sirainen ut.actime = st.st_atime;
cf77eee4f485c152886e12bc3aa288da81c68532Timo Sirainen ut.modtime = st.st_mtime;
cf77eee4f485c152886e12bc3aa288da81c68532Timo Sirainen if (utime(temp_path, &ut) < 0) {
cf77eee4f485c152886e12bc3aa288da81c68532Timo Sirainen mail_storage_set_critical(storage,
cf77eee4f485c152886e12bc3aa288da81c68532Timo Sirainen "utime(%s) failed: %m", temp_path);
cf77eee4f485c152886e12bc3aa288da81c68532Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen /* the temp file was successfully written. rename it now to the
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen destination file. the destination shouldn't exist, but if it does
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen its contents should be the same (except for maybe older metadata) */
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (rename(temp_path, dest_path) < 0) {
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen mail_storage_set_critical(storage,
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen "rename(%s, %s) failed: %m", temp_path, dest_path);
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen i_unlink_if_exists(temp_path);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen return -1;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (fdatasync_path(dest_dir) < 0) {
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen mail_storage_set_critical(storage,
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen "fdatasync(%s) failed: %m", dest_dir);
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen i_unlink(dest_path);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen return -1;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (unlink(file->cur_path) < 0) {
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen dbox_file_set_syscall_error(file, "unlink()");
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen if (errno == EACCES) {
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen /* configuration problem? revert the write */
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen i_unlink(dest_path);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen /* who knows what happened to the file. keep both just to be
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen sure both won't get deleted. */
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen return -1;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen /* file was successfully moved - reopen it */
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen dbox_file_close(file);
4ca83616715c3bd417e34ced2c1d61852513e427Timo Sirainen if (dbox_file_open(file, &deleted) <= 0) {
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen mail_storage_set_critical(storage,
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen "dbox_file_move(%s): reopening file failed", dest_path);
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen return -1;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen }
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen return 0;
c2d2161296e2361f97ee48b70b168602157069e6Timo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic int
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainensdbox_unlink_attachments(struct sdbox_file *sfile,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const ARRAY_TYPE(mail_attachment_extref) *extrefs)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct dbox_storage *storage = sfile->file.storage;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const struct mail_attachment_extref *extref;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const char *path;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen int ret = 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_foreach(extrefs, extref) T_BEGIN {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen path = sdbox_file_attachment_relpath(sfile, extref->path);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (index_attachment_delete(&storage->storage,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen storage->attachment_fs, path) < 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen } T_END;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return ret;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenint sdbox_file_unlink_with_attachments(struct sdbox_file *sfile)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ARRAY_TYPE(mail_attachment_extref) extrefs;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const char *extrefs_line;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pool_t pool;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen int ret;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = sdbox_file_get_attachments(&sfile->file, &extrefs_line);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (ret < 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (ret == 0) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* no attachments */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return dbox_file_unlink(&sfile->file);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pool = pool_alloconly_create("sdbox attachments unlink", 1024);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen p_array_init(&extrefs, pool, 16);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen if (!index_attachment_parse_extrefs(extrefs_line, pool, &extrefs)) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen i_warning("%s: Ignoring corrupted extref: %s",
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen sfile->file.cur_path, extrefs_line);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_clear(&extrefs);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* try to delete the file first, so if it fails we don't have
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen missing attachments */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if ((ret = dbox_file_unlink(&sfile->file)) >= 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen (void)sdbox_unlink_attachments(sfile, &extrefs);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pool_unref(&pool);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return ret;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}