doveadm-fs.c revision ab0475b6fb7f7dfb0c622063b91c839d19d5aa62
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void cmd_fs_delete(int argc, char *argv[]);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic struct fs *
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainencmd_fs_init(int *argc, char **argv[], int own_arg_count, doveadm_command_t *cmd)
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 if (fs_init((*argv)[1], (*argv)[2], &fs_set, &fs, &error) < 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const unsigned char *data;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_get);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen i_error("%s doesn't exist", fs_file_path(file));
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen i_error("read(%s) failed: %m", fs_file_path(file));
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen hash = buffer_create_dynamic(pool_datastack_create(), 32);
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen i_fatal("Invalid -h parameter: Hash not in hex");
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_put);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE);
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");
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 hash_method_lookup(hash_method_sha256.name), hash->data);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen input = i_stream_create_file(src_path, IO_BLOCK_SIZE);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if ((ret = o_stream_send_istream(output, input)) < 0) {
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen if (fs_write_stream_finish(file, &output) < 0) {
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen i_error("fs_write_stream_finish() failed: %s",
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainenstatic void cmd_fs_copy(int argc, char *argv[])
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_copy);
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);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainenstatic void cmd_fs_stat(int argc, char *argv[])
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_stat);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen i_error("%s doesn't exist", fs_file_path(file));
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen fs_file_path(file), fs_file_last_error(file));
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainenstatic void cmd_fs_metadata(int argc, char *argv[])
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const struct fs_metadata *m;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_metadata);
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_error("%s doesn't exist", fs_file_path(file));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen fs_file_path(file), fs_file_last_error(file));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenstatic bool cmd_fs_delete_ctx_run(struct fs_delete_ctx *ctx)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen unsigned int i;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainencmd_fs_delete_dir_recursive(struct fs *fs, unsigned int async_count,
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen unsigned int i;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen ctx.files = t_new(struct fs_file *, ctx.files_count);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen /* delete subdirs first. all fs backends can't handle recursive
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen lookups, so save the list first. */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen iter = fs_iter_init(fs, path, FS_ITER_FLAG_DIRS);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
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 */
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen i_error("fs_wait_async() failed: %s", fs_last_error(fs));
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen while (doveadm_exit_code == 0 && cmd_fs_delete_ctx_run(&ctx)) {
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen i_error("fs_wait_async() failed: %s", fs_last_error(fs));
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainencmd_fs_delete_recursive(int argc, char *argv[], unsigned int async_count)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_delete);
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);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen fs_file_path(file), fs_file_last_error(file));
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainenstatic void cmd_fs_delete(int argc, char *argv[])
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen unsigned int async_count = 0;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen cmd_fs_delete_recursive(argc, argv, async_count);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_delete);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen i_error("%s doesn't exist", fs_file_path(file));
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen fs_file_path(file), fs_file_last_error(file));
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainenstatic void cmd_fs_iter_full(int argc, char *argv[], enum fs_iter_flags flags,
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainenstatic void cmd_fs_iter(int argc, char *argv[])
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenstatic void cmd_fs_iter_dirs(int argc, char *argv[])
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen cmd_fs_iter_full(argc, argv, FS_ITER_FLAG_DIRS, cmd_fs_iter_dirs);
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 Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen unsigned int i;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen unsigned int i;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++)