doveadm-fs.c revision 5592b04741577d014760097fc40f0f5276241754
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void cmd_fs_delete(int argc, char *argv[]);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic struct fs *
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainencmd_fs_init(int *argc, char **argv[], int own_arg_count, doveadm_command_t *cmd)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ssl_set.ca_dir = doveadm_settings->ssl_client_ca_dir;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ssl_set.ca_file = doveadm_settings->ssl_client_ca_file;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fs_init((*argv)[1], (*argv)[2], &fs_set, &fs, &error) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const unsigned char *data;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_get);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_error("read(%s) failed: %s", fs_file_path(file),
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash = buffer_create_dynamic(pool_datastack_create(), 32);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("Invalid -h parameter: Hash not in hex");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_put);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen else if (hash->used == hash_method_md5.digest_size) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if ((props & FS_PROPERTY_WRITE_HASH_MD5) == 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fs backend doesn't support MD5 hashes");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash_method_lookup(hash_method_md5.name), hash->data);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen } else if (hash->used == hash_method_sha256.digest_size) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if ((props & FS_PROPERTY_WRITE_HASH_SHA256) == 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_fatal("fs backend doesn't support SHA256 hashes");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen hash_method_lookup(hash_method_sha256.name), hash->data);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen input = i_stream_create_file(src_path, IO_BLOCK_SIZE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if ((ret = o_stream_send_istream(output, input)) < 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fs_write_stream_finish(file, &output) < 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_error("fs_write_stream_finish() failed: %s",
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void cmd_fs_copy(int argc, char *argv[])
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fs = cmd_fs_init(&argc, &argv, 2, cmd_fs_copy);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen src_file = fs_file_init(fs, src_path, FS_OPEN_MODE_READONLY);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen dest_file = fs_file_init(fs, dest_path, FS_OPEN_MODE_REPLACE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void cmd_fs_stat(int argc, char *argv[])
2abfef71398a61e5ed97c23a1ceb71461933ccb8Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_stat);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen fs_file_path(file), fs_file_last_error(file));
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenstatic void cmd_fs_metadata(int argc, char *argv[])
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct fs_metadata *m;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_metadata);
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen file = fs_file_init(fs, argv[0], FS_OPEN_MODE_READONLY);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("%s doesn't exist: %s", fs_file_path(file),
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen fs_file_path(file), fs_file_last_error(file));
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainenstatic int cmd_fs_delete_ctx_run(struct fs_delete_ctx *ctx)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen unsigned int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("%s doesn't exist: %s", fs_file_path(ctx->files[i]),
ea9fd7f876643e985946a2563140359064819b8eTimo Sirainenstatic int doveadm_fs_delete_async_fname(struct fs_delete_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen t_strdup_printf("%s%s", ctx->path_prefix, fname),
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen i_error("fs_wait_async() failed: %s", fs_last_error(ctx->fs));
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen return doveadm_fs_delete_async_fname(ctx, fname);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenstatic void doveadm_fs_delete_async_finish(struct fs_delete_ctx *ctx)
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen unsigned int i;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen while (doveadm_exit_code == 0 && cmd_fs_delete_ctx_run(ctx) > 0) {
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen i_error("fs_wait_async() failed: %s", fs_last_error(ctx->fs));
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainencmd_fs_delete_dir_recursive(struct fs *fs, unsigned int async_count,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ctx.files = t_new(struct fs_file *, ctx.files_count);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* delete subdirs first. all fs backends can't handle recursive
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lookups, so save the list first. */
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen iter = fs_iter_init(fs, path_prefix, FS_ITER_FLAG_DIRS);
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen /* append "/" so that if FS_PROPERTY_DIRECTORIES is set,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen we'll include the "/" suffix in the filename when deleting
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen t_strdup_printf("%s%s", path_prefix, *fnamep));
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen /* delete files. again because we're doing this asynchronously finish
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen the iteration first. */
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen if ((fs_get_properties(fs) & FS_PROPERTY_DIRECTORIES) != 0) {
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen /* we need to explicitly delete also the directories */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while ((fname = fs_iter_next(iter)) != NULL) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen ret = doveadm_fs_delete_async_fname(&ctx, *fnamep);
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainencmd_fs_delete_recursive(int argc, char *argv[], unsigned int async_count)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen fs = cmd_fs_init(&argc, &argv, 1, cmd_fs_delete);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen cmd_fs_delete_dir_recursive(fs, async_count, path);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if ((fs_get_properties(fs) & FS_PROPERTY_DIRECTORIES) != 0) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* delete the root itself */
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen file = fs_file_init(fs, path, FS_OPEN_MODE_READONLY);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen fs_file_path(file), fs_file_last_error(file));
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainenstatic void cmd_fs_delete_paths(int argc, char *argv[],
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen unsigned int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs = cmd_fs_init(&argc, &argv, 0, cmd_fs_delete);
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen ctx.files = t_new(struct fs_file *, ctx.files_count);
7bd6001d84ecc1792ddfd54fe8efa63c509d90b1Timo Sirainen ret = doveadm_fs_delete_async_fname(&ctx, argv[i]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void cmd_fs_delete(int argc, char *argv[])
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen unsigned int async_count = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_fs_delete_recursive(argc, argv, async_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void cmd_fs_iter_full(int argc, char *argv[], enum fs_iter_flags flags,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic void cmd_fs_iter(int argc, char *argv[])
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void cmd_fs_iter_dirs(int argc, char *argv[])
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_fs_iter_full(argc, argv, FS_ITER_FLAG_DIRS, cmd_fs_iter_dirs);
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen .usage = "[-h <hash>] <fs-driver> <fs-args> <input path> <path>",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenDOVEADM_CMD_PARAM('h', "hash", CMD_PARAM_STR, 0)
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenDOVEADM_CMD_PARAM('\0', "input-path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen .usage = "<fs-driver> <fs-args> <source path> <dest path>",
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo SirainenDOVEADM_CMD_PARAM('\0', "source-path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAM('\0', "destination-path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
43955c82f9f52c969c777b3da00bc170183dfdf2Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen .usage = "[-R] [-n <count>] <fs-driver> <fs-args> <path> [<path> ...]",
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo SirainenDOVEADM_CMD_PARAM('R', "recursive", CMD_PARAM_BOOL, 0)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('n', "sync-count", CMD_PARAM_INT64, 0)
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
5fb3bff645380804c9db2510940c41db6b8fdb01Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
7c449f545b10daa47027552f98d916a9805da662Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
7c449f545b10daa47027552f98d916a9805da662Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-driver", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "fs-args", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo SirainenDOVEADM_CMD_PARAM('\0', "path", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenstatic void fs_cmd_help(doveadm_command_t *cmd)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen unsigned int i;
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmd_fs); i++)