diff --git a/btrbk b/btrbk index 670ace8..abcd10b 100755 --- a/btrbk +++ b/btrbk @@ -82,104 +82,104 @@ my %config_options = ( # NOTE: the parser always maps "no" to undef # NOTE: keys "volume", "subvolume" and "target" are hardcoded # NOTE: files "." and "no" map to - timestamp_format => { default => "long", accept => [ "short", "long", "long-iso" ], context => [ "global", "volume", "subvolume" ] }, - snapshot_dir => { default => undef, accept_file => { relative => 1, absolute => 1 }, context => [ "global", "volume", "subvolume" ] }, - snapshot_name => { c_default => 1, accept_file => { name_only => 1 }, context => [ "subvolume" ], deny_glob_context => 1 }, # NOTE: defaults to the subvolume name (hardcoded) - snapshot_create => { default => "always", accept => [ "no", "always", "ondemand", "onchange" ], context => [ "global", "volume", "subvolume" ] }, - incremental => { default => "yes", accept => [ "yes", "no", "strict" ] }, - incremental_prefs => { default => \@incremental_prefs_default, accept => qr/$incremental_prefs_match/, split => $split_match }, - incremental_clones => { default => "yes", accept => [ "yes", "no" ] }, - incremental_resolve => { default => "mountpoint", accept => [ "mountpoint", "directory", "_all_accessible" ] }, + timestamp_format => { default => "long", accept => [qw( short long long-iso )], context => [qw( global volume subvolume )] }, + snapshot_dir => { default => undef, accept_file => { relative => 1, absolute => 1 }, context => [qw( global volume subvolume )] }, + snapshot_name => { c_default => 1, accept_file => { name_only => 1 }, context => [qw( subvolume )], deny_glob_context => 1 }, # NOTE: defaults to the subvolume name (hardcoded) + snapshot_create => { default => "always", accept => [qw( no always ondemand onchange )], context => [qw( global volume subvolume )] }, + incremental => { default => "yes", accept => [qw( yes no strict )] }, + incremental_prefs => { default => \@incremental_prefs_default, accept => [ qr/$incremental_prefs_match/ ], split => $split_match }, + incremental_clones => { default => "yes", accept => [qw( yes no )] }, + incremental_resolve => { default => "mountpoint", accept => [qw( mountpoint directory _all_accessible )] }, preserve_day_of_week => { default => "sunday", accept => [ (keys %day_of_week_map) ] }, preserve_hour_of_day => { default => 0, accept => [ (0..23) ] }, - snapshot_preserve => { default => undef, accept => [ "no" ], accept_preserve_matrix => 1, context => [ "global", "volume", "subvolume" ], }, - snapshot_preserve_min => { default => "all", accept => [ "all", "latest", qr/[1-9][0-9]*[hdwmy]/ ], context => [ "global", "volume", "subvolume" ], }, - target_preserve => { default => undef, accept => [ "no" ], accept_preserve_matrix => 1 }, - target_preserve_min => { default => "all", accept => [ "all", "latest", "no", qr/[0-9]+[hdwmy]/ ] }, - archive_preserve => { default => undef, accept => [ "no" ], accept_preserve_matrix => 1, context => [ "global" ] }, - archive_preserve_min => { default => "all", accept => [ "all", "latest", "no", qr/[0-9]+[hdwmy]/ ], context => [ "global" ] }, - btrfs_commit_delete => { default => undef, accept => [ "after", "each", "no" ] }, + snapshot_preserve => { default => undef, accept => [qw( no )], accept_preserve_matrix => 1, context => [qw( global volume subvolume )], }, + snapshot_preserve_min => { default => "all", accept => [qw( all latest ), qr/[1-9][0-9]*[hdwmy]/ ], context => [qw( global volume subvolume )], }, + target_preserve => { default => undef, accept => [qw( no )], accept_preserve_matrix => 1 }, + target_preserve_min => { default => "all", accept => [qw( all latest no ), qr/[0-9]+[hdwmy]/ ] }, + archive_preserve => { default => undef, accept => [qw( no )], accept_preserve_matrix => 1, context => [qw( global )] }, + archive_preserve_min => { default => "all", accept => [qw( all latest no ), qr/[0-9]+[hdwmy]/ ], context => [qw( global )] }, + btrfs_commit_delete => { default => undef, accept => [qw( after each no )] }, ssh_identity => { default => undef, accept_file => { absolute => 1 } }, ssh_user => { default => "root", accept => [ qr/[a-z_][a-z0-9_-]*/ ] }, - ssh_compression => { default => undef, accept => [ "yes", "no" ] }, + ssh_compression => { default => undef, accept => [qw( yes no )] }, ssh_cipher_spec => { default => "default", accept => [ qr/$ssh_cipher_match(,$ssh_cipher_match)*/ ] }, - transaction_log => { default => undef, accept => [ "no" ], accept_file => { absolute => 1 }, context => [ "global" ] }, - transaction_syslog => { default => undef, accept => [ "no", @syslog_facilities ], context => [ "global" ] }, - lockfile => { default => undef, accept => [ "no" ], accept_file => { absolute => 1 }, context => [ "global" ] }, + transaction_log => { default => undef, accept => [qw( no )], accept_file => { absolute => 1 }, context => [qw( global )] }, + transaction_syslog => { default => undef, accept => [qw( no ), @syslog_facilities ], context => [qw( global )] }, + lockfile => { default => undef, accept => [qw( no )], accept_file => { absolute => 1 }, context => [qw( global )] }, - rate_limit => { default => undef, accept => [ "no", qr/[0-9]+[kmgtKMGT]?/ ], require_bin => 'mbuffer' }, - rate_limit_remote => { default => undef, accept => [ "no", qr/[0-9]+[kmgtKMGT]?/ ] }, # NOTE: requires 'mbuffer' command on remote hosts - stream_buffer => { default => undef, accept => [ "no", qr/[0-9]+[kmgKMG%]?/ ], require_bin => 'mbuffer' }, - stream_buffer_remote => { default => undef, accept => [ "no", qr/[0-9]+[kmgKMG%]?/ ] }, # NOTE: requires 'mbuffer' command on remote hosts - stream_compress => { default => undef, accept => [ "no", (keys %compression) ] }, - stream_compress_level => { default => "default", accept => [ "default", qr/[0-9]+/ ] }, - stream_compress_long => { default => "default", accept => [ "default", qr/[0-9]+/ ] }, - stream_compress_threads => { default => "default", accept => [ "default", qr/[0-9]+/ ] }, - stream_compress_adapt => { default => undef, accept => [ "yes", "no" ] }, + rate_limit => { default => undef, accept => [qw( no ), qr/[0-9]+[kmgtKMGT]?/ ], require_bin => 'mbuffer' }, + rate_limit_remote => { default => undef, accept => [qw( no ), qr/[0-9]+[kmgtKMGT]?/ ] }, # NOTE: requires 'mbuffer' command on remote hosts + stream_buffer => { default => undef, accept => [qw( no ), qr/[0-9]+[kmgKMG%]?/ ], require_bin => 'mbuffer' }, + stream_buffer_remote => { default => undef, accept => [qw( no ), qr/[0-9]+[kmgKMG%]?/ ] }, # NOTE: requires 'mbuffer' command on remote hosts + stream_compress => { default => undef, accept => [qw( no ), (keys %compression) ] }, + stream_compress_level => { default => "default", accept => [qw( default ), qr/[0-9]+/ ] }, + stream_compress_long => { default => "default", accept => [qw( default ), qr/[0-9]+/ ] }, + stream_compress_threads => { default => "default", accept => [qw( default ), qr/[0-9]+/ ] }, + stream_compress_adapt => { default => undef, accept => [qw( yes no )] }, - raw_target_compress => { default => undef, accept => [ "no", (keys %compression) ] }, - raw_target_compress_level => { default => "default", accept => [ "default", qr/[0-9]+/ ] }, - raw_target_compress_long => { default => "default", accept => [ "default", qr/[0-9]+/ ] }, - raw_target_compress_threads => { default => "default", accept => [ "default", qr/[0-9]+/ ] }, - raw_target_encrypt => { default => undef, accept => [ "no", "gpg", "openssl_enc" ] }, + raw_target_compress => { default => undef, accept => [qw( no ), (keys %compression) ] }, + raw_target_compress_level => { default => "default", accept => [qw( default ), qr/[0-9]+/ ] }, + raw_target_compress_long => { default => "default", accept => [qw( default ), qr/[0-9]+/ ] }, + raw_target_compress_threads => { default => "default", accept => [qw( default ), qr/[0-9]+/ ] }, + raw_target_encrypt => { default => undef, accept => [qw( no gpg openssl_enc )] }, raw_target_block_size => { default => "128K", accept => [ qr/[0-9]+[kmgKMG]?/ ] }, - raw_target_split => { default => undef, accept => [ "no", qr/[0-9]+([kmgtpezyKMGTPEZY][bB]?)?/ ] }, + raw_target_split => { default => undef, accept => [qw( no ), qr/[0-9]+([kmgtpezyKMGTPEZY][bB]?)?/ ] }, gpg_keyring => { default => undef, accept_file => { absolute => 1 } }, gpg_recipient => { default => undef, accept => [ qr/[0-9a-zA-Z_@\+\-\.]+/ ] }, openssl_ciphername => { default => "aes-256-cbc", accept => [ qr/[0-9a-zA-Z\-]+/ ] }, - openssl_iv_size => { default => undef, accept => [ "no", qr/[0-9]+/ ] }, + openssl_iv_size => { default => undef, accept => [qw( no ), qr/[0-9]+/ ] }, openssl_keyfile => { default => undef, accept_file => { absolute => 1 } }, kdf_backend => { default => undef, accept_file => { absolute => 1 } }, kdf_keysize => { default => "32", accept => [ qr/[0-9]+/ ] }, - kdf_keygen => { default => "once", accept => [ "once", "each" ] }, + kdf_keygen => { default => "once", accept => [qw( once each )] }, group => { default => undef, accept => [ qr/$group_match/ ], allow_multiple => 1, split => $split_match }, - noauto => { default => undef, accept => [ "yes", "no" ] }, + noauto => { default => undef, accept => [qw( yes no )] }, - backend => { default => "btrfs-progs", accept => [ "btrfs-progs", "btrfs-progs-btrbk", "btrfs-progs-sudo", "btrfs-progs-doas" ] }, - backend_local => { default => undef, accept => [ "no", "btrfs-progs", "btrfs-progs-btrbk", "btrfs-progs-sudo", "btrfs-progs-doas" ] }, - backend_remote => { default => undef, accept => [ "no", "btrfs-progs", "btrfs-progs-btrbk", "btrfs-progs-sudo", "btrfs-progs-doas" ] }, - backend_local_user => { default => undef, accept => [ "no", "btrfs-progs", "btrfs-progs-btrbk", "btrfs-progs-sudo", "btrfs-progs-doas" ] }, + backend => { default => "btrfs-progs", accept => [qw( btrfs-progs btrfs-progs-btrbk btrfs-progs-sudo btrfs-progs-doas )] }, + backend_local => { default => undef, accept => [qw( no btrfs-progs btrfs-progs-btrbk btrfs-progs-sudo btrfs-progs-doas )] }, + backend_remote => { default => undef, accept => [qw( no btrfs-progs btrfs-progs-btrbk btrfs-progs-sudo btrfs-progs-doas )] }, + backend_local_user => { default => undef, accept => [qw( no btrfs-progs btrfs-progs-btrbk btrfs-progs-sudo btrfs-progs-doas )] }, - compat => { default => undef, accept => [ "no", "busybox" ] }, - compat_local => { default => undef, accept => [ "no", "busybox" ] }, - compat_remote => { default => undef, accept => [ "no", "busybox" ] }, - safe_commands => { default => undef, accept => [ "yes", "no" ], context => [ "global" ] }, + compat => { default => undef, accept => [qw( no busybox )] }, + compat_local => { default => undef, accept => [qw( no busybox )] }, + compat_remote => { default => undef, accept => [qw( no busybox )] }, + safe_commands => { default => undef, accept => [qw( yes no )], context => [qw( global )] }, - snapshot_qgroup_destroy => { default => undef, accept => [ "yes", "no" ], context => [ "global", "volume", "subvolume" ] }, - target_qgroup_destroy => { default => undef, accept => [ "yes", "no" ] }, - archive_qgroup_destroy => { default => undef, accept => [ "yes", "no" ], context => [ "global" ] }, + snapshot_qgroup_destroy => { default => undef, accept => [qw( yes no )], context => [qw( global volume subvolume )] }, + target_qgroup_destroy => { default => undef, accept => [qw( yes no )] }, + archive_qgroup_destroy => { default => undef, accept => [qw( yes no )], context => [qw( global )] }, - archive_exclude => { default => undef, accept_file => { wildcards => 1 }, allow_multiple => 1, context => [ "global" ] }, - archive_exclude_older => { default => undef, accept => [ "yes", "no" ] }, + archive_exclude => { default => undef, accept_file => { wildcards => 1 }, allow_multiple => 1, context => [qw( global )] }, + archive_exclude_older => { default => undef, accept => [qw( yes no )] }, - cache_dir => { default => undef, accept_file => { absolute => 1 }, allow_multiple => 1, context => [ "global" ] }, - ignore_extent_data_inline => { default => "yes", accept => [ "yes", "no" ] }, + cache_dir => { default => undef, accept_file => { absolute => 1 }, allow_multiple => 1, context => [qw( global )] }, + ignore_extent_data_inline => { default => "yes", accept => [qw( yes no )] }, - warn_unknown_targets => { default => undef, accept => [ "yes", "no" ] }, + warn_unknown_targets => { default => undef, accept => [qw( yes no )] }, # deprecated options - ssh_port => { default => "default", accept => [ "default", qr/[0-9]+/ ], + ssh_port => { default => "default", accept => [qw( default ), qr/[0-9]+/ ], deprecated => { DEFAULT => { warn => 'Please use "ssh://hostname[:port]" notation in the "volume" and "target" configuration lines.' } } }, - btrfs_progs_compat => { default => undef, accept => [ "yes", "no" ], + btrfs_progs_compat => { default => undef, accept => [qw( yes no )], deprecated => { DEFAULT => { ABORT => 1, warn => 'This feature has been dropped in btrbk-v0.23.0. Please update to newest btrfs-progs, AT LEAST >= $BTRFS_PROGS_MIN' } } }, - snapshot_preserve_daily => { default => 'all', accept => [ "all", qr/[0-9]+/ ], context => [ "global", "volume", "subvolume" ], + snapshot_preserve_daily => { default => 'all', accept => [qw( all ), qr/[0-9]+/ ], context => [qw( global volume subvolume )], deprecated => { DEFAULT => { FAILSAFE_PRESERVE => 1, warn => 'Please use "snapshot_preserve" and/or "snapshot_preserve_min"' } } }, - snapshot_preserve_weekly => { default => 0, accept => [ "all", qr/[0-9]+/ ], context => [ "global", "volume", "subvolume" ], + snapshot_preserve_weekly => { default => 0, accept => [qw( all ), qr/[0-9]+/ ], context => [qw( global volume subvolume )], deprecated => { DEFAULT => { FAILSAFE_PRESERVE => 1, warn => 'Please use "snapshot_preserve" and/or "snapshot_preserve_min"' } } }, - snapshot_preserve_monthly => { default => 'all', accept => [ "all", qr/[0-9]+/ ], context => [ "global", "volume", "subvolume" ], + snapshot_preserve_monthly => { default => 'all', accept => [qw( all ), qr/[0-9]+/ ], context => [qw( global volume subvolume )], deprecated => { DEFAULT => { FAILSAFE_PRESERVE => 1, warn => 'Please use "snapshot_preserve" and/or "snapshot_preserve_min"' } } }, - target_preserve_daily => { default => 'all', accept => [ "all", qr/[0-9]+/ ], + target_preserve_daily => { default => 'all', accept => [qw( all ), qr/[0-9]+/ ], deprecated => { DEFAULT => { FAILSAFE_PRESERVE => 1, warn => 'Please use "target_preserve" and/or "target_preserve_min"' } } }, - target_preserve_weekly => { default => 0, accept => [ "all", qr/[0-9]+/ ], + target_preserve_weekly => { default => 0, accept => [qw( all ), qr/[0-9]+/ ], deprecated => { DEFAULT => { FAILSAFE_PRESERVE => 1, warn => 'Please use "target_preserve" and/or "target_preserve_min"' } } }, - target_preserve_monthly => { default => 'all', accept => [ "all", qr/[0-9]+/ ], + target_preserve_monthly => { default => 'all', accept => [qw( all ), qr/[0-9]+/ ], deprecated => { DEFAULT => { FAILSAFE_PRESERVE => 1, warn => 'Please use "target_preserve" and/or "target_preserve_min"' } } }, - resume_missing => { default => "yes", accept => [ "yes", "no" ], + resume_missing => { default => "yes", accept => [qw( yes no )], deprecated => { yes => { warn => 'ignoring (missing backups are always resumed since btrbk v0.23.0)' }, no => { FAILSAFE_PRESERVE => 1, warn => 'Please use "target_preserve_min latest" and "target_preserve no" if you want to keep only the latest backup', } } }, - snapshot_create_always => { default => undef, accept => [ "yes", "no" ], + snapshot_create_always => { default => undef, accept => [qw( yes no )], deprecated => { yes => { warn => "Please use \"snapshot_create always\"", replace_key => "snapshot_create", replace_value => "always", @@ -190,7 +190,7 @@ my %config_options = ( } }, }, - receive_log => { default => undef, accept => [ "sidecar", "no" ], accept_file => { absolute => 1 }, + receive_log => { default => undef, accept => [qw( sidecar no )], accept_file => { absolute => 1 }, deprecated => { DEFAULT => { warn => "ignoring" } }, } );