sudo zypper install -t pattern devel_C_C++
# install the extra packages for snapper development (both SLE and openSUSE)
sudo zypper install git libmount-devel dbus-1-devel libacl-devel libboost_thread-devel libjson-c-devel \
- docbook-xsl-stylesheets libxml2-devel libbtrfs-devel
+ docbook-xsl-stylesheets libxml2-devel libbtrfs-devel libopenssl-devel
```
In the RHEL-based distributions, you can install the needed
sudo dnf install git libmount-devel dbus-devel libacl-devel \
docbook-xsl libxml2-devel btrfs-progs-devel \
cmake make automake gcc-c++ systemd-devel boost-devel \
- ncurses-devel json-c-devel pam-devel
+ ncurses-devel json-c-devel pam-devel openssl-devel
```
### Building 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-cat-bin", target_cat_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-rm-bin", target_rm_bin);
vector<string> receive_options;
string target_btrfs_bin = BTRFS_BIN;
+ string target_cat_bin = CAT_BIN;
string target_ls_bin = LS_BIN;
string target_mkdir_bin = MKDIR_BIN;
string target_rm_bin = RM_BIN;
--- /dev/null
+/*
+ * Copyright (c) 2026 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 <iomanip>
+#include <iostream>
+#include <sstream>
+
+#include <boost/algorithm/string.hpp>
+#include <openssl/sha.h>
+
+#include <snapper/Enum.h>
+#include <snapper/LoggerImpl.h>
+#include <snapper/SystemCmd.h>
+#include <snapper/XmlFile.h>
+
+#include "CmdMetaParse.h"
+
+#include "../misc.h"
+
+
+namespace snapper
+{
+ CmdMetaParse::CmdMetaParse(const Shell& shell, const string& snapshot_dir,
+ const string& cat_bin)
+ : path(snapshot_dir + "/info.xml")
+ {
+ SystemCmd::Args cmd_args = { cat_bin, 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);
+ }
+
+ content = boost::join(cmd.get_stdout(), "");
+
+ y2mil(*this);
+ }
+
+
+ string CmdMetaParse::get_checksum() const
+ {
+ if (!content.length())
+ return "";
+
+ unsigned char hash[SHA256_DIGEST_LENGTH];
+ SHA256(reinterpret_cast<const unsigned char*>(content.c_str()), content.length(),
+ hash);
+
+ std::stringstream ss;
+ for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
+ {
+ ss << std::hex << std::setw(2) << std::setfill('0')
+ << static_cast<int>(hash[i]);
+ }
+
+ return ss.str();
+ }
+
+
+ SnapshotMeta CmdMetaParse::get_meta() const
+ {
+ SnapshotMeta meta;
+
+ if (!content.length())
+ {
+ // The `info.xml` file might be missing.
+ // Using fallback values for snapshot metadata.
+ return meta;
+ }
+
+ XmlFile file(XmlFile::FromString, content);
+ const xmlNode* node = file.getRootElement();
+ string tmp;
+
+ if (!getChildValue(node, "type", tmp) || !toValue(tmp, meta.type, true))
+ {
+ // Log error for the missing attribute and retain the default value.
+ y2err("The type attribute is missing from " << path);
+ }
+
+ getChildValue(node, "pre_num", meta.pre_num);
+ getChildValue(node, "cleanup", meta.cleanup);
+
+ for (const xmlNode* tmp : getChildNodes(node, "userdata"))
+ {
+ string key, value;
+ getChildValue(tmp, "key", key);
+ getChildValue(tmp, "value", value);
+ if (!key.empty())
+ meta.userdata[key] = value;
+ }
+
+ return meta;
+ }
+
+
+ std::ostream& operator<<(std::ostream& s, const CmdMetaParse& cmd_metaparse)
+ {
+ SnapshotMeta meta = cmd_metaparse.get_meta();
+ s << "path: " << cmd_metaparse.path
+ << ", checksum: " << cmd_metaparse.get_checksum()
+ << ", type: " << toString(meta.type) << ", pre_num: " << meta.pre_num
+ << ", cleanup: " << meta.cleanup
+ << ", userdata: " << show_userdata(meta.userdata) << '\n';
+
+ return s;
+ }
+
+
+} // namespace snapper
--- /dev/null
+/*
+ * Copyright (c) 2026 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_METAPARSE_H
+#define SNAPPER_CMD_METAPARSE_H
+
+
+#include <snapper/Snapshot.h>
+
+#include "Shell.h"
+
+
+namespace snapper
+{
+ using std::string;
+
+
+ struct SnapshotMeta
+ {
+ SnapshotType type = SnapshotType::SINGLE;
+ unsigned int pre_num = 0;
+ string cleanup;
+ map<string, string> userdata;
+ };
+
+
+ class CmdMetaParse
+ {
+ public:
+
+ CmdMetaParse(const Shell& shell, const string& snapshot_dir,
+ const string& cat_bin);
+
+ string get_checksum() const;
+ SnapshotMeta get_meta() const;
+
+ friend std::ostream& operator<<(std::ostream& s,
+ const CmdMetaParse& cmd_metaparse);
+
+ private:
+
+ string path;
+ string content = "";
+ };
+
+} // namespace snapper
+
+
+#endif
# Makefile.am for snapper/client/snbk
#
-AM_CPPFLAGS = -I$(top_srcdir) $(DBUS_CFLAGS) $(JSON_C_CFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir) $(DBUS_CFLAGS) $(JSON_C_CFLAGS) $(CRYPTO_CFLAGS) \
+ $(XML2_CFLAGS)
sbin_PROGRAMS = snbk
CmdBtrfs.cc CmdBtrfs.h \
CmdLs.cc CmdLs.h \
CmdChecksum.cc CmdChecksum.h \
+ CmdMetaParse.cc CmdMetaParse.h \
JsonFile.cc JsonFile.h \
utils.cc utils.h \
- TreeView.cc TreeView.h
+ TreeView.cc TreeView.h \
+ ../misc.cc ../misc.h
snbk_LDADD = \
../../snapper/libsnapper.la \
../../dbus/libdbus.la \
../proxy/libproxy.la \
../proxy/libclient.la \
- $(JSON_C_LIBS)
+ $(JSON_C_LIBS) \
+ $(CRYPTO_LIBS) \
+ $(XML2_LIBS)
AC_PATH_PROG([XSLTPROC], [xsltproc], [/usr/bin/xsltproc])
AC_PATH_PROG([BTRFS_BIN], [btrfs], [/usr/sbin/btrfs])
+AC_PATH_PROG([CAT_BIN], [cat], [/usr/bin/cat])
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([TOUCH_BIN], [touch], [/usr/bin/touch])
AC_DEFINE_UNQUOTED([BTRFS_BIN], ["$BTRFS_BIN"], [Path of btrfs program.])
+AC_DEFINE_UNQUOTED([CAT_BIN], ["$CAT_BIN"], [Path of cat program.])
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.])
PKG_CHECK_MODULES(DBUS, dbus-1)
PKG_CHECK_MODULES(XML2, libxml-2.0)
PKG_CHECK_MODULES(JSON_C, json-c, [], [AC_MSG_WARN([Cannot find json-c. Please install libjson-c-devel])])
+PKG_CHECK_MODULES([CRYPTO], [libcrypto])
PKG_CHECK_MODULES(ZLIB, zlib)
# Conditional support for libbtrfsutil based on existence of pkg-config file
Priority: optional
Section: admin
Maintainer: Arvin Schnell <aschnell@suse.com>
-Build-Depends: debhelper (>= 4.1.16), btrfs-progs, g++, libboost-dev, libboost-thread-dev, libboost-test-dev, libxml2-dev, libz-dev, libdbus-1-dev, libpam-dev, xsltproc, docbook-xsl
+Build-Depends: debhelper (>= 4.1.16), btrfs-progs, g++, libboost-dev, libboost-thread-dev, libboost-test-dev, libxml2-dev, libz-dev, libdbus-1-dev, libpam-dev, xsltproc, docbook-xsl, libssl-dev
Homepage: http://en.opensuse.org/Portal:Snapper
Package: snapper
Binary: snapper
Maintainer: Arvin Schnell <aschnell@suse.com>
Architecture: any
-Build-Depends: debhelper (>= 4.1.16), acl-dev, btrfs-progs, dbus, g++, libboost-dev, libboost-thread-dev, libboost-test-dev, libxml2-dev, libz-dev, libdbus-1-dev, libjson-c-dev, libpam-dev, xsltproc, docbook-xsl, locales-all, ncurses-dev
+Build-Depends: debhelper (>= 4.1.16), acl-dev, btrfs-progs, dbus, g++, libboost-dev, libboost-thread-dev, libboost-test-dev, libxml2-dev, libz-dev, libdbus-1-dev, libjson-c-dev, libpam-dev, xsltproc, docbook-xsl, locales-all, ncurses-dev, libssl-dev
#
# The 'Files' line is generated during 'make package':
# Files:
Binary: snapper
Maintainer: Arvin Schnell <aschnell@suse.com>
Architecture: any
-Build-Depends: debhelper (>= 4.1.16), acl-dev, btrfs-progs, dbus, g++, libboost-dev, libboost-thread-dev, libboost-test-dev, libxml2-dev, libz-dev, libdbus-1-dev, libjson-c-dev, libpam-dev, xsltproc, docbook-xsl, locales-all, ncurses-dev
+Build-Depends: debhelper (>= 4.1.16), acl-dev, btrfs-progs, dbus, g++, libboost-dev, libboost-thread-dev, libboost-test-dev, libxml2-dev, libz-dev, libdbus-1-dev, libjson-c-dev, libpam-dev, xsltproc, docbook-xsl, locales-all, ncurses-dev, libssl-dev
#
# The 'Files' line is generated during 'make package':
# Files:
Binary: snapper
Maintainer: Arvin Schnell <aschnell@suse.com>
Architecture: any
-Build-Depends: debhelper (>= 4.1.16), acl-dev, btrfs-progs, dbus, g++, libboost-dev, libboost-thread-dev, libboost-test-dev, libxml2-dev, libz-dev, libdbus-1-dev, libjson-c-dev, libpam-dev, xsltproc, docbook-xsl, language-pack-en, language-pack-de, language-pack-fr, ncurses-dev
+Build-Depends: debhelper (>= 4.1.16), acl-dev, btrfs-progs, dbus, g++, libboost-dev, libboost-thread-dev, libboost-test-dev, libxml2-dev, libz-dev, libdbus-1-dev, libjson-c-dev, libpam-dev, xsltproc, docbook-xsl, language-pack-en, language-pack-de, language-pack-fr, ncurses-dev, libssl-dev
#
# The 'Files' line is generated during 'make package':
# Files:
%if %{with coverage}
BuildRequires: lcov
%endif
+%if 0%{?suse_version}
+BuildRequires: libopenssl-devel
+%else
+BuildRequires: openssl-devel
+%endif
Requires: dbus-service
Requires: diffutils
Requires: libsnapper@LIBVERSION_MAJOR@ = %version