bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd);
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainenstatic void cmd_fs_delete(int argc, char *argv[]);
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomistatic void cmd_fs_getopt(int *argc, char **argv[])
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi i_fatal("fs_init: Add -- if you have - in arguments");
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic struct fs *
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainencmd_fs_init(int *argc, char **argv[], int own_arg_count, doveadm_command_t *cmd)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ssl_set.ca_dir = doveadm_settings->ssl_client_ca_dir;
56d1345c43bbd28c36b7faa85e4163bd9e874290Timo Sirainen ssl_set.ca_file = doveadm_settings->ssl_client_ca_file;
dfdcbff54e2be83e7f8f87c757dbbde6b3819500Aki Tuomi if (fs_init((*argv)[0], (*argv)[1], &fs_set, &fs, &error) < 0)
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_header("content", "content", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_get);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while ((ret = i_stream_read_more(input, &data, &size)) > 0) {
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
f79ba7136a322a10309e5dad9a22d568fe89fb59Timo Sirainen i_error("read(%s) failed: %s", fs_file_path(file),
4d981bcd01bd1dd5248095b0e59957949332657eTimo Sirainen i_fatal("Invalid -h parameter: Hash not in hex");
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_put);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE);
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 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 hash_method_lookup(hash_method_sha256.name), hash->data);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen input = i_stream_create_file(src_path, IO_BLOCK_SIZE);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (fs_write_stream_finish(file, &output) < 0) {
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_error("fs_write_stream_finish() failed: %s",
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_copy(int argc, char *argv[])
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_copy);
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 Sirainenstatic void cmd_fs_stat(int argc, char *argv[])
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_stat);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_formatted_set_format("%{path} size=%{size}");
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_header("size", "size", DOVEADM_PRINT_HEADER_FLAG_NUMBER);
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen fs_file_path(file), fs_file_last_error(file));
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainenstatic void cmd_fs_metadata(int argc, char *argv[])
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen const struct fs_metadata *m;
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_metadata);
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
967bcc77ff5077100391f5eb947e2cc51461f6baAki Tuomi doveadm_print_formatted_set_format("%{key}=%{value}\n");
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
a601cdf61506674a681195acfe57c9864bd3f7acTimo Sirainen fs_file_path(file), fs_file_last_error(file));
ab1e085cf10b68a7e6a8889156493a3369a194e9Timo Sirainenstatic int cmd_fs_delete_ctx_run(struct fs_delete_ctx *ctx)
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen unsigned int i;
3d8059535db10bacdb96025533d43e826f6762ebTimo Sirainen i_error("%s doesn't exist: %s", fs_file_path(ctx->files[i]),
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainenstatic int doveadm_fs_delete_async_fname(struct fs_delete_ctx *ctx,
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen unsigned int i;
01c4df2aded7cb44bbaf69d61bd6d9e496b919a4Timo Sirainen t_strdup_printf("%s%s", ctx->path_prefix, fname),
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen return doveadm_fs_delete_async_fname(ctx, fname);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainenstatic void doveadm_fs_delete_async_finish(struct fs_delete_ctx *ctx)
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen unsigned int i;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen while (doveadm_exit_code == 0 && cmd_fs_delete_ctx_run(ctx) > 0) {
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainencmd_fs_delete_dir_recursive(struct fs *fs, unsigned int async_count,
f86f7ec83f6626701137ad86fc7c7d431367ea83Timo Sirainen ctx.files = t_new(struct fs_file *, ctx.files_count);
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen /* delete subdirs first. all fs backends can't handle recursive
ca096c557fac1cf87dd5f129c202b2c1d990ff59Timo Sirainen lookups, so save the list first. */
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 t_strdup_printf("%s%s", path_prefix, *fnamep));
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 */
c58f46762024d6df2c5ef5590be75c8abbe7e5d7Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen ret = doveadm_fs_delete_async_fname(&ctx, *fnamep);
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainenstatic void cmd_fs_delete_recursive_path(struct fs *fs, const char *path,
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 fs_file_path(file), fs_file_last_error(file));
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainencmd_fs_delete_recursive(int argc, char *argv[], unsigned int async_count)
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen unsigned int i;
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen fs = cmd_fs_init(&argc, &argv, 0, cmd_fs_delete);
035d6e469a65b412e7f8574e1ef008d15c63d85aTimo Sirainen cmd_fs_delete_recursive_path(fs, argv[i], async_count);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainenstatic void cmd_fs_delete_paths(int argc, char *argv[],
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen unsigned int i;
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen fs = cmd_fs_init(&argc, &argv, 0, cmd_fs_delete);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen ctx.files = t_new(struct fs_file *, ctx.files_count);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainen ret = doveadm_fs_delete_async_fname(&ctx, argv[i]);
89f9c7bf3cc041de11974af9ac45f543e9761444Timo Sirainenstatic void cmd_fs_delete(int argc, char *argv[])
244d1dd1a501d1e4b53d8af9a2704640b276b7daTimo Sirainen cmd_fs_delete_recursive(argc, argv, async_count);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_iter_full(int argc, char *argv[], enum fs_iter_flags flags,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_iter(int argc, char *argv[])
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void cmd_fs_iter_dirs(int argc, char *argv[])
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen cmd_fs_iter_full(argc, argv, FS_ITER_FLAG_DIRS, cmd_fs_iter_dirs);
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 Tuomi .usage = "[-h <hash>] <fs-driver> <fs-args> <input path> <path>",
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 Tuomi .usage = "<fs-driver> <fs-args> <source path> <dest path>",
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_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_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 Tuomi .usage = "[-R] [-n <count>] <fs-driver> <fs-args> <path> [<path> ...]",
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_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_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)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen unsigned int i;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++) {
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen unsigned int i;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++)