doveadm-fs.c revision 5592b04741577d014760097fc40f0f5276241754
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "array.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "md5.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "sha2.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "hash-method.h"
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include "hex-binary.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "istream.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "ostream.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "iostream-ssl.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "fs-api.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "doveadm.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include <stdio.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <unistd.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void cmd_fs_delete(int argc, char *argv[]);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic struct fs *
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainencmd_fs_init(int *argc, char **argv[], int own_arg_count, doveadm_command_t *cmd)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct ssl_iostream_settings ssl_set;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct fs_settings fs_set;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct fs *fs;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *error;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (own_arg_count > 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (*argc != 3 + own_arg_count)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_cmd_help(cmd);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen } else {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (*argc <= 3)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_cmd_help(cmd);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen memset(&ssl_set, 0, sizeof(ssl_set));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ssl_set.ca_dir = doveadm_settings->ssl_client_ca_dir;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ssl_set.ca_file = doveadm_settings->ssl_client_ca_file;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ssl_set.verbose = doveadm_debug;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen memset(&fs_set, 0, sizeof(fs_set));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_set.ssl_client_set = &ssl_set;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_set.temp_dir = "/tmp";
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_set.base_dir = doveadm_settings->base_dir;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_set.debug = doveadm_debug;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fs_init((*argv)[1], (*argv)[2], &fs_set, &fs, &error) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fs_init() failed: %s", error);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen *argc += 3;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen *argv += 3;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return fs;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void cmd_fs_get(int argc, char *argv[])
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct fs *fs;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct fs_file *file;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct istream *input;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const unsigned char *data;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen size_t size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ssize_t ret;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_get);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen input = fs_read_stream(file, IO_BLOCK_SIZE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fwrite(data, 1, size, stdout);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_stream_skip(input, size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_assert(ret == -1);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (input->stream_errno == ENOENT) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_file_last_error(file));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen } else if (input->stream_errno != 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_error("read(%s) failed: %s", fs_file_path(file),
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_file_last_error(file));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_stream_unref(&input);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_file_deinit(&file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_deinit(&fs);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void cmd_fs_put(int argc, char *argv[])
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct fs *fs;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen enum fs_properties props;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *src_path, *dest_path;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct fs_file *file;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct istream *input;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct ostream *output;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen buffer_t *hash = NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen off_t ret;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int c;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen while ((c = getopt(argc, argv, "h:")) > 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen switch (c) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen case 'h':
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash = buffer_create_dynamic(pool_datastack_create(), 32);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (hex_to_binary(optarg, hash) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("Invalid -h parameter: Hash not in hex");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen break;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen default:
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_cmd_help(cmd_fs_put);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen argc -= optind-1; argv += optind-1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_put);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen src_path = argv[0];
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen dest_path = argv[1];
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen props = fs_get_properties(fs);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (hash == NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen else if (hash->used == hash_method_md5.digest_size) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if ((props & FS_PROPERTY_WRITE_HASH_MD5) == 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fs backend doesn't support MD5 hashes");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_write_set_hash(file,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash_method_lookup(hash_method_md5.name), hash->data);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen } else if (hash->used == hash_method_sha256.digest_size) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if ((props & FS_PROPERTY_WRITE_HASH_SHA256) == 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fs backend doesn't support SHA256 hashes");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_write_set_hash(file,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash_method_lookup(hash_method_sha256.name), hash->data);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen output = fs_write_stream(file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen input = i_stream_create_file(src_path, IO_BLOCK_SIZE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if ((ret = o_stream_send_istream(output, input)) < 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (output->stream_errno != 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_error("write(%s) failed: %s", dest_path,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen o_stream_get_error(output));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen } else {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_error("read(%s) failed: %s", src_path,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_stream_get_error(input));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_stream_destroy(&input);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fs_write_stream_finish(file, &output) < 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_error("fs_write_stream_finish() failed: %s",
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_file_last_error(file));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_file_deinit(&file);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_deinit(&fs);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void cmd_fs_copy(int argc, char *argv[])
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct fs *fs;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct fs_file *src_file, *dest_file;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *src_path, *dest_path;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_copy);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen src_path = argv[0];
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen dest_path = argv[1];
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen src_file = fs_file_init(fs, src_path, FS_OPEN_MODE_READONLY);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen dest_file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fs_copy(src_file, dest_file) == 0) ;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen else if (errno == ENOENT) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_error("%s doesn't exist: %s", src_path,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs_last_error(fs));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("fs_copy(%s, %s) failed: %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen src_path, dest_path, fs_last_error(fs));
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs_file_deinit(&src_file);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs_file_deinit(&dest_file);
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen fs_deinit(&fs);
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void cmd_fs_stat(int argc, char *argv[])
e8bdf1be00aec45d0c6dd72ad9c8be02a3dfc778Timo Sirainen{
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen struct fs *fs;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct fs_file *file;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct stat st;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
2abfef71398a61e5ed97c23a1ceb71461933ccb8Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_stat);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fs_stat(file, &st) == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen printf("%s size=%lld\n", fs_file_path(file),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (long long)st.st_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (errno == ENOENT) {
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen fs_file_last_error(file));
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen } else {
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen i_error("fs_stat(%s) failed: %s",
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen fs_file_path(file), fs_file_last_error(file));
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen }
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen fs_file_deinit(&file);
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen fs_deinit(&fs);
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen}
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenstatic void cmd_fs_metadata(int argc, char *argv[])
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct fs *fs;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct fs_file *file;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct fs_metadata *m;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const ARRAY_TYPE(fs_metadata) *metadata;
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_metadata);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen if (fs_get_metadata(file, &metadata) == 0) {
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen array_foreach(metadata, m)
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen printf("%s=%s\n", m->key, m->value);
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen } else if (errno == ENOENT) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs_file_last_error(file));
9c7e765845357342923e16351181091028e5930fTimo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen } else {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen i_error("fs_stat(%s) failed: %s",
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen fs_file_path(file), fs_file_last_error(file));
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen }
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen fs_file_deinit(&file);
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen fs_deinit(&fs);
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen}
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenstruct fs_delete_ctx {
b00787191c3c31bebb939c3d00f1fcdb67356c69Timo Sirainen struct fs *fs;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen const char *path_prefix;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen unsigned int files_count;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen struct fs_file **files;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen};
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainenstatic int cmd_fs_delete_ctx_run(struct fs_delete_ctx *ctx)
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen unsigned int i;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen int ret = 0;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen for (i = 0; i < ctx->files_count; i++) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (ctx->files[i] == NULL)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen ;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen else if (fs_delete(ctx->files[i]) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs_file_deinit(&ctx->files[i]);
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen else if (errno == EAGAIN) {
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen if (ret == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (errno == ENOENT) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("%s doesn't exist: %s", fs_file_path(ctx->files[i]),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs_file_last_error(ctx->files[i]));
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen ret = -1;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen } else {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen i_error("fs_delete(%s) failed: %s",
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen fs_file_path(ctx->files[i]),
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen fs_file_last_error(ctx->files[i]));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen
ea9fd7f876643e985946a2563140359064819b8eTimo Sirainenstatic int doveadm_fs_delete_async_fname(struct fs_delete_ctx *ctx,
ea9fd7f876643e985946a2563140359064819b8eTimo Sirainen const char *fname)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen int ret;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < ctx->files_count; i++) {
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (ctx->files[i] != NULL)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen continue;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->files[i] = fs_file_init(ctx->fs,
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen t_strdup_printf("%s%s", ctx->path_prefix, fname),
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen FS_OPEN_MODE_READONLY | FS_OPEN_FLAG_ASYNC |
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen FS_OPEN_FLAG_ASYNC_NOQUEUE);
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen fname = NULL;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen break;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen }
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if ((ret = cmd_fs_delete_ctx_run(ctx)) < 0)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return -1;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (fname != NULL) {
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (ret > 0 && fs_wait_async(ctx->fs) < 0) {
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen i_error("fs_wait_async() failed: %s", fs_last_error(ctx->fs));
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return -1;;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen }
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen return doveadm_fs_delete_async_fname(ctx, fname);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen }
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen return 0;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen}
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenstatic void doveadm_fs_delete_async_finish(struct fs_delete_ctx *ctx)
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen{
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen unsigned int i;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen while (doveadm_exit_code == 0 && cmd_fs_delete_ctx_run(ctx) > 0) {
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen if (fs_wait_async(ctx->fs) < 0) {
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen i_error("fs_wait_async() failed: %s", fs_last_error(ctx->fs));
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen break;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen }
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen }
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen for (i = 0; i < ctx->files_count; i++) {
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (ctx->files[i] != NULL)
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen fs_file_deinit(&ctx->files[i]);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen }
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen}
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenstatic void
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainencmd_fs_delete_dir_recursive(struct fs *fs, unsigned int async_count,
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen const char *path_prefix)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen{
538303a216166f3526c0ae9658c9978275cfa100Timo Sirainen struct fs_iter *iter;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen ARRAY_TYPE(const_string) fnames;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen struct fs_delete_ctx ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *fname, *const *fnamep;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen int ret;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainen memset(&ctx, 0, sizeof(ctx));
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen ctx.fs = fs;
c93cd163f9c1d4b0ca29f49cbfdbf474caeef5bfTimo Sirainen ctx.path_prefix = path_prefix;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen ctx.files_count = I_MAX(async_count, 1);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ctx.files = t_new(struct fs_file *, ctx.files_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* delete subdirs first. all fs backends can't handle recursive
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lookups, so save the list first. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_array_init(&fnames, 8);
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen iter = fs_iter_init(fs, path_prefix, FS_ITER_FLAG_DIRS);
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen /* append "/" so that if FS_PROPERTY_DIRECTORIES is set,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen we'll include the "/" suffix in the filename when deleting
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen it. */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen fname = t_strconcat(fname, "/", NULL);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen array_append(&fnames, &fname, 1);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen }
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (fs_iter_deinit(&iter) < 0) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen i_error("fs_iter_deinit(%s) failed: %s",
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen path_prefix, fs_last_error(fs));
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen array_foreach(&fnames, fnamep) T_BEGIN {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen cmd_fs_delete_dir_recursive(fs, async_count,
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen t_strdup_printf("%s%s", path_prefix, *fnamep));
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen } T_END;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen /* delete files. again because we're doing this asynchronously finish
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen the iteration first. */
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen if ((fs_get_properties(fs) & FS_PROPERTY_DIRECTORIES) != 0) {
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen /* we need to explicitly delete also the directories */
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen } else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_clear(&fnames);
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen }
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen iter = fs_iter_init(fs, path_prefix, 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fname = t_strdup(fname);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_append(&fnames, &fname, 1);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen if (fs_iter_deinit(&iter) < 0) {
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen i_error("fs_iter_deinit(%s) failed: %s",
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen path_prefix, fs_last_error(fs));
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen }
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen array_foreach(&fnames, fnamep) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen T_BEGIN {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen ret = doveadm_fs_delete_async_fname(&ctx, *fnamep);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen } T_END;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (ret < 0)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen break;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen }
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen doveadm_fs_delete_async_finish(&ctx);
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen}
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainenstatic void
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainencmd_fs_delete_recursive(int argc, char *argv[], unsigned int async_count)
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen{
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen struct fs *fs;
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen struct fs_file *file;
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen const char *path;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen unsigned int path_len;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_delete);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen path = argv[0];
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen path_len = strlen(path);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (path_len > 0 && path[path_len-1] != '/')
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen path = t_strconcat(path, "/", NULL);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen cmd_fs_delete_dir_recursive(fs, async_count, path);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if ((fs_get_properties(fs) & FS_PROPERTY_DIRECTORIES) != 0) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* delete the root itself */
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen file = fs_file_init(fs, path, FS_OPEN_MODE_READONLY);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (fs_delete(file) < 0) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_error("fs_delete(%s) failed: %s",
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen fs_file_path(file), fs_file_last_error(file));
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs_file_deinit(&file);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen fs_deinit(&fs);
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainenstatic void cmd_fs_delete_paths(int argc, char *argv[],
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen unsigned int async_count)
b3bb775c6b735a7f6021dea799601fbfdb656e58Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen struct fs *fs;
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen struct fs_delete_ctx ctx;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen unsigned int i;
b3bb775c6b735a7f6021dea799601fbfdb656e58Timo Sirainen int ret;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs = cmd_fs_init(&argc, &argv, 0, cmd_fs_delete);
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen memset(&ctx, 0, sizeof(ctx));
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen ctx.fs = fs;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ctx.path_prefix = "";
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen ctx.files_count = I_MAX(async_count, 1);
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen ctx.files = t_new(struct fs_file *, ctx.files_count);
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen for (i = 0; argv[i] != NULL; i++) {
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen T_BEGIN {
7bd6001d84ecc1792ddfd54fe8efa63c509d90b1Timo Sirainen ret = doveadm_fs_delete_async_fname(&ctx, argv[i]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } T_END;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0)
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
9a56220167d02bbcb66a81b7553f4eb4da939945Timo Sirainen doveadm_fs_delete_async_finish(&ctx);
9a56220167d02bbcb66a81b7553f4eb4da939945Timo Sirainen fs_deinit(&fs);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void cmd_fs_delete(int argc, char *argv[])
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen bool recursive = FALSE;
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen unsigned int async_count = 0;
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen int c;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen while ((c = getopt(argc, argv, "Rn:")) > 0) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen switch (c) {
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen case 'R':
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen recursive = TRUE;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen break;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen case 'n':
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen if (str_to_uint(optarg, &async_count) < 0)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_fatal("Invalid -n parameter: %s", optarg);
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen break;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen default:
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen fs_cmd_help(cmd_fs_delete);
9a099a65160987349f441c82ab0e38f32b747adbTimo Sirainen }
9a099a65160987349f441c82ab0e38f32b747adbTimo Sirainen }
9a099a65160987349f441c82ab0e38f32b747adbTimo Sirainen argc -= optind-1; argv += optind-1;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (recursive)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_fs_delete_recursive(argc, argv, async_count);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen else
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_fs_delete_paths(argc, argv, async_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void cmd_fs_iter_full(int argc, char *argv[], enum fs_iter_flags flags,
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen doveadm_command_t *cmd)
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen{
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen struct fs *fs;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen struct fs_iter *iter;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen const char *fname;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd);
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen iter = fs_iter_init(fs, argv[0], flags);
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL)
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen printf("%s\n", fname);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fs_iter_deinit(&iter) < 0) {
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen i_error("fs_iter_deinit(%s) failed: %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen argv[0], fs_last_error(fs));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs_deinit(&fs);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic void cmd_fs_iter(int argc, char *argv[])
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen cmd_fs_iter_full(argc, argv, 0, cmd_fs_iter);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void cmd_fs_iter_dirs(int argc, char *argv[])
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_fs_iter_full(argc, argv, FS_ITER_FLAG_DIRS, cmd_fs_iter_dirs);
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen}
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainenstruct doveadm_cmd_ver2 doveadm_cmd_fs[] = {
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen{
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen .name = "fs get",
eae1d6e75713d3d658908ac39b719992e2f8a456Timo Sirainen .old_cmd = cmd_fs_get,
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen .usage = "<fs-driver> <fs-args> <path>",
38df0cacce475112991e60d796f8f2105c616f01Timo SirainenDOVEADM_CMD_PARAMS_START
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo SirainenDOVEADM_CMD_PARAMS_END
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen},
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen .name = "fs put",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen .old_cmd = cmd_fs_put,
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen .usage = "[-h <hash>] <fs-driver> <fs-args> <input path> <path>",
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo SirainenDOVEADM_CMD_PARAMS_START
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenDOVEADM_CMD_PARAM('h', "hash", CMD_PARAM_STR, 0)
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenDOVEADM_CMD_PARAM('\0', "input-path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAMS_END
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen},
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen{
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen .name = "fs copy",
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen .old_cmd = cmd_fs_copy,
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen .usage = "<fs-driver> <fs-args> <source path> <dest path>",
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenDOVEADM_CMD_PARAMS_START
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenDOVEADM_CMD_PARAM('\0', "source-path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAM('\0', "destination-path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenDOVEADM_CMD_PARAMS_END
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen},
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen{
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen .name = "fs stat",
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen .old_cmd = cmd_fs_stat,
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen .usage = "<fs-driver> <fs-args> <path>",
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAMS_START
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAMS_END
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen},
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen .name = "fs metadata",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen .old_cmd = cmd_fs_metadata,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen .usage = "<fs-driver> <fs-args> <path>",
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo SirainenDOVEADM_CMD_PARAMS_START
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5fb3bff645380804c9db2510940c41db6b8fdb01Timo SirainenDOVEADM_CMD_PARAMS_END
d22301419109ed4a38351715e6760011421dadecTimo Sirainen},
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen .name = "fs delete",
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen .old_cmd = cmd_fs_delete,
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen .usage = "[-R] [-n <count>] <fs-driver> <fs-args> <path> [<path> ...]",
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo SirainenDOVEADM_CMD_PARAMS_START
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo SirainenDOVEADM_CMD_PARAM('R', "recursive", CMD_PARAM_BOOL, 0)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('n', "sync-count", CMD_PARAM_INT64, 0)
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5fb3bff645380804c9db2510940c41db6b8fdb01Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo SirainenDOVEADM_CMD_PARAMS_END
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen},
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen{
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen .name = "fs iter",
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen .old_cmd = cmd_fs_iter,
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen .usage = "<fs-driver> <fs-args> <path>",
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAMS_START
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
7c449f545b10daa47027552f98d916a9805da662Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAMS_END
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen},
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen .name = "fs iter-dirs",
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen .old_cmd = cmd_fs_iter_dirs,
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen .usage = "<fs-driver> <fs-args> <path>",
7c449f545b10daa47027552f98d916a9805da662Timo SirainenDOVEADM_CMD_PARAMS_START
7c449f545b10daa47027552f98d916a9805da662Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
ff4bb2dfb5714eeb0408d3bb862de1646351d097Timo SirainenDOVEADM_CMD_PARAMS_END
b3bb775c6b735a7f6021dea799601fbfdb656e58Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen};
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen unsigned int i;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (doveadm_cmd_fs[i].old_cmd == cmd)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen help_ver2(&doveadm_cmd_fs[i]);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen }
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_unreached();
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid doveadm_register_fs_commands(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++)
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen doveadm_cmd_register_ver2(&doveadm_cmd_fs[i]);
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen