void dbox_file_free(struct dbox_file *file) { i_assert(file->refcount == 0); if (file->metadata_pool != NULL) pool_unref(&file->metadata_pool); dbox_file_close(file); i_free(file->primary_path); i_free(file->alt_path); i_free(file); }
int dbox_file_fix(struct dbox_file *file, uoff_t start_offset) { struct ostream *output; const char *dir, *p, *temp_path, *broken_path; bool deleted; int fd, ret; i_assert(dbox_file_is_open(file)); p = strrchr(file->cur_path, '/'); i_assert(p != NULL); dir = t_strdup_until(file->cur_path, p); temp_path = t_strdup_printf("%s/%s", dir, dbox_generate_tmp_filename()); fd = file->storage->v.file_create_fd(file, temp_path, FALSE); if (fd == -1) return -1; output = o_stream_create_fd_file(fd, 0, FALSE); ret = dbox_file_fix_write_stream(file, start_offset, temp_path, output); o_stream_unref(&output); if (close(fd) < 0) { mail_storage_set_critical(&file->storage->storage, "close(%s) failed: %m", temp_path); ret = -1; } if (ret < 0) { if (unlink(temp_path) < 0) { mail_storage_set_critical(&file->storage->storage, "unlink(%s) failed: %m", temp_path); } return -1; } /* keep a copy of the original file in case someone wants to look at it */ broken_path = t_strconcat(file->cur_path, DBOX_MAIL_FILE_BROKEN_COPY_SUFFIX, NULL); if (link(file->cur_path, broken_path) < 0) { mail_storage_set_critical(&file->storage->storage, "link(%s, %s) failed: %m", file->cur_path, broken_path); } else { i_warning("dbox: Copy of the broken file saved to %s", broken_path); } if (rename(temp_path, file->cur_path) < 0) { mail_storage_set_critical(&file->storage->storage, "rename(%s, %s) failed: %m", temp_path, file->cur_path); return -1; } /* file was successfully recreated - reopen it */ dbox_file_close(file); if (dbox_file_open(file, &deleted) <= 0) { mail_storage_set_critical(&file->storage->storage, "dbox_file_fix(%s): reopening file failed", file->cur_path); return -1; } return 0; }