From: Arvin Schnell Date: Mon, 13 Oct 2025 12:35:17 +0000 (+0200) Subject: - redesigned target snapshot detection in snbk X-Git-Tag: v0.13.1~77^2 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1062%2Fhead;p=thirdparty%2Fsnapper.git - redesigned target snapshot detection in snbk --- diff --git a/client/snbk/BackupConfig.cc b/client/snbk/BackupConfig.cc index 7a819333..661b5041 100644 --- a/client/snbk/BackupConfig.cc +++ b/client/snbk/BackupConfig.cc @@ -75,9 +75,8 @@ namespace snapper get_child_nodes(json_file.get_root(), "receive-options", receive_options); get_child_value(json_file.get_root(), "target-btrfs-bin", target_btrfs_bin); - get_child_value(json_file.get_root(), "target-findmnt-bin", target_findmnt_bin); + get_child_value(json_file.get_root(), "target-ls-bin", target_ls_bin); get_child_value(json_file.get_root(), "target-mkdir-bin", target_mkdir_bin); - get_child_value(json_file.get_root(), "target-realpath-bin", target_realpath_bin); get_child_value(json_file.get_root(), "target-rm-bin", target_rm_bin); get_child_value(json_file.get_root(), "target-rmdir-bin", target_rmdir_bin); } diff --git a/client/snbk/BackupConfig.h b/client/snbk/BackupConfig.h index 935c6d61..f92c3d37 100644 --- a/client/snbk/BackupConfig.h +++ b/client/snbk/BackupConfig.h @@ -75,9 +75,8 @@ namespace snapper vector receive_options; string target_btrfs_bin = BTRFS_BIN; - string target_findmnt_bin = FINDMNT_BIN; + string target_ls_bin = LS_BIN; string target_mkdir_bin = MKDIR_BIN; - string target_realpath_bin = REALPATH_BIN; string target_rm_bin = RM_BIN; string target_rmdir_bin = RMDIR_BIN; diff --git a/client/snbk/CmdBtrfs.cc b/client/snbk/CmdBtrfs.cc index 37db965f..89f680f2 100644 --- a/client/snbk/CmdBtrfs.cc +++ b/client/snbk/CmdBtrfs.cc @@ -22,9 +22,7 @@ #include -#include #include -#include #include "snapper/SnapperTmpl.h" #include "snapper/SystemCmd.h" @@ -40,124 +38,6 @@ namespace snapper using namespace std; - CmdBtrfsSubvolumeList::CmdBtrfsSubvolumeList(const string& btrfs_bin, const Shell& shell, const string& mount_point) - { - SystemCmd::Args cmd_args = { btrfs_bin, "subvolume", "list", "-a", "-puqR", "--", mount_point }; - SystemCmd cmd(shellify(shell, cmd_args)); - - if (cmd.retcode() != 0) - { - y2err("command '" << cmd.cmd() << "' failed: " << cmd.retcode()); - for (const string& tmp : cmd.get_stdout()) - y2err(tmp); - for (const string& tmp : cmd.get_stderr()) - y2err(tmp); - - SN_THROW(Exception("'btrfs subvolume list' failed")); - } - - parse(cmd.get_stdout()); - } - - - void - CmdBtrfsSubvolumeList::parse(const vector& lines) - { - for (const string& line : lines) - { - Entry entry; - - string::size_type pos1 = line.find("ID "); - if (pos1 == string::npos) - SN_THROW(Exception("could not find 'id' in 'btrfs subvolume list' output")); - line.substr(pos1 + strlen("ID ")) >> entry.id; - - string::size_type pos2 = line.find(" parent "); - if (pos2 == string::npos) - SN_THROW(Exception("could not find 'parent' in 'btrfs subvolume list' output")); - line.substr(pos2 + strlen(" parent ")) >> entry.parent_id; - - // Subvolume can already be deleted, in which case parent is "0" - // (and path "DELETED"). That is a temporary state. - if (entry.parent_id == 0) - continue; - - string::size_type pos3 = line.find(" path "); - if (pos3 == string::npos) - SN_THROW(Exception("could not find 'path' in 'btrfs subvolume list' output")); - entry.path = line.substr(pos3 + strlen(" path ")); - if (boost::starts_with(entry.path, "/")) - entry.path.erase(0, strlen("/")); - - string::size_type pos4 = line.find(" uuid "); - if (pos4 == string::npos) - SN_THROW(Exception("could not find 'uuid' in 'btrfs subvolume list' output")); - line.substr(pos4 + strlen(" uuid ")) >> entry.uuid; - - string::size_type pos5 = line.find(" parent_uuid "); - if (pos5 == string::npos) - SN_THROW(Exception("could not find 'parent_uuid' in 'btrfs subvolume list' output")); - line.substr(pos5 + strlen(" parent_uuid ")) >> entry.parent_uuid; - if (entry.parent_uuid == "-") - entry.parent_uuid = ""; - - string::size_type pos6 = line.find(" received_uuid "); - if (pos6 == string::npos) - SN_THROW(Exception("could not find 'received_uuid' in 'btrfs subvolume list' output")); - line.substr(pos6 + strlen(" received_uuid ")) >> entry.received_uuid; - if (entry.received_uuid == "-") - entry.received_uuid = ""; - - data.push_back(entry); - } - - // No way to get read-only flag. Only showing read-only snapshots does not help. - - y2mil(*this); - } - - - CmdBtrfsSubvolumeList::const_iterator - CmdBtrfsSubvolumeList::find_entry_by_path(const string& path) const - { - for (const_iterator it = data.begin(); it != data.end(); ++it) - { - if (it->path == path) - return it; - } - - return data.end(); - } - - - std::ostream& - operator<<(std::ostream& s, const CmdBtrfsSubvolumeList& cmd_btrfs_subvolume_list) - { - for (const CmdBtrfsSubvolumeList::Entry& entry : cmd_btrfs_subvolume_list) - s << entry; - - return s; - } - - - std::ostream& - operator<<(std::ostream& s, const CmdBtrfsSubvolumeList::Entry& entry) - { - s << "id:" << entry.id << " parent-id:" << entry.parent_id - << " path:" << entry.path << " uuid:" << entry.uuid; - - if (!entry.parent_uuid.empty()) - s << " parent-uuid:" << entry.parent_uuid; - - if (!entry.received_uuid.empty()) - s << " received-uuid:" << entry.received_uuid; - - s << '\n'; - - return s; - } - - CmdBtrfsSubvolumeShow::CmdBtrfsSubvolumeShow(const string& btrfs_bin, const Shell& shell, const string& mount_point) { SystemCmd::Args cmd_args = { btrfs_bin, "subvolume", "show", "--", mount_point }; diff --git a/client/snbk/CmdBtrfs.h b/client/snbk/CmdBtrfs.h index 61e0243e..4a94a7d9 100644 --- a/client/snbk/CmdBtrfs.h +++ b/client/snbk/CmdBtrfs.h @@ -35,56 +35,6 @@ namespace snapper using std::vector; - /** - * Class to probe for btrfs subvolumes: Call "btrfs subvolume list - * ". - */ - class CmdBtrfsSubvolumeList - { - public: - - static const long top_level_id = 5; - static const long unknown_id = -1; - - CmdBtrfsSubvolumeList(const string& btrfs_bin, const Shell& shell, const string& mount_point); - - /** - * Entry for every subvolume (unfortunately except the top-level). - * - * Caution: parent_id and parent_uuid are something completely - * different - not just different ways to specify the - * "parent". - */ - struct Entry - { - long id = unknown_id; - long parent_id = unknown_id; - string path; - string uuid; - string parent_uuid; - string received_uuid; - }; - - typedef vector::value_type value_type; - typedef vector::const_iterator const_iterator; - - const_iterator begin() const { return data.begin(); } - const_iterator end() const { return data.end(); } - - const_iterator find_entry_by_path(const string& path) const; - - friend std::ostream& operator<<(std::ostream& s, const CmdBtrfsSubvolumeList& cmd_btrfs_subvolume_list); - friend std::ostream& operator<<(std::ostream& s, const Entry& entry); - - private: - - void parse(const vector& lines); - - vector data; - - }; - - /** * Class to probe for btrfs subvolume information: Call "btrfs subvolume * show ". diff --git a/client/snbk/CmdFindmnt.cc b/client/snbk/CmdFindmnt.cc deleted file mode 100644 index ea603ce0..00000000 --- a/client/snbk/CmdFindmnt.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2024 SUSE LLC - * - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, contact Novell, Inc. - * - * To contact Novell about this file by physical or electronic mail, you may - * find current contact information at www.novell.com. - */ - - -#include "CmdFindmnt.h" -#include "JsonFile.h" - -#include "snapper/SystemCmd.h" -#include "snapper/SnapperDefines.h" -#include "snapper/Exception.h" -#include "snapper/LoggerImpl.h" - - -namespace snapper -{ - - CmdFindmnt::CmdFindmnt(const string& findmnt_bin, const Shell& shell, const string& path) - : path(path) - { - SystemCmd::Args cmd_args = { findmnt_bin, "--json", "--target", path }; - SystemCmd cmd(shellify(shell, cmd_args)); - - if (cmd.retcode() != 0) - { - y2err("command '" << cmd.cmd() << "' failed: " << cmd.retcode()); - for (const string& tmp : cmd.get_stdout()) - y2err(tmp); - for (const string& tmp : cmd.get_stderr()) - y2err(tmp); - - SN_THROW(Exception("'findmnt' failed")); - } - - parse_json(cmd.get_stdout()); - } - - - void - CmdFindmnt::parse_json(const vector& lines) - { - JsonFile json_file(lines); - - vector tmp1; - - if (!get_child_nodes(json_file.get_root(), "filesystems", tmp1)) - SN_THROW(Exception("\"filesystems\" not found in json output of 'findmnt'")); - - for (json_object* tmp2 : tmp1) - { - if (!get_child_value(tmp2, "source", source)) - SN_THROW(Exception("\"source\" not found or invalid")); - - if (!get_child_value(tmp2, "target", target)) - SN_THROW(Exception("\"target\" not found or invalid")); - } - - y2mil(*this); - } - - - std::ostream& - operator<<(std::ostream& s, const CmdFindmnt& cmd_findmnt) - { - s << "path:" << cmd_findmnt.path << " source:" << cmd_findmnt.source - << " target:" << cmd_findmnt.target; - - return s; - } - -} diff --git a/client/snbk/CmdFindmnt.h b/client/snbk/CmdFindmnt.h deleted file mode 100644 index 9a251419..00000000 --- a/client/snbk/CmdFindmnt.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2024 SUSE LLC - * - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, contact Novell, Inc. - * - * To contact Novell about this file by physical or electronic mail, you may - * find current contact information at www.novell.com. - */ - - -#ifndef SNAPPER_CMD_FINDMNT_H -#define SNAPPER_CMD_FINDMNT_H - - -#include "Shell.h" - - -namespace snapper -{ - - using std::string; - using std::vector; - - - /** - * Class to probe for mount points: Call "findmnt --target ". - */ - class CmdFindmnt - { - public: - - CmdFindmnt(const string& findmnt_bin, const Shell& shell, const string& path); - - const string& get_source() const { return source; } - const string& get_target() const { return target; } - - friend std::ostream& operator<<(std::ostream& s, const CmdFindmnt& cmd_findmnt); - - private: - - void parse_json(const vector& lines); - - const string path; - - string source; - string target; - - }; - -} - -#endif diff --git a/client/snbk/CmdRealpath.cc b/client/snbk/CmdLs.cc similarity index 66% rename from client/snbk/CmdRealpath.cc rename to client/snbk/CmdLs.cc index 991e7b98..05eaa00b 100644 --- a/client/snbk/CmdRealpath.cc +++ b/client/snbk/CmdLs.cc @@ -1,5 +1,6 @@ /* - * Copyright (c) 2024 SUSE LLC + * Copyright (c) [2004-2015] Novell, Inc. + * Copyright (c) [2016-2025] SUSE LLC * * All Rights Reserved. * @@ -20,21 +21,20 @@ */ -#include "CmdRealpath.h" - +#include "snapper/SnapperTmpl.h" #include "snapper/SystemCmd.h" -#include "snapper/SnapperDefines.h" #include "snapper/Exception.h" #include "snapper/LoggerImpl.h" +#include "CmdLs.h" namespace snapper { - CmdRealpath::CmdRealpath(const string& realpath_bin, const Shell& shell, const string& path) + CmdLs::CmdLs(const string& ls_bin, const Shell& shell, const string& path) : path(path) { - SystemCmd::Args cmd_args = { realpath_bin, "--canonicalize-existing", "--", path }; + SystemCmd::Args cmd_args = { ls_bin, "-1", "--sort=none", path }; SystemCmd cmd(shellify(shell, cmd_args)); if (cmd.retcode() != 0) @@ -45,29 +45,26 @@ namespace snapper for (const string& tmp : cmd.get_stderr()) y2err(tmp); - SN_THROW(Exception("'realpath' failed")); + SN_THROW(Exception("'ls' failed")); } parse(cmd.get_stdout()); + + y2mil(*this); } void - CmdRealpath::parse(const vector& lines) + CmdLs::parse(const vector& lines) { - if (lines.size() != 1) - SN_THROW(Exception("failed to parse output of 'realpath'")); - - realpath = lines[0]; - - y2mil(*this); + entries = lines; } std::ostream& - operator<<(std::ostream& s, const CmdRealpath& cmd_realpath) + operator<<(std::ostream& s, const CmdLs& cms_ls) { - s << "path:" << cmd_realpath.path << " realpath:" << cmd_realpath.realpath; + s << "path:" << cms_ls.path << " entries:" << cms_ls.entries << '\n'; return s; } diff --git a/client/snbk/CmdRealpath.h b/client/snbk/CmdLs.h similarity index 64% rename from client/snbk/CmdRealpath.h rename to client/snbk/CmdLs.h index c69afb62..d69c15ca 100644 --- a/client/snbk/CmdRealpath.h +++ b/client/snbk/CmdLs.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2024 SUSE LLC + * Copyright (c) [2004-2015] Novell, Inc. + * Copyright (c) [2016-2025] SUSE LLC * * All Rights Reserved. * @@ -20,8 +21,8 @@ */ -#ifndef SNAPPER_CMD_REALPATH_H -#define SNAPPER_CMD_REALPATH_H +#ifndef SNAPPER_CMD_LS_H +#define SNAPPER_CMD_LS_H #include "Shell.h" @@ -29,23 +30,25 @@ namespace snapper { - using std::string; using std::vector; /** - * Class to probe realpath: Call "realpath ". + * A sequence of file names found in a pathname. */ - class CmdRealpath + class CmdLs { public: - CmdRealpath(const string& realpath_bin, const Shell& shell, const string& path); + CmdLs(const string& ls_bin, const Shell& shell, const string& path); + + typedef vector::const_iterator const_iterator; - const string& get_realpath() const { return realpath; } + const_iterator begin() const { return entries.begin(); } + const_iterator end() const { return entries.end(); } - friend std::ostream& operator<<(std::ostream& s, const CmdRealpath& cmd_realpath); + friend std::ostream& operator<<(std::ostream& s, const CmdLs& cmd_ls); private: @@ -53,7 +56,7 @@ namespace snapper const string path; - string realpath; + vector entries; }; diff --git a/client/snbk/Makefile.am b/client/snbk/Makefile.am index a1c245b5..4a0f06ad 100644 --- a/client/snbk/Makefile.am +++ b/client/snbk/Makefile.am @@ -19,8 +19,7 @@ snbk_SOURCES = \ GlobalOptions.cc GlobalOptions.h \ Shell.cc Shell.h \ CmdBtrfs.cc CmdBtrfs.h \ - CmdFindmnt.cc CmdFindmnt.h \ - CmdRealpath.cc CmdRealpath.h \ + CmdLs.cc CmdLs.h \ JsonFile.cc JsonFile.h snbk_LDADD = \ diff --git a/client/snbk/TheBigThing.cc b/client/snbk/TheBigThing.cc index 3c57fed0..1bcf9003 100644 --- a/client/snbk/TheBigThing.cc +++ b/client/snbk/TheBigThing.cc @@ -34,8 +34,7 @@ #include "../utils/text.h" #include "CmdBtrfs.h" -#include "CmdFindmnt.h" -#include "CmdRealpath.h" +#include "CmdLs.h" #include "BackupConfig.h" #include "TheBigThing.h" @@ -71,10 +70,10 @@ namespace snapper const string num_string = to_string(num); - // Create directory on target. + // Create directory on target. No failure if it already exists (option --parents). - SystemCmd::Args cmd1_args = { backup_config.target_mkdir_bin, "--", backup_config.target_path + "/" + - num_string }; + SystemCmd::Args cmd1_args = { backup_config.target_mkdir_bin, "--parents", "--", backup_config.target_path + + "/" + num_string }; SystemCmd cmd1(shellify(backup_config.get_target_shell(), cmd1_args)); if (cmd1.retcode() != 0) { @@ -320,112 +319,94 @@ namespace snapper if (verbose) cout << _("Probing target snapshots.") << endl; - // In case the target-path is a symbolic link (or includes things like "/../") we - // need a lookup for the realpath first. - - CmdRealpath cmd_realpath(backup_config.target_realpath_bin, shell_target, backup_config.target_path); - const string target_path = cmd_realpath.get_realpath(); - - CmdFindmnt cmd_findmnt(backup_config.target_findmnt_bin, shell_target, target_path); - const string mount_point = cmd_findmnt.get_target(); - - if (target_path.size() < mount_point.size()) - SN_THROW(Exception("unsupported target-path setup")); + /* Using 'btrfs subvolume list' instead of 'ls' is much more complicated. */ - if (!boost::starts_with(target_path, mount_point)) - SN_THROW(Exception("unsupported target-path setup")); - - CmdBtrfsSubvolumeList target_snapshots(backup_config.target_btrfs_bin, shell_target, mount_point); - - string start; - if (target_path != mount_point) - start = target_path.substr(mount_point.size() + 1) + "/"; - - static const regex subvol_regex("\\[(.*?)\\]"); - smatch subvol; - if (regex_search(cmd_findmnt.get_source(), subvol, subvol_regex)) - start = subvol[1].str().substr(1) + "/" + start; + CmdLs cmd_ls(backup_config.target_ls_bin, shell_target, backup_config.target_path); if (verbose) cout << _("Probing extra information for target snapshots.") << endl; - static const regex num_regex("([0-9]+)/snapshot", regex::extended); + static const regex num_regex("[0-9]+", regex::extended); - for (const CmdBtrfsSubvolumeList::Entry& target_snapshot : target_snapshots) + for (const string& num_string : cmd_ls) { - if (!boost::starts_with(target_snapshot.path, start)) - continue; - - string path = target_snapshot.path.substr(start.size()); - - smatch match; - - if (!regex_match(path, match, num_regex)) + if (!regex_match(num_string, num_regex)) { - string error = sformat(_("Invalid subvolume path '%s' on target."), path.c_str()); + string error = sformat(_("Invalid subvolume path '%s' on target."), num_string.c_str()); SN_THROW(Exception(error)); } - unsigned int num = stoi(match[1]); + unsigned int num = stoi(num_string); + vector::iterator it = find(num); // Query additional information (receive-uuid, read-only) from btrfs. - CmdBtrfsSubvolumeShow y(backup_config.target_btrfs_bin, shell_target, target_path + "/" + path); - - bool is_read_only = y.is_read_only(); - if (!is_read_only) + try { - y2deb(num << " not read-only, maybe interrupted transfer"); - } + CmdBtrfsSubvolumeShow extra(backup_config.target_btrfs_bin, shell_target, backup_config.target_path + + "/" + num_string + "/" SNAPSHOT_NAME); - vector::iterator it = find(num); - if (it != end()) - { - // Wrong receive-uuid can happen when a snapshots is transferred, then removed - // and a new one with the same number is generated. + bool is_read_only = extra.is_read_only(); + if (!is_read_only) + { + y2deb(num << " not read-only, maybe interrupted transfer"); + } - // When a snapshot is restored using btrfs send and receive the received - // uuid of the source is identical to the received uuid of the target - - // not the uuid of the target. In that case the target is also valid. + if (it != end()) + { + // Wrong receive-uuid can happen when a snapshots is transferred, then removed + // and a new one with the same number is generated. - bool correct_uuid = false; + // When a snapshot is restored using btrfs send and receive the received + // uuid of the source is identical to the received uuid of the target - + // not the uuid of the target. In that case the target is also valid. - if (!y.get_received_uuid().empty()) - { - if (it->source_uuid == y.get_received_uuid()) - correct_uuid = true; - else if (it->source_received_uuid == y.get_received_uuid()) - correct_uuid = true; + bool correct_uuid = false; - if (!correct_uuid) + if (!extra.get_received_uuid().empty()) { - y2deb(num << " wrong uuid, maybe snapshot number reuse"); + if (it->source_uuid == extra.get_received_uuid()) + correct_uuid = true; + else if (it->source_received_uuid == extra.get_received_uuid()) + correct_uuid = true; + + if (!correct_uuid) + { + y2deb(num << " wrong uuid, maybe snapshot number reuse"); + } } - } - if (correct_uuid && is_read_only) - it->target_state = TheBigThing::TargetState::VALID; + if (correct_uuid && is_read_only) + it->target_state = TheBigThing::TargetState::VALID; + else + it->target_state = TheBigThing::TargetState::INVALID; + } else - it->target_state = TheBigThing::TargetState::INVALID; - } - else - { - TheBigThing the_big_thing(num); + { + TheBigThing the_big_thing(num); - // Cannot check received-uuid so assume valid. + // Cannot check received-uuid so assume valid. - if (is_read_only) - the_big_thing.target_state = TheBigThing::TargetState::VALID; - else - the_big_thing.target_state = TheBigThing::TargetState::INVALID; + if (is_read_only) + the_big_thing.target_state = TheBigThing::TargetState::VALID; + else + the_big_thing.target_state = TheBigThing::TargetState::INVALID; - it = the_big_things.insert(the_big_things.end(), the_big_thing); + it = the_big_things.insert(the_big_things.end(), the_big_thing); + } + + it->target_uuid = extra.get_uuid(); + it->target_parent_uuid = extra.get_parent_uuid(); + it->target_received_uuid = extra.get_received_uuid(); + it->target_creation_time = extra.get_creation_time(); } + catch (const Exception& e) + { + SN_CAUGHT(e); - it->target_uuid = y.get_uuid(); - it->target_parent_uuid = y.get_parent_uuid(); - it->target_received_uuid = y.get_received_uuid(); - it->target_creation_time = y.get_creation_time(); + // target_state is plain and simply missing or the snapshot is not even in + // the list. + } } } diff --git a/client/snbk/cmd-list-configs.cc b/client/snbk/cmd-list-configs.cc index b2e9d69b..9106ee83 100644 --- a/client/snbk/cmd-list-configs.cc +++ b/client/snbk/cmd-list-configs.cc @@ -54,8 +54,8 @@ namespace snapper enum class Column { NAME, CONFIG, TARGET_MODE, AUTOMATIC, SOURCE_PATH, TARGET_PATH, SSH_HOST, - SSH_USER, SSH_PORT, SSH_IDENTITY, TARGET_BTRFS_BIN, TARGET_FINDMNT_BIN, - TARGET_MKDIR_BIN, TARGET_REALPATH_BIN, TARGET_RM_BIN, TARGET_RMDIR_BIN + SSH_USER, SSH_PORT, SSH_IDENTITY, TARGET_BTRFS_BIN, TARGET_LS_BIN, + TARGET_MKDIR_BIN, TARGET_RM_BIN, TARGET_RMDIR_BIN }; @@ -97,15 +97,12 @@ namespace snapper case Column::TARGET_BTRFS_BIN: return Cell(_("Target btrfs bin")); - case Column::TARGET_FINDMNT_BIN: - return Cell(_("Target findmnt Bin")); + case Column::TARGET_LS_BIN: + return Cell(_("Target ls Bin")); case Column::TARGET_MKDIR_BIN: return Cell(_("Target mkdir bin")); - case Column::TARGET_REALPATH_BIN: - return Cell(_("Target realpath bin")); - case Column::TARGET_RM_BIN: return Cell(_("Target rm bin")); @@ -164,15 +161,12 @@ namespace snapper case Column::TARGET_BTRFS_BIN: return backup_config.target_btrfs_bin; - case Column::TARGET_FINDMNT_BIN: - return backup_config.target_findmnt_bin; + case Column::TARGET_LS_BIN: + return backup_config.target_ls_bin; case Column::TARGET_MKDIR_BIN: return backup_config.target_mkdir_bin; - case Column::TARGET_REALPATH_BIN: - return backup_config.target_realpath_bin; - case Column::TARGET_RM_BIN: return backup_config.target_rm_bin; @@ -302,8 +296,8 @@ namespace snapper const vector all_columns = { Column::NAME, Column::CONFIG, Column::TARGET_MODE, Column::AUTOMATIC, Column::SOURCE_PATH, Column::TARGET_PATH, Column::SSH_HOST, Column::SSH_USER, Column::SSH_PORT, Column::SSH_IDENTITY, Column::TARGET_BTRFS_BIN, - Column::TARGET_FINDMNT_BIN, Column::TARGET_MKDIR_BIN, Column::TARGET_REALPATH_BIN, - Column::TARGET_RM_BIN, Column::TARGET_RMDIR_BIN + Column::TARGET_LS_BIN, Column::TARGET_MKDIR_BIN, Column::TARGET_RM_BIN, + Column::TARGET_RMDIR_BIN }; switch (global_options.output_format()) @@ -327,8 +321,8 @@ namespace snapper const vector EnumInfo::names({ "name", "config", "target-mode", "automatic", "source-path", "target-path", "ssh-host", - "ssh-user", "ssh-port", "ssh-identity", "target-btrfs-bin", "target-findmnt-bin", - "target-mkdir-bin", "target-realpath-bin", "target-rm-bin", "target-rmdir-bin" + "ssh-user", "ssh-port", "ssh-identity", "target-btrfs-bin", "target-ls-bin", + "target-mkdir-bin", "target-rm-bin", "target-rmdir-bin" }); } diff --git a/configure.ac b/configure.ac index 0d78d0f8..a116203d 100644 --- a/configure.ac +++ b/configure.ac @@ -31,15 +31,14 @@ AC_PATH_PROG([CHATTR_BIN], [chattr], [/usr/bin/chattr]) AC_PATH_PROG([CHSNAP_BIN], [chsnap], [/sbin/chsnap]) AC_PATH_PROG([CP_BIN], [cp], [/bin/cp]) AC_PATH_PROG([DIFF_BIN], [diff], [/usr/bin/diff]) -AC_PATH_PROG([FINDMNT_BIN], [findmnt], [/usr/bin/findmnt]) AC_PATH_PROG([LVCHANGE_BIN], [lvchange], [/sbin/lvchange]) AC_PATH_PROG([LVCREATE_BIN], [lvcreate], [/sbin/lvcreate]) +AC_PATH_PROG([LS_BIN], [ls], [/usr/bin/ls]) AC_PATH_PROG([LVM_BIN], [lvm], [/sbin/lvm]) AC_PATH_PROG([LVREMOVE_BIN], [lvremove], [/sbin/lvremove]) AC_PATH_PROG([LVRENAME_BIN], [lvrename], [/sbin/lvrename]) AC_PATH_PROG([LVS_BIN], [lvs], [/sbin/lvs]) AC_PATH_PROG([MKDIR_BIN], [mkdir], [/bin/mkdir]) -AC_PATH_PROG([REALPATH_BIN], [realpath], [/usr/bin/realpath]) AC_PATH_PROG([RM_BIN], [rm], [/bin/rm]) AC_PATH_PROG([RMDIR_BIN], [rmdir], [/bin/rmdir]) AC_PATH_PROG([TOUCH_BIN], [touch], [/usr/bin/touch]) @@ -49,15 +48,14 @@ AC_DEFINE_UNQUOTED([CHATTR_BIN], ["$CHATTR_BIN"], [Path of chattr program.]) AC_DEFINE_UNQUOTED([CHSNAP_BIN], ["$CHSNAP_BIN"], [Path of chsnap program.]) AC_DEFINE_UNQUOTED([CP_BIN], ["$CP_BIN"], [Path of cp program.]) AC_DEFINE_UNQUOTED([DIFF_BIN], ["$DIFF_BIN"], [Path of diff program.]) -AC_DEFINE_UNQUOTED([FINDMNT_BIN], ["$FINDMNT_BIN"], [Path of findmnt program.]) AC_DEFINE_UNQUOTED([LVCHANGE_BIN], ["$LVCHANGE_BIN"], [Path of lvchange program.]) AC_DEFINE_UNQUOTED([LVCREATE_BIN], ["$LVCREATE_BIN"], [Path of lvcreate program.]) +AC_DEFINE_UNQUOTED([LS_BIN], ["$LS_BIN"], [Path of ls program.]) AC_DEFINE_UNQUOTED([LVM_BIN], ["$LVM_BIN"], [Path of lvm program.]) AC_DEFINE_UNQUOTED([LVREMOVE_BIN], ["$LVREMOVE_BIN"], [Path of lvremove program.]) AC_DEFINE_UNQUOTED([LVRENAME_BIN], ["$LVRENAME_BIN"], [Path of lvrename program.]) AC_DEFINE_UNQUOTED([LVS_BIN], ["$LVS_BIN"], [Path of lvs program.]) AC_DEFINE_UNQUOTED([MKDIR_BIN], ["$MKDIR_BIN"], [Path of mkdir program.]) -AC_DEFINE_UNQUOTED([REALPATH_BIN], ["$REALPATH_BIN"], [Path of realpath program.]) AC_DEFINE_UNQUOTED([RM_BIN], ["$RM_BIN"], [Path of rm program.]) AC_DEFINE_UNQUOTED([RMDIR_BIN], ["$RMDIR_BIN"], [Path of rmdir program.]) AC_DEFINE_UNQUOTED([TOUCH_BIN], ["$TOUCH_BIN"], [Path of touch program.]) diff --git a/doc/snapper-backup-configs.xml.in b/doc/snapper-backup-configs.xml.in index 7a6e202f..8e17f5e2 100644 --- a/doc/snapper-backup-configs.xml.in +++ b/doc/snapper-backup-configs.xml.in @@ -2,13 +2,13 @@ - 2025-10-07 + 2025-10-13 snapper-backup-configs 5 - 2025-10-07 + 2025-10-13 @VERSION@ Filesystem Snapshot Management @@ -138,9 +138,9 @@ - + - Location of the findmnt binary on the target. Can also + Location of the ls binary on the target. Can also be used to install wrapper scripts. Optional. @@ -153,14 +153,6 @@ - - - - Location of the realpath binary on the target. Can also - be used to install wrapper scripts. Optional. - - - diff --git a/package/snapper.changes b/package/snapper.changes index ee7331f5..33aa71f3 100644 --- a/package/snapper.changes +++ b/package/snapper.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Oct 13 08:43:43 CEST 2025 - aschnell@suse.com + +- redesigned target snapshot detection in snbk + (gh#openSUSE/snapper#1061) + ------------------------------------------------------------------- Tue Oct 07 14:42:16 CEST 2025 - aschnell@suse.com