bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen#include "lib.h"
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen#include "array.h"
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen#include "md5.h"
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen#include "sha2.h"
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen#include "hash-method.h"
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen#include "hex-binary.h"
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen#include "istream.h"
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen#include "ostream.h"
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen#include "iostream-ssl.h"
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen#include "fs-api.h"
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen#include "doveadm.h"
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi#include "doveadm-print.h"
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen#include <stdio.h>
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen#include <unistd.h>
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd);
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainenstatic void cmd_fs_delete(int argc, char *argv[]);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomistatic void cmd_fs_getopt(int *argc, char **argv[])
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi{
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi if (getopt(*argc, *argv, "") == '?')
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi i_fatal("fs_init: Add -- if you have - in arguments");
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi *argc -= optind;
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi *argv += optind;
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi}
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic struct fs *
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainencmd_fs_init(int *argc, char **argv[], int own_arg_count, doveadm_command_t *cmd)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct ssl_iostream_settings ssl_set;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs_settings fs_set;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs *fs;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen const char *error;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen if (own_arg_count > 0) {
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi if (*argc != 2 + own_arg_count)
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen fs_cmd_help(cmd);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen } else {
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi if (*argc <= 2)
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen fs_cmd_help(cmd);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen }
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ssl_set);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ssl_set.ca_dir = doveadm_settings->ssl_client_ca_dir;
56d1345c43bbd28c36b7faa85e4163bd9e874290Timo Sirainen ssl_set.ca_file = doveadm_settings->ssl_client_ca_file;
713a54f695b8ad63826d22ebbe52f55c347e8c88Timo Sirainen ssl_set.verbose = doveadm_debug;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&fs_set);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_set.ssl_client_set = &ssl_set;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_set.temp_dir = "/tmp";
6766440ffdd8d3ff99a1f732eef212813089bb81Timo Sirainen fs_set.base_dir = doveadm_settings->base_dir;
713a54f695b8ad63826d22ebbe52f55c347e8c88Timo Sirainen fs_set.debug = doveadm_debug;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi if (fs_init((*argv)[0], (*argv)[1], &fs_set, &fs, &error) < 0)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_fatal("fs_init() failed: %s", error);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi *argc += 2;
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi *argv += 2;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen return fs;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_get(int argc, char *argv[])
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs *fs;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs_file *file;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct istream *input;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen const unsigned char *data;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen size_t size;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ssize_t ret;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
f65486adb62eb4c817cfad2deaf8befea3012787Timo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_PAGER);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_header("content", "content", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi cmd_fs_getopt(&argc, &argv);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_get);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen input = fs_read_stream(file, IO_BLOCK_SIZE);
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while ((ret = i_stream_read_more(input, &data, &size)) > 0) {
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_stream(data, size);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_stream_skip(input, size);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen }
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_stream("", 0);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_assert(ret == -1);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (input->stream_errno == ENOENT) {
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
4c9caab4525a8d59f76e6943f99a73e4dc6e75f5Timo Sirainen i_stream_get_error(input));
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen } else if (input->stream_errno != 0) {
f79ba7136a322a10309e5dad9a22d568fe89fb59Timo Sirainen i_error("read(%s) failed: %s", fs_file_path(file),
4c9caab4525a8d59f76e6943f99a73e4dc6e75f5Timo Sirainen i_stream_get_error(input));
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen }
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_stream_unref(&input);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_file_deinit(&file);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_deinit(&fs);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_put(int argc, char *argv[])
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs *fs;
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen enum fs_properties props;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen const char *src_path, *dest_path;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs_file *file;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct istream *input;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct ostream *output;
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen buffer_t *hash = NULL;
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen int c;
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen while ((c = getopt(argc, argv, "h:")) > 0) {
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen switch (c) {
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen case 'h':
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi hash = t_buffer_create(32);
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen if (hex_to_binary(optarg, hash) < 0)
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen i_fatal("Invalid -h parameter: Hash not in hex");
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen break;
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen default:
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen fs_cmd_help(cmd_fs_put);
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen }
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen }
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi argc -= optind; argv += optind;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_put);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen src_path = argv[0];
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen dest_path = argv[1];
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE);
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen props = fs_get_properties(fs);
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen if (hash == NULL)
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen ;
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen else if (hash->used == hash_method_md5.digest_size) {
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen if ((props & FS_PROPERTY_WRITE_HASH_MD5) == 0)
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen i_fatal("fs backend doesn't support MD5 hashes");
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen fs_write_set_hash(file,
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen hash_method_lookup(hash_method_md5.name), hash->data);
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen } else if (hash->used == hash_method_sha256.digest_size) {
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen if ((props & FS_PROPERTY_WRITE_HASH_SHA256) == 0)
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen i_fatal("fs backend doesn't support SHA256 hashes");
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen fs_write_set_hash(file,
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen hash_method_lookup(hash_method_sha256.name), hash->data);
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen }
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen output = fs_write_stream(file);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen input = i_stream_create_file(src_path, IO_BLOCK_SIZE);
6f187ae85911f63cb87271246c68f3c13a0adb7bTimo Sirainen o_stream_nsend_istream(output, input);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_stream_destroy(&input);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (fs_write_stream_finish(file, &output) < 0) {
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_error("fs_write_stream_finish() failed: %s",
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_file_last_error(file));
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen }
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_file_deinit(&file);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_deinit(&fs);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_copy(int argc, char *argv[])
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs *fs;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs_file *src_file, *dest_file;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen const char *src_path, *dest_path;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi cmd_fs_getopt(&argc, &argv);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_copy);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen src_path = argv[0];
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen dest_path = argv[1];
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen src_file = fs_file_init(fs, src_path, FS_OPEN_MODE_READONLY);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen dest_file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (fs_copy(src_file, dest_file) == 0) ;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen else if (errno == ENOENT) {
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen i_error("%s doesn't exist: %s", src_path,
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen fs_last_error(fs));
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen } else {
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_error("fs_copy(%s, %s) failed: %s",
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen src_path, dest_path, fs_last_error(fs));
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen }
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_file_deinit(&src_file);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_file_deinit(&dest_file);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_deinit(&fs);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_stat(int argc, char *argv[])
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs *fs;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs_file *file;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct stat st;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi cmd_fs_getopt(&argc, &argv);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_stat);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_init(DOVEADM_PRINT_TYPE_FORMATTED);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_formatted_set_format("%{path} size=%{size}");
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_header_simple("path");
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_header("size", "size", DOVEADM_PRINT_HEADER_FLAG_NUMBER);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (fs_stat(file, &st) == 0) {
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print(fs_file_path(file));
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print(dec2str(st.st_size));
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen } else if (errno == ENOENT) {
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen fs_file_last_error(file));
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen } else {
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_error("fs_stat(%s) failed: %s",
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_file_path(file), fs_file_last_error(file));
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen }
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_file_deinit(&file);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_deinit(&fs);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainenstatic void cmd_fs_metadata(int argc, char *argv[])
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen{
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen struct fs *fs;
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen struct fs_file *file;
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen const struct fs_metadata *m;
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen const ARRAY_TYPE(fs_metadata) *metadata;
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi cmd_fs_getopt(&argc, &argv);
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_metadata);
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_init(DOVEADM_PRINT_TYPE_FORMATTED);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_formatted_set_format("%{key}=%{value}\n");
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_header_simple("key");
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_header_simple("value");
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen if (fs_get_metadata(file, &metadata) == 0) {
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi array_foreach(metadata, m) {
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print(m->key);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print(m->value);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi }
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen } else if (errno == ENOENT) {
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen fs_file_last_error(file));
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen } else {
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen i_error("fs_stat(%s) failed: %s",
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen fs_file_path(file), fs_file_last_error(file));
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen }
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen fs_file_deinit(&file);
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen fs_deinit(&fs);
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen}
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainenstruct fs_delete_ctx {
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen struct fs *fs;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen const char *path_prefix;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen unsigned int files_count;
f86f7ec83f6626701137ad86fc7c7d431367ea83Timo Sirainen struct fs_file **files;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen};
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen
ab1e085cf10b68a7e6a8889156493a3369a194e9Timo Sirainenstatic int cmd_fs_delete_ctx_run(struct fs_delete_ctx *ctx)
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen{
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen unsigned int i;
f942b7b96a5c3c6756a6ea7bc3de0cd01bcb07fbTimo Sirainen int ret = 0;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen for (i = 0; i < ctx->files_count; i++) {
f86f7ec83f6626701137ad86fc7c7d431367ea83Timo Sirainen if (ctx->files[i] == NULL)
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen ;
f86f7ec83f6626701137ad86fc7c7d431367ea83Timo Sirainen else if (fs_delete(ctx->files[i]) == 0)
f86f7ec83f6626701137ad86fc7c7d431367ea83Timo Sirainen fs_file_deinit(&ctx->files[i]);
f942b7b96a5c3c6756a6ea7bc3de0cd01bcb07fbTimo Sirainen else if (errno == EAGAIN) {
f942b7b96a5c3c6756a6ea7bc3de0cd01bcb07fbTimo Sirainen if (ret == 0)
f942b7b96a5c3c6756a6ea7bc3de0cd01bcb07fbTimo Sirainen ret = 1;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen } else if (errno == ENOENT) {
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen i_error("%s doesn't exist: %s", fs_file_path(ctx->files[i]),
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen fs_file_last_error(ctx->files[i]));
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen ret = -1;
f942b7b96a5c3c6756a6ea7bc3de0cd01bcb07fbTimo Sirainen } else {
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen i_error("fs_delete(%s) failed: %s",
f86f7ec83f6626701137ad86fc7c7d431367ea83Timo Sirainen fs_file_path(ctx->files[i]),
f86f7ec83f6626701137ad86fc7c7d431367ea83Timo Sirainen fs_file_last_error(ctx->files[i]));
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
f942b7b96a5c3c6756a6ea7bc3de0cd01bcb07fbTimo Sirainen ret = -1;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen }
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen }
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen return ret;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen}
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainenstatic int doveadm_fs_delete_async_fname(struct fs_delete_ctx *ctx,
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen const char *fname)
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen{
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen unsigned int i;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen int ret;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen for (i = 0; i < ctx->files_count; i++) {
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen if (ctx->files[i] != NULL)
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen continue;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen ctx->files[i] = fs_file_init(ctx->fs,
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen t_strdup_printf("%s%s", ctx->path_prefix, fname),
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen FS_OPEN_MODE_READONLY | FS_OPEN_FLAG_ASYNC |
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen FS_OPEN_FLAG_ASYNC_NOQUEUE);
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen fname = NULL;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen break;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen }
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen if ((ret = cmd_fs_delete_ctx_run(ctx)) < 0)
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen return -1;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen if (fname != NULL) {
d34b8a75f3b74e26adc85b6436d033b1dcfaf9daTimo Sirainen if (ret > 0)
d34b8a75f3b74e26adc85b6436d033b1dcfaf9daTimo Sirainen fs_wait_async(ctx->fs);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen return doveadm_fs_delete_async_fname(ctx, fname);
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen }
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen return 0;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen}
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainenstatic void doveadm_fs_delete_async_finish(struct fs_delete_ctx *ctx)
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen{
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen unsigned int i;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen while (doveadm_exit_code == 0 && cmd_fs_delete_ctx_run(ctx) > 0) {
d34b8a75f3b74e26adc85b6436d033b1dcfaf9daTimo Sirainen fs_wait_async(ctx->fs);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen }
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen for (i = 0; i < ctx->files_count; i++) {
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen if (ctx->files[i] != NULL)
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen fs_file_deinit(&ctx->files[i]);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen }
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen}
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainenstatic void
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainencmd_fs_delete_dir_recursive(struct fs *fs, unsigned int async_count,
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen const char *path_prefix)
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen{
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen struct fs_iter *iter;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen ARRAY_TYPE(const_string) fnames;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen struct fs_delete_ctx ctx;
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen const char *fname, *const *fnamep;
f942b7b96a5c3c6756a6ea7bc3de0cd01bcb07fbTimo Sirainen int ret;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ctx);
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen ctx.fs = fs;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen ctx.path_prefix = path_prefix;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen ctx.files_count = I_MAX(async_count, 1);
f86f7ec83f6626701137ad86fc7c7d431367ea83Timo Sirainen ctx.files = t_new(struct fs_file *, ctx.files_count);
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen /* delete subdirs first. all fs backends can't handle recursive
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen lookups, so save the list first. */
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen t_array_init(&fnames, 8);
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen iter = fs_iter_init(fs, path_prefix, FS_ITER_FLAG_DIRS);
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen /* append "/" so that if FS_PROPERTY_DIRECTORIES is set,
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen we'll include the "/" suffix in the filename when deleting
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen it. */
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen fname = t_strconcat(fname, "/", NULL);
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen array_append(&fnames, &fname, 1);
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen }
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen if (fs_iter_deinit(&iter) < 0) {
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen i_error("fs_iter_deinit(%s) failed: %s",
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen path_prefix, fs_last_error(fs));
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen }
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen array_foreach(&fnames, fnamep) T_BEGIN {
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen cmd_fs_delete_dir_recursive(fs, async_count,
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen t_strdup_printf("%s%s", path_prefix, *fnamep));
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen } T_END;
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen /* delete files. again because we're doing this asynchronously finish
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen the iteration first. */
d4b03b1b224603afbc2468f07ffb80cc872b1f9fTimo Sirainen if ((fs_get_properties(fs) & FS_PROPERTY_DIRECTORIES) != 0) {
d4b03b1b224603afbc2468f07ffb80cc872b1f9fTimo Sirainen /* we need to explicitly delete also the directories */
d4b03b1b224603afbc2468f07ffb80cc872b1f9fTimo Sirainen } else {
d4b03b1b224603afbc2468f07ffb80cc872b1f9fTimo Sirainen array_clear(&fnames);
d4b03b1b224603afbc2468f07ffb80cc872b1f9fTimo Sirainen }
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen iter = fs_iter_init(fs, path_prefix, 0);
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen fname = t_strdup(fname);
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen array_append(&fnames, &fname, 1);
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen }
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen if (fs_iter_deinit(&iter) < 0) {
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen i_error("fs_iter_deinit(%s) failed: %s",
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen path_prefix, fs_last_error(fs));
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen }
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen array_foreach(&fnames, fnamep) {
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen T_BEGIN {
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen ret = doveadm_fs_delete_async_fname(&ctx, *fnamep);
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen } T_END;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen if (ret < 0)
f942b7b96a5c3c6756a6ea7bc3de0cd01bcb07fbTimo Sirainen break;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen }
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen doveadm_fs_delete_async_finish(&ctx);
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen}
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainenstatic void cmd_fs_delete_recursive_path(struct fs *fs, const char *path,
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen unsigned int async_count)
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen{
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen struct fs_file *file;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t path_len;
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen path_len = strlen(path);
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen if (path_len > 0 && path[path_len-1] != '/')
f9ca41ec7a26e8e571e268ee5c8da2e5745a4ab0Timo Sirainen path = t_strconcat(path, "/", NULL);
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen cmd_fs_delete_dir_recursive(fs, async_count, path);
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen if ((fs_get_properties(fs) & FS_PROPERTY_DIRECTORIES) != 0) {
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen /* delete the root itself */
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen file = fs_file_init(fs, path, FS_OPEN_MODE_READONLY);
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen if (fs_delete(file) < 0) {
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen i_error("fs_delete(%s) failed: %s",
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen fs_file_path(file), fs_file_last_error(file));
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen }
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen fs_file_deinit(&file);
95c13a27352739261c53ecd23fe2f0c3d61aa06fTimo Sirainen }
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen}
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainenstatic void
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainencmd_fs_delete_recursive(int argc, char *argv[], unsigned int async_count)
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen{
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen struct fs *fs;
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen unsigned int i;
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen fs = cmd_fs_init(&argc, &argv, 0, cmd_fs_delete);
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen for (i = 0; argv[i] != NULL; i++)
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen cmd_fs_delete_recursive_path(fs, argv[i], async_count);
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen fs_deinit(&fs);
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen}
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainenstatic void cmd_fs_delete_paths(int argc, char *argv[],
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen unsigned int async_count)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs *fs;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen struct fs_delete_ctx ctx;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen unsigned int i;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen int ret;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen fs = cmd_fs_init(&argc, &argv, 0, cmd_fs_delete);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ctx);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen ctx.fs = fs;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen ctx.path_prefix = "";
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen ctx.files_count = I_MAX(async_count, 1);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen ctx.files = t_new(struct fs_file *, ctx.files_count);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen for (i = 0; argv[i] != NULL; i++) {
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen T_BEGIN {
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen ret = doveadm_fs_delete_async_fname(&ctx, argv[i]);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen } T_END;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen if (ret < 0)
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen break;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen }
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen doveadm_fs_delete_async_finish(&ctx);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen fs_deinit(&fs);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen}
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainenstatic void cmd_fs_delete(int argc, char *argv[])
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen{
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen bool recursive = FALSE;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen unsigned int async_count = 0;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen int c;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen while ((c = getopt(argc, argv, "Rn:")) > 0) {
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen switch (c) {
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen case 'R':
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen recursive = TRUE;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen break;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen case 'n':
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen if (str_to_uint(optarg, &async_count) < 0)
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen i_fatal("Invalid -n parameter: %s", optarg);
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen break;
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen default:
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen fs_cmd_help(cmd_fs_delete);
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen }
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen }
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi argc -= optind; argv += optind;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen if (recursive)
244d1dd1a501d1e4b53d8af9a2704640b276b7daTimo Sirainen cmd_fs_delete_recursive(argc, argv, async_count);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen else
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen cmd_fs_delete_paths(argc, argv, async_count);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_iter_full(int argc, char *argv[], enum fs_iter_flags flags,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen doveadm_command_t *cmd)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs *fs;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct fs_iter *iter;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen const char *fname;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi cmd_fs_getopt(&argc, &argv);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_init(DOVEADM_PRINT_TYPE_FORMATTED);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_formatted_set_format("%{path}\n");
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_header_simple("path");
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen iter = fs_iter_init(fs, argv[0], flags);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi while ((fname = fs_iter_next(iter)) != NULL) {
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print(fname);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi }
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (fs_iter_deinit(&iter) < 0) {
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_error("fs_iter_deinit(%s) failed: %s",
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen argv[0], fs_last_error(fs));
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen }
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_deinit(&fs);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_iter(int argc, char *argv[])
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen cmd_fs_iter_full(argc, argv, 0, cmd_fs_iter);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_iter_dirs(int argc, char *argv[])
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen cmd_fs_iter_full(argc, argv, FS_ITER_FLAG_DIRS, cmd_fs_iter_dirs);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
5592b04741577d014760097fc40f0f5276241754Aki Tuomistruct doveadm_cmd_ver2 doveadm_cmd_fs[] = {
5592b04741577d014760097fc40f0f5276241754Aki Tuomi{
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .name = "fs get",
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .old_cmd = cmd_fs_get,
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .usage = "<fs-driver> <fs-args> <path>",
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_START
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_END
5592b04741577d014760097fc40f0f5276241754Aki Tuomi},
5592b04741577d014760097fc40f0f5276241754Aki Tuomi{
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .name = "fs put",
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .old_cmd = cmd_fs_put,
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .usage = "[-h <hash>] <fs-driver> <fs-args> <input path> <path>",
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_START
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('h', "hash", CMD_PARAM_STR, 0)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "input-path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_END
5592b04741577d014760097fc40f0f5276241754Aki Tuomi},
5592b04741577d014760097fc40f0f5276241754Aki Tuomi{
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .name = "fs copy",
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .old_cmd = cmd_fs_copy,
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .usage = "<fs-driver> <fs-args> <source path> <dest path>",
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_START
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "source-path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "destination-path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_END
5592b04741577d014760097fc40f0f5276241754Aki Tuomi},
5592b04741577d014760097fc40f0f5276241754Aki Tuomi{
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .name = "fs stat",
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .old_cmd = cmd_fs_stat,
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .usage = "<fs-driver> <fs-args> <path>",
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_START
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_END
5592b04741577d014760097fc40f0f5276241754Aki Tuomi},
5592b04741577d014760097fc40f0f5276241754Aki Tuomi{
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .name = "fs metadata",
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .old_cmd = cmd_fs_metadata,
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .usage = "<fs-driver> <fs-args> <path>",
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_START
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_END
5592b04741577d014760097fc40f0f5276241754Aki Tuomi},
5592b04741577d014760097fc40f0f5276241754Aki Tuomi{
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .name = "fs delete",
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .old_cmd = cmd_fs_delete,
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .usage = "[-R] [-n <count>] <fs-driver> <fs-args> <path> [<path> ...]",
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_START
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('R', "recursive", CMD_PARAM_BOOL, 0)
a18da4410dcd47ab8d9b40c09a76a54fa55b9c86Timo SirainenDOVEADM_CMD_PARAM('n', "max-parallel", CMD_PARAM_INT64, 0)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_END
5592b04741577d014760097fc40f0f5276241754Aki Tuomi},
5592b04741577d014760097fc40f0f5276241754Aki Tuomi{
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .name = "fs iter",
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .old_cmd = cmd_fs_iter,
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .usage = "<fs-driver> <fs-args> <path>",
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_START
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_END
5592b04741577d014760097fc40f0f5276241754Aki Tuomi},
5592b04741577d014760097fc40f0f5276241754Aki Tuomi{
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .name = "fs iter-dirs",
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .old_cmd = cmd_fs_iter_dirs,
5592b04741577d014760097fc40f0f5276241754Aki Tuomi .usage = "<fs-driver> <fs-args> <path>",
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_START
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5592b04741577d014760097fc40f0f5276241754Aki TuomiDOVEADM_CMD_PARAMS_END
5592b04741577d014760097fc40f0f5276241754Aki Tuomi}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen};
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen unsigned int i;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++) {
5592b04741577d014760097fc40f0f5276241754Aki Tuomi if (doveadm_cmd_fs[i].old_cmd == cmd)
5592b04741577d014760097fc40f0f5276241754Aki Tuomi help_ver2(&doveadm_cmd_fs[i]);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen }
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_unreached();
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenvoid doveadm_register_fs_commands(void)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen{
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen unsigned int i;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++)
5592b04741577d014760097fc40f0f5276241754Aki Tuomi doveadm_cmd_register_ver2(&doveadm_cmd_fs[i]);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen}