From 8ce80db688328dc1ddeb893c933aeb1aa4c705b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Va=C5=A1ek?= <david.vasek@nic.cz> Date: Tue, 28 Jan 2025 15:16:10 +0100 Subject: [PATCH 1/4] ctl/backup: check that a backup/restore directory has been provided from ctl --- src/knot/ctl/commands.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/knot/ctl/commands.c b/src/knot/ctl/commands.c index 1f53014f7f..e992976a07 100644 --- a/src/knot/ctl/commands.c +++ b/src/knot/ctl/commands.c @@ -578,6 +578,9 @@ static int init_backup(ctl_args_t *args, bool restore_mode) const char *db_storage = conf_str(&db_storage_val); const char *backup_dir = args->data[KNOT_CTL_IDX_DATA]; + if (backup_dir == NULL) { + return KNOT_ENOPARAM; + } if (same_path(backup_dir, db_storage)) { char *msg = sprintf_alloc("%s the database storage directory not allowed", @@ -615,8 +618,7 @@ static int init_backup(ctl_args_t *args, bool restore_mode) // The present timer db size is not up-to-date, use the maximum one. conf_val_t timer_db_size = conf_db_param(conf(), C_TIMER_DB_MAX_SIZE); - int ret = zone_backup_init(restore_mode, filters, forced, - args->data[KNOT_CTL_IDX_DATA], + int ret = zone_backup_init(restore_mode, filters, forced, backup_dir, knot_lmdb_copy_size(&args->server->kaspdb), conf_int(&timer_db_size), knot_lmdb_copy_size(&args->server->journaldb), -- GitLab From d6c98a2957a5d6433f9897cc15152271843b3e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Va=C5=A1ek?= <david.vasek@nic.cz> Date: Tue, 28 Jan 2025 15:47:20 +0100 Subject: [PATCH 2/4] ctl/flush: report missing outdir value as missing rather than invalid --- src/knot/ctl/commands.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/knot/ctl/commands.c b/src/knot/ctl/commands.c index e992976a07..e8965ec7ba 100644 --- a/src/knot/ctl/commands.c +++ b/src/knot/ctl/commands.c @@ -522,9 +522,13 @@ static int zone_notify(zone_t *zone, _unused_ ctl_args_t *args) static int zone_flush(zone_t *zone, ctl_args_t *args) { if (MATCH_AND_FILTER(args, CTL_FILTER_FLUSH_OUTDIR)) { - rcu_read_lock(); - int ret = zone_dump_to_dir(conf(), zone, args->data[KNOT_CTL_IDX_DATA]); - rcu_read_unlock(); + int ret = KNOT_ENOPARAM; + const char *dir = args->data[KNOT_CTL_IDX_DATA]; + if (dir != NULL) { + rcu_read_lock(); + ret = zone_dump_to_dir(conf(), zone, dir); + rcu_read_unlock(); + } if (ret != KNOT_EOK) { log_zone_warning(zone->name, "failed to update zone file (%s)", knot_strerror(ret)); -- GitLab From 05648a83ac416a69836c00f92fee9a9bc75248e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Va=C5=A1ek?= <david.vasek@nic.cz> Date: Wed, 29 Jan 2025 16:52:00 +0100 Subject: [PATCH 3/4] ctl/backup: make common failure report reusable --- src/knot/ctl/commands.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/knot/ctl/commands.c b/src/knot/ctl/commands.c index e8965ec7ba..d8af6726cd 100644 --- a/src/knot/ctl/commands.c +++ b/src/knot/ctl/commands.c @@ -513,6 +513,19 @@ static int zone_retransfer(zone_t *zone, _unused_ ctl_args_t *args) return schedule_trigger(zone, args, ZONE_EVENT_REFRESH, true); } +static void common_failure(_unused_ ctl_args_t *args, int err, const char *msg) +{ + if (args->data[KNOT_CTL_IDX_ZONE] == NULL) { + log_ctl_error("%s", msg); + } else { + log_ctl_zone_str_error(args->data[KNOT_CTL_IDX_ZONE], "%s", msg); + } + + /* Warning: zone name in the control command params discarded here. */ + args->data[KNOT_CTL_IDX_ZONE] = NULL; + ctl_send_error(args, knot_strerror(err)); +} + static int zone_notify(zone_t *zone, _unused_ ctl_args_t *args) { zone_notifailed_clear(zone); @@ -725,18 +738,8 @@ static int zones_apply_backup(ctl_args_t *args, bool restore_mode) char *msg = sprintf_alloc("%s init failed (%s)", restore_mode ? "restore" : "backup", knot_strerror(ret)); - - if (args->data[KNOT_CTL_IDX_ZONE] == NULL) { - log_ctl_error("%s", msg); - } else { - log_ctl_zone_str_error(args->data[KNOT_CTL_IDX_ZONE], - "%s", msg); - } + common_failure(args, ret, msg); free (msg); - - /* Warning: zone name in the control command params discarded here. */ - args->data[KNOT_CTL_IDX_ZONE] = NULL; - ctl_send_error(args, knot_strerror(ret)); return KNOT_CTL_EZONE; } -- GitLab From da42dd4927edb3df7d029e7646269c61e080726a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Va=C5=A1ek?= <david.vasek@nic.cz> Date: Wed, 29 Jan 2025 17:38:34 +0100 Subject: [PATCH 4/4] ctl/flush: check params and the output directory once before actual flushing --- src/knot/ctl/commands.c | 52 ++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/src/knot/ctl/commands.c b/src/knot/ctl/commands.c index d8af6726cd..c95b6e8358 100644 --- a/src/knot/ctl/commands.c +++ b/src/knot/ctl/commands.c @@ -16,6 +16,7 @@ #include <string.h> #include <unistd.h> +#include <sys/stat.h> #include <sys/time.h> #include <time.h> #include <urcu.h> @@ -533,28 +534,51 @@ static int zone_notify(zone_t *zone, _unused_ ctl_args_t *args) } static int zone_flush(zone_t *zone, ctl_args_t *args) +{ + zone_set_flag(zone, ZONE_USER_FLUSH); + if (ctl_has_flag(args->data[KNOT_CTL_IDX_FLAGS], CTL_FLAG_FORCE)) { + zone_set_flag(zone, ZONE_FORCE_FLUSH); + } + + return schedule_trigger(zone, args, ZONE_EVENT_FLUSH, true); +} + +static int zone_flush_outdir(zone_t *zone, ctl_args_t *args) +{ + rcu_read_lock(); + int ret = zone_dump_to_dir(conf(), zone, args->data[KNOT_CTL_IDX_DATA]); + rcu_read_unlock(); + + if (ret != KNOT_EOK) { + log_zone_warning(zone->name, "failed to update zone file (%s)", + knot_strerror(ret)); + } + return ret; +} + +static int zones_apply_flush(ctl_args_t *args) { if (MATCH_AND_FILTER(args, CTL_FILTER_FLUSH_OUTDIR)) { - int ret = KNOT_ENOPARAM; const char *dir = args->data[KNOT_CTL_IDX_DATA]; - if (dir != NULL) { - rcu_read_lock(); - ret = zone_dump_to_dir(conf(), zone, dir); - rcu_read_unlock(); + if (dir == NULL) { + char *msg = "flush, output directory not specified"; + common_failure(args, KNOT_ENOPARAM, msg); + return KNOT_CTL_EZONE; } + int ret = make_path(dir, S_IRUSR | S_IWUSR | S_IXUSR | + S_IRGRP | S_IWGRP | S_IXGRP); if (ret != KNOT_EOK) { - log_zone_warning(zone->name, "failed to update zone file (%s)", - knot_strerror(ret)); + char *msg = sprintf_alloc("flush, failed to create output directory '%s' (%s)", + dir, knot_strerror(ret)); + common_failure(args, ret, msg); + free(msg); + return KNOT_CTL_EZONE; } - return ret; - } - zone_set_flag(zone, ZONE_USER_FLUSH); - if (ctl_has_flag(args->data[KNOT_CTL_IDX_FLAGS], CTL_FLAG_FORCE)) { - zone_set_flag(zone, ZONE_FORCE_FLUSH); + return zones_apply(args, zone_flush_outdir); } - return schedule_trigger(zone, args, ZONE_EVENT_FLUSH, true); + return zones_apply(args, zone_flush); } static void report_insufficient_backup(ctl_args_t *args, zone_backup_ctx_t *ctx) @@ -1878,7 +1902,7 @@ static int ctl_zone(ctl_args_t *args, ctl_cmd_t cmd) case CTL_ZONE_NOTIFY: return zones_apply(args, zone_notify); case CTL_ZONE_FLUSH: - return zones_apply(args, zone_flush); + return zones_apply_flush(args); case CTL_ZONE_BACKUP: return zones_apply_backup(args, false); case CTL_ZONE_RESTORE: -- GitLab