doveadm-fs.c revision ab0475b6fb7f7dfb0c622063b91c839d19d5aa62
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen#include "array.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "md5.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "sha2.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "hash-method.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "hex-binary.h"
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen#include "istream.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "ostream.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "iostream-ssl.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "fs-api.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "doveadm.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <stdio.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <unistd.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void cmd_fs_delete(int argc, char *argv[]);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic struct fs *
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainencmd_fs_init(int *argc, char **argv[], int own_arg_count, doveadm_command_t *cmd)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct ssl_iostream_settings ssl_set;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct fs_settings fs_set;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct fs *fs;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen const char *error;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen if (*argc != 3 + own_arg_count)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fs_cmd_help(cmd);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen memset(&ssl_set, 0, sizeof(ssl_set));
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ssl_set.ca_dir = doveadm_settings->ssl_client_ca_dir;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ssl_set.ca_file = doveadm_settings->ssl_client_ca_file;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ssl_set.verbose = doveadm_debug;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen memset(&fs_set, 0, sizeof(fs_set));
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen fs_set.ssl_client_set = &ssl_set;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen fs_set.temp_dir = "/tmp";
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen fs_set.base_dir = doveadm_settings->base_dir;
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen fs_set.debug = doveadm_debug;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (fs_init((*argv)[1], (*argv)[2], &fs_set, &fs, &error) < 0)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen i_fatal("fs_init() failed: %s", error);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *argc += 3;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *argv += 3;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return fs;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void cmd_fs_get(int argc, char *argv[])
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct fs *fs;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct fs_file *file;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct istream *input;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const unsigned char *data;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen size_t size;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ssize_t ret;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_get);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen input = fs_read_stream(file, IO_BLOCK_SIZE);
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fwrite(data, 1, size, stdout);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_stream_skip(input, size);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_assert(ret == -1);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (input->stream_errno == ENOENT) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen i_error("%s doesn't exist", fs_file_path(file));
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen } else if (input->stream_errno != 0) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen i_error("read(%s) failed: %m", fs_file_path(file));
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_stream_unref(&input);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fs_file_deinit(&file);
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen fs_deinit(&fs);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void cmd_fs_put(int argc, char *argv[])
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen{
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen struct fs *fs;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen enum fs_properties props;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen const char *src_path, *dest_path;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen struct fs_file *file;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen struct istream *input;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen struct ostream *output;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen buffer_t *hash = NULL;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen off_t ret;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen int c;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen while ((c = getopt(argc, argv, "h:")) > 0) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen switch (c) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen case 'h':
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen hash = buffer_create_dynamic(pool_datastack_create(), 32);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (hex_to_binary(optarg, hash) < 0)
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen i_fatal("Invalid -h parameter: Hash not in hex");
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen break;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen default:
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen fs_cmd_help(cmd_fs_put);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen argc -= optind-1; argv += optind-1;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_put);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen src_path = argv[0];
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen dest_path = argv[1];
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen props = fs_get_properties(fs);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (hash == NULL)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen ;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen else if (hash->used == hash_method_md5.digest_size) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if ((props & FS_PROPERTY_WRITE_HASH_MD5) == 0)
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen i_fatal("fs backend doesn't support MD5 hashes");
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen fs_write_set_hash(file,
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen hash_method_lookup(hash_method_md5.name), hash->data);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen } else if (hash->used == hash_method_sha256.digest_size) {
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen if ((props & FS_PROPERTY_WRITE_HASH_SHA256) == 0)
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen i_fatal("fs backend doesn't support SHA256 hashes");
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen fs_write_set_hash(file,
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen hash_method_lookup(hash_method_sha256.name), hash->data);
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen }
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen output = fs_write_stream(file);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen input = i_stream_create_file(src_path, IO_BLOCK_SIZE);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if ((ret = o_stream_send_istream(output, input)) < 0) {
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if (output->stream_errno != 0)
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen i_error("write(%s) failed: %m", dest_path);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen else
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen i_error("read(%s) failed: %m", src_path);
5d4855d7b4dcffb6975ed8e3c9c376dac74e5c8aTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_stream_destroy(&input);
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen if (fs_write_stream_finish(file, &output) < 0) {
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen i_error("fs_write_stream_finish() failed: %s",
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen fs_file_last_error(file));
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fs_file_deinit(&file);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fs_deinit(&fs);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainenstatic void cmd_fs_copy(int argc, char *argv[])
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct fs *fs;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct fs_file *src_file, *dest_file;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen const char *src_path, *dest_path;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_copy);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen src_path = argv[0];
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen dest_path = argv[1];
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen src_file = fs_file_init(fs, src_path, FS_OPEN_MODE_READONLY);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen dest_file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (fs_copy(src_file, dest_file) == 0) ;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen else if (errno == ENOENT) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen i_error("%s doesn't exist", src_path);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen } else {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_error("fs_copy(%s, %s) failed: %s",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen src_path, dest_path, fs_last_error(fs));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen fs_file_deinit(&src_file);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen fs_file_deinit(&dest_file);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen fs_deinit(&fs);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen}
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainenstatic void cmd_fs_stat(int argc, char *argv[])
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen{
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen struct fs *fs;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen struct fs_file *file;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen struct stat st;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_stat);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen if (fs_stat(file, &st) == 0) {
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen printf("%s size=%lld\n", fs_file_path(file),
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen (long long)st.st_size);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen } else if (errno == ENOENT) {
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen i_error("%s doesn't exist", fs_file_path(file));
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen } else {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen i_error("fs_stat(%s) failed: %s",
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen fs_file_path(file), fs_file_last_error(file));
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen }
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen fs_file_deinit(&file);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fs_deinit(&fs);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainenstatic void cmd_fs_metadata(int argc, char *argv[])
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct fs *fs;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct fs_file *file;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const struct fs_metadata *m;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen const ARRAY_TYPE(fs_metadata) *metadata;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_metadata);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen if (fs_get_metadata(file, &metadata) == 0) {
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen array_foreach(metadata, m)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen printf("%s=%s\n", m->key, m->value);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen } else if (errno == ENOENT) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_error("%s doesn't exist", fs_file_path(file));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen } else {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen i_error("fs_stat(%s) failed: %s",
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen fs_file_path(file), fs_file_last_error(file));
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen }
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen fs_file_deinit(&file);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen fs_deinit(&fs);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen}
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenstruct fs_delete_ctx {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen unsigned int files_count;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct fs_file **files;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen};
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenstatic bool cmd_fs_delete_ctx_run(struct fs_delete_ctx *ctx)
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen{
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen unsigned int i;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen bool ret = FALSE;
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen for (i = 0; i < ctx->files_count; i++) {
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen if (ctx->files[i] == NULL)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen ;
4376643cd2c7110e752c09f838f2c4eee6ed8ac6Timo Sirainen else if (fs_delete(ctx->files[i]) == 0)
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen fs_file_deinit(&ctx->files[i]);
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen else if (errno == EAGAIN)
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen ret = TRUE;
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen else {
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen i_error("fs_delete(%s) failed: %s",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fs_file_path(ctx->files[i]),
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen fs_file_last_error(ctx->files[i]));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen }
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return ret;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen}
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainencmd_fs_delete_dir_recursive(struct fs *fs, unsigned int async_count,
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen const char *path)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen struct fs_iter *iter;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ARRAY_TYPE(const_string) fnames;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct fs_delete_ctx ctx;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *fname, *const *fnamep;
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen unsigned int i;
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen memset(&ctx, 0, sizeof(ctx));
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ctx.files_count = I_MAX(async_count, 1);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ctx.files = t_new(struct fs_file *, ctx.files_count);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen /* delete subdirs first. all fs backends can't handle recursive
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen lookups, so save the list first. */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen t_array_init(&fnames, 8);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen iter = fs_iter_init(fs, path, FS_ITER_FLAG_DIRS);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen fname = t_strdup(fname);
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen array_append(&fnames, &fname, 1);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen if (fs_iter_deinit(&iter) < 0) {
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen i_error("fs_iter_deinit(%s) failed: %s",
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen path, fs_last_error(fs));
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen array_foreach(&fnames, fnamep) T_BEGIN {
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen cmd_fs_delete_dir_recursive(fs, async_count,
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen t_strdup_printf("%s/%s", path, *fnamep));
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen } T_END;
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* delete files. again because we're doing this asynchronously finish
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen the iteration first. */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if ((fs_get_properties(fs) & FS_PROPERTY_DIRECTORIES) != 0) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen /* we need to explicitly delete also the directories */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen } else {
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen array_clear(&fnames);
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen }
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen iter = fs_iter_init(fs, path, 0);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen fname = t_strdup(fname);
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen array_append(&fnames, &fname, 1);
430c0b0c370bebeeceba2e206be76bc134742f41Timo Sirainen }
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen if (fs_iter_deinit(&iter) < 0) {
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen i_error("fs_iter_deinit(%s) failed: %s",
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen path, fs_last_error(fs));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen array_foreach(&fnames, fnamep) T_BEGIN {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen fname = *fnamep;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen retry:
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen for (i = 0; i < ctx.files_count; i++) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (ctx.files[i] != NULL)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen continue;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen ctx.files[i] = fs_file_init(fs,
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen t_strdup_printf("%s/%s", path, fname),
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen FS_OPEN_MODE_READONLY | FS_OPEN_FLAG_ASYNC |
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen FS_OPEN_FLAG_ASYNC_NOQUEUE);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen fname = NULL;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen break;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen cmd_fs_delete_ctx_run(&ctx);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen if (fname != NULL) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (fs_wait_async(fs) < 0) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen i_error("fs_wait_async() failed: %s", fs_last_error(fs));
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen break;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen goto retry;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen } T_END;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen while (doveadm_exit_code == 0 && cmd_fs_delete_ctx_run(&ctx)) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (fs_wait_async(fs) < 0) {
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen i_error("fs_wait_async() failed: %s", fs_last_error(fs));
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen break;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen for (i = 0; i < ctx.files_count; i++) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (ctx.files[i] != NULL)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen fs_file_deinit(&ctx.files[i]);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenstatic void
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainencmd_fs_delete_recursive(int argc, char *argv[], unsigned int async_count)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen{
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct fs *fs;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct fs_file *file;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen const char *path;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_delete);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen path = argv[0];
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen cmd_fs_delete_dir_recursive(fs, async_count, path);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if ((fs_get_properties(fs) & FS_PROPERTY_DIRECTORIES) != 0) {
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen /* delete the root itself */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen file = fs_file_init(fs, path, FS_OPEN_MODE_READONLY);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (fs_delete(file) < 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_error("fs_delete(%s) failed: %s",
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen fs_file_path(file), fs_file_last_error(file));
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fs_file_deinit(&file);
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fs_deinit(&fs);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainenstatic void cmd_fs_delete(int argc, char *argv[])
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen{
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen struct fs *fs;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen struct fs_file *file;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen bool recursive = FALSE;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen unsigned int async_count = 0;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen int c;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen while ((c = getopt(argc, argv, "Rn:")) > 0) {
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen switch (c) {
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen case 'R':
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen recursive = TRUE;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case 'n':
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen if (str_to_uint(optarg, &async_count) < 0)
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen i_fatal("Invalid -n parameter: %s", optarg);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen default:
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen fs_cmd_help(cmd_fs_delete);
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen }
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen }
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen argc -= optind-1; argv += optind-1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (recursive) {
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen cmd_fs_delete_recursive(argc, argv, async_count);
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen return;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_delete);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen if (fs_delete(file) == 0)
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen ;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen else if (errno == ENOENT) {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen i_error("%s doesn't exist", fs_file_path(file));
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen doveadm_exit_code = DOVEADM_EX_NOTFOUND;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen } else {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen i_error("fs_delete(%s) failed: %s",
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen fs_file_path(file), fs_file_last_error(file));
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen doveadm_exit_code = EX_TEMPFAIL;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen }
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen fs_file_deinit(&file);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen fs_deinit(&fs);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainenstatic void cmd_fs_iter_full(int argc, char *argv[], enum fs_iter_flags flags,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen doveadm_command_t *cmd)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct fs *fs;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen struct fs_iter *iter;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen const char *fname;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen iter = fs_iter_init(fs, argv[0], flags);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL)
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen printf("%s\n", fname);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (fs_iter_deinit(&iter) < 0) {
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen i_error("fs_iter_deinit(%s) failed: %s",
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen argv[0], fs_last_error(fs));
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen }
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen fs_deinit(&fs);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen}
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainenstatic void cmd_fs_iter(int argc, char *argv[])
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen{
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen cmd_fs_iter_full(argc, argv, 0, cmd_fs_iter);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen}
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenstatic void cmd_fs_iter_dirs(int argc, char *argv[])
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen cmd_fs_iter_full(argc, argv, FS_ITER_FLAG_DIRS, cmd_fs_iter_dirs);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstruct doveadm_cmd doveadm_cmd_fs[] = {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen { cmd_fs_get, "fs get", "<fs-driver> <fs-args> <path>" },
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen { cmd_fs_put, "fs put", "[-h <hash>] <fs-driver> <fs-args> <input path> <path>" },
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen { cmd_fs_copy, "fs copy", "<fs-driver> <fs-args> <source path> <dest path>" },
7cba14a4c3beb026a2862ee50d24c554fa713329Timo Sirainen { cmd_fs_stat, "fs stat", "<fs-driver> <fs-args> <path>" },
7cba14a4c3beb026a2862ee50d24c554fa713329Timo Sirainen { cmd_fs_metadata, "fs metadata", "<fs-driver> <fs-args> <path>" },
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen { cmd_fs_delete, "fs delete", "[-R] [-n <count>] <fs-driver> <fs-args> <path>" },
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen { cmd_fs_iter, "fs iter", "<fs-driver> <fs-args> <path>" },
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen { cmd_fs_iter_dirs, "fs iter-dirs", "<fs-driver> <fs-args> <path>" },
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen};
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen unsigned int i;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (doveadm_cmd_fs[i].cmd == cmd)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen help(&doveadm_cmd_fs[i]);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen i_unreached();
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenvoid doveadm_register_fs_commands(void)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen unsigned int i;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen doveadm_register_cmd(&doveadm_cmd_fs[i]);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen