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);
}
vector<string> 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;
#include <sys/utsname.h>
-#include <cstring>
#include <regex>
-#include <boost/algorithm/string.hpp>
#include "snapper/SnapperTmpl.h"
#include "snapper/SystemCmd.h"
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<string>& 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, "<FS_TREE>/"))
- entry.path.erase(0, strlen("<FS_TREE>/"));
-
- 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 };
using std::vector;
- /**
- * Class to probe for btrfs subvolumes: Call "btrfs subvolume list
- * <mount-point>".
- */
- 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<Entry>::value_type value_type;
- typedef vector<Entry>::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<string>& lines);
-
- vector<Entry> data;
-
- };
-
-
/**
* Class to probe for btrfs subvolume information: Call "btrfs subvolume
* show <mount-point>".
+++ /dev/null
-/*
- * 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<string>& lines)
- {
- JsonFile json_file(lines);
-
- vector<json_object*> 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;
- }
-
-}
+++ /dev/null
-/*
- * 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 <path>".
- */
- 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<string>& lines);
-
- const string path;
-
- string source;
- string target;
-
- };
-
-}
-
-#endif
/*
- * Copyright (c) 2024 SUSE LLC
+ * Copyright (c) [2004-2015] Novell, Inc.
+ * Copyright (c) [2016-2025] SUSE LLC
*
* All Rights Reserved.
*
*/
-#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)
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<string>& lines)
+ CmdLs::parse(const vector<string>& 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;
}
/*
- * Copyright (c) 2024 SUSE LLC
+ * Copyright (c) [2004-2015] Novell, Inc.
+ * Copyright (c) [2016-2025] SUSE LLC
*
* All Rights Reserved.
*
*/
-#ifndef SNAPPER_CMD_REALPATH_H
-#define SNAPPER_CMD_REALPATH_H
+#ifndef SNAPPER_CMD_LS_H
+#define SNAPPER_CMD_LS_H
#include "Shell.h"
namespace snapper
{
-
using std::string;
using std::vector;
/**
- * Class to probe realpath: Call "realpath <path>".
+ * 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<string>::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:
const string path;
- string realpath;
+ vector<string> entries;
};
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 = \
#include "../utils/text.h"
#include "CmdBtrfs.h"
-#include "CmdFindmnt.h"
-#include "CmdRealpath.h"
+#include "CmdLs.h"
#include "BackupConfig.h"
#include "TheBigThing.h"
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)
{
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<TheBigThing>::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<TheBigThing>::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.
+ }
}
}
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
};
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"));
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;
const vector<Column> 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())
const vector<string> EnumInfo<Column>::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"
});
}
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])
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.])
<refentry id='snapper-backup-configs5'>
<refentryinfo>
- <date>2025-10-07</date>
+ <date>2025-10-13</date>
</refentryinfo>
<refmeta>
<refentrytitle>snapper-backup-configs</refentrytitle>
<manvolnum>5</manvolnum>
- <refmiscinfo class='date'>2025-10-07</refmiscinfo>
+ <refmiscinfo class='date'>2025-10-13</refmiscinfo>
<refmiscinfo class='version'>@VERSION@</refmiscinfo>
<refmiscinfo class='manual'>Filesystem Snapshot Management</refmiscinfo>
</refmeta>
</varlistentry>
<varlistentry>
- <term><option>target-findmnt-bin</option></term>
+ <term><option>target-ls-bin</option></term>
<listitem>
- <para>Location of the findmnt binary on the target. Can also
+ <para>Location of the ls binary on the target. Can also
be used to install wrapper scripts. Optional.</para>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
- <varlistentry>
- <term><option>target-realpath-bin</option></term>
- <listitem>
- <para>Location of the realpath binary on the target. Can also
- be used to install wrapper scripts. Optional.</para>
- </listitem>
- </varlistentry>
-
<varlistentry>
<term><option>target-rm-bin</option></term>
<listitem>
+-------------------------------------------------------------------
+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