return _("Snapshot is in use.");
if (name == "error.io_error")
- return _("IO Error.");
+ return sformat(_("IO Error (%s)."), e.message());
if (name == "error.create_config_failed")
return sformat(_("Creating config failed (%s)."), e.message());
}
catch (const InvalidConfigException& e)
{
+ SN_CAUGHT(e);
cerr << _("Failed to initialize filesystem handler.") << endl;
exit(EXIT_FAILURE);
}
void
print_xa_diff(const string loc_pre, const string loc_post)
{
- try {
+ try
+ {
XAModification xa_mod = XAModification(XAttributes(loc_pre), XAttributes(loc_post));
if (!xa_mod.empty())
xa_mod.dumpDiffReport(cout);
}
}
- catch (const XAttributesException& e) {}
+ catch (const XAttributesException& e)
+ {
+ SN_CAUGHT(e);
+ }
}
void
}
catch (const ConfigNotFoundException& e)
- {
- cerr << sformat(_("Config '%s' not found."), config_name.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
- catch (const InvalidConfigException& e)
- {
- cerr << sformat(_("Config '%s' is invalid."), config_name.c_str()) << endl;
- exit(EXIT_FAILURE);
- }
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("Config '%s' not found."), config_name.c_str()) << endl;
+ exit(EXIT_FAILURE);
+ }
+ catch (const InvalidConfigException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("Config '%s' is invalid."), config_name.c_str()) << endl;
+ exit(EXIT_FAILURE);
+ }
catch (const ListConfigsFailedException& e)
{
+ SN_CAUGHT(e);
cerr << sformat(_("Listing configs failed (%s)."), e.what()) << endl;
exit(EXIT_FAILURE);
}
catch (const CreateConfigFailedException& e)
{
+ SN_CAUGHT(e);
cerr << sformat(_("Creating config failed (%s)."), e.what()) << endl;
exit(EXIT_FAILURE);
}
catch (const DeleteConfigFailedException& e)
{
+ SN_CAUGHT(e);
cerr << sformat(_("Deleting config failed (%s)."), e.what()) << endl;
exit(EXIT_FAILURE);
}
catch (const InvalidConfigdataException& e)
{
+ SN_CAUGHT(e);
cerr << _("Invalid configdata.") << endl;
exit(EXIT_FAILURE);
}
catch (const AclException& e)
{
+ SN_CAUGHT(e);
cerr << _("ACL error.") << endl;
exit(EXIT_FAILURE);
}
+ catch (const IOErrorException& e)
+ {
+ SN_CAUGHT(e);
+ cerr << sformat(_("IO error (%s)."), e.what()) << endl;
+ exit(EXIT_FAILURE);
+ }
catch (const InvalidUserException& e)
{
+ SN_CAUGHT(e);
cerr << _("Invalid user.") << endl;
exit(EXIT_FAILURE);
}
catch (const InvalidGroupException& e)
{
+ SN_CAUGHT(e);
cerr << _("Invalid group.") << endl;
exit(EXIT_FAILURE);
}
}
catch (const DBus::ErrorException& e)
{
+ SN_CAUGHT(e);
+
if (strcmp(e.name(), "error.unknown_config") == 0 && config_name == "root")
{
cerr << _("The config 'root' does not exist. Likely snapper is not configured.") << endl
}
catch (const DBus::FatalException& e)
{
+ SN_CAUGHT(e);
cerr << _("Failure") << " (" << e.what() << ")." << endl;
exit(EXIT_FAILURE);
}
#include <list>
#include <map>
+#include "snapper/Exception.h"
+
namespace DBus
{
using std::map;
- struct Exception : public std::exception
+ struct Exception : public snapper::Exception
{
- explicit Exception() throw() {}
- virtual const char* what() const throw() { return "dbus generic exception"; }
+ explicit Exception() : snapper::Exception("dbus generic exception") {}
+ explicit Exception(const string& msg) : snapper::Exception(msg) {}
};
struct ErrorException : public Exception
{
- explicit ErrorException(const DBusError err) throw() : err(err) {}
+ explicit ErrorException(const DBusError err)
+ : Exception("dbus error exception"), err(err) {}
virtual ~ErrorException() throw() { dbus_error_free(&err); }
- virtual const char* what() const throw() { return "dbus error exception"; }
virtual const char* name() const throw() { return err.name; }
virtual const char* message() const throw() { return err.message; }
DBusError err;
struct MarshallingException : public Exception
{
- explicit MarshallingException() throw() {}
- virtual const char* what() const throw() { return "dbus marshalling exception"; }
+ explicit MarshallingException() : Exception("dbus marshalling exception") {}
};
struct FatalException : public Exception
{
- explicit FatalException() throw() {}
- virtual const char* what() const throw() { return "dbus fatal exception"; }
+ explicit FatalException() : Exception("dbus fatal exception") {}
};
+-------------------------------------------------------------------
+Mon Aug 31 16:26:51 CEST 2015 - aschnell@suse.com
+
+- improved error reporting (bsc#940046)
+
-------------------------------------------------------------------
Wed Aug 26 11:58:24 CEST 2015 - aschnell@suse.de
}
-struct Permissions : public std::exception
+struct Permissions : public Exception
{
- explicit Permissions() throw() {}
- virtual const char* what() const throw() { return "permissions"; }
+ explicit Permissions() : Exception("no permissions") {}
};
}
-struct Lock : public std::exception
+struct Lock : public Exception
{
- explicit Lock() throw() {}
- virtual const char* what() const throw() { return "locked"; }
+ explicit Lock() : Exception("locked") {}
};
}
-struct ConfigInUse : public std::exception
+struct ConfigInUse : public Exception
{
- explicit ConfigInUse() throw() {}
- virtual const char* what() const throw() { return "config in use"; }
+ explicit ConfigInUse() : Exception("config in use") {}
};
-struct SnapshotInUse : public std::exception
+struct SnapshotInUse : public Exception
{
- explicit SnapshotInUse() throw() {}
- virtual const char* what() const throw() { return "snapshot in use"; }
+ explicit SnapshotInUse() : Exception("snapshot in use") {}
};
}
catch (const DBus::MarshallingException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.dbus.marshalling", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const DBus::FatalException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.dbus.fatal", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const UnknownConfig& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.unknown_config", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const CreateConfigFailedException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.create_config_failed", e.what());
conn.send(reply);
}
catch (const DeleteConfigFailedException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.delete_config_failed", e.what());
conn.send(reply);
}
catch (const Permissions& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.no_permissions", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const Lock& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.config_locked", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const ConfigInUse& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.config_in_use", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const SnapshotInUse& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.snapshot_in_use", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const NoComparison& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.no_comparisons", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const IllegalSnapshotException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.illegal_snapshot", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const CreateSnapshotFailedException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.create_snapshot_failed", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const DeleteSnapshotFailedException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.delete_snapshot_failed", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const InvalidConfigdataException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.invalid_configdata", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const InvalidUserdataException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.invalid_userdata", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const AclException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.acl_error", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const IOErrorException& e)
{
- DBus::MessageError reply(msg, "error.io_error", DBUS_ERROR_FAILED);
+ SN_CAUGHT(e);
+ DBus::MessageError reply(msg, "error.io_error", e.what());
conn.send(reply);
}
catch (const IsSnapshotMountedFailedException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.is_snapshot_mounted", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const MountSnapshotFailedException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.mount_snapshot", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const UmountSnapshotFailedException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.umount_snapshot", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const InvalidUserException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.invalid_user", DBUS_ERROR_FAILED);
conn.send(reply);
}
catch (const InvalidGroupException& e)
{
+ SN_CAUGHT(e);
DBus::MessageError reply(msg, "error.invalid_group", DBUS_ERROR_FAILED);
conn.send(reply);
}
+ catch (const Exception& e)
+ {
+ SN_CAUGHT(e);
+ DBus::MessageError reply(msg, "error.something", DBUS_ERROR_FAILED);
+ conn.send(reply);
+ }
catch (...)
{
y2err("caught unknown exception");
extern boost::shared_mutex big_mutex;
-struct NoComparison : public std::exception
+struct NoComparison : Exception
{
- explicit NoComparison() throw() {}
- virtual const char* what() const throw() { return "no comparison"; }
+ explicit NoComparison() : Exception("no comparison") {}
};
};
-struct UnknownConfig : public std::exception
+struct UnknownConfig : public Exception
{
- explicit UnknownConfig() throw() {}
- virtual const char* what() const throw() { return "unknown config"; }
+ explicit UnknownConfig() : Exception("unknown config") {}
};
{
public:
- struct InvalidKeyException : public SnapperException
+ struct InvalidKeyException : public Exception
{
- explicit InvalidKeyException() throw() {}
- virtual const char* what() const throw() { return "invalid key"; }
+ explicit InvalidKeyException() : Exception("invalid key") {}
};
SysconfigFile(const char* name) : AsciiFile(name), modified(false) {}
#include "snapper/SnapperTmpl.h"
#include "snapper/SnapperDefines.h"
#include "snapper/Acls.h"
+#include "snapper/Exception.h"
namespace snapper
struct stat stat;
if (subvolume_dir.stat(&stat) != 0)
{
- throw IOErrorException();
+ throw IOErrorException("stat on subvolume directory failed");
}
if (!is_subvolume(stat))
{
- y2err("subvolume is not a btrfs snapshot");
- throw IOErrorException();
+ throw IOErrorException("subvolume is not a btrfs snapshot");
}
return subvolume_dir;
struct stat stat;
if (infos_dir.stat(&stat) != 0)
{
- throw IOErrorException();
+ throw IOErrorException("stat on info directory failed");
}
if (!is_subvolume(stat))
{
- y2err(".snapshots is not a btrfs snapshot");
- throw IOErrorException();
+ SN_THROW(IOErrorException(".snapshots is not a btrfs snapshot"));
}
if (stat.st_uid != 0)
{
y2err(".snapshots must have owner root");
- throw IOErrorException();
+ throw IOErrorException(".snapshots must have owner root");
}
if (stat.st_gid != 0 && stat.st_mode & S_IWGRP)
{
y2err(".snapshots must have group root or must not be group-writable");
- throw IOErrorException();
+ throw IOErrorException(".snapshots must have group root or must not be group-writable");
}
if (stat.st_mode & S_IWOTH)
{
y2err(".snapshots must not be world-writable");
- throw IOErrorException();
+ throw IOErrorException(".snapshots must not be world-writable");
}
return infos_dir;
}
- struct BtrfsSendReceiveException : public SnapperException
+ struct BtrfsSendReceiveException : public Exception
{
- explicit BtrfsSendReceiveException() throw() {}
- virtual const char* what() const throw() { return "Btrfs send/receive error"; }
+ explicit BtrfsSendReceiveException() : Exception("btrfs send/receive error") {}
};
u64 flags;
if (ioctl(dir.fd(), BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0)
{
- throw IOErrorException();
+ throw IOErrorException("ioctl BTRFS_IOC_SUBVOL_GETFLAGS failed");
}
return flags & BTRFS_SUBVOL_RDONLY;
y2mil("stopwatch " << stopwatch << " for comparing directories");
}
- catch (const SnapperException& e)
+ catch (const Exception& e)
{
y2err("special btrfs cmpDirs failed, " << e.what());
y2mil("cmpDirs fallback");
}
catch (const runtime_error& e)
{
- y2err("set default failed, " << e.what());
- throw IOErrorException();
+ throw IOErrorException(string("set default failed, ") + e.what());
}
}
return DELETED;
if (r1 != 0)
- {
- y2err("stat failed path:" << file1.fullname());
- throw IOErrorException();
- }
+ throw IOErrorException("stat failed path:" + file1.fullname());
if (r2 != 0)
- {
- y2err("lstat failed path:" << file2.fullname());
- throw IOErrorException();
- }
+ throw IOErrorException("lstat failed path:" + file2.fullname());
return cmpFiles(file1, stat1, file2, stat2);
}
struct stat stat1;
int r1 = dir1.stat(&stat1);
if (r1 != 0)
- {
- y2err("stat failed path:" << dir1.fullname() << " errno:" << errno);
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("stat failed path:%s errno:%d", dir1.fullname().c_str(), errno));
struct stat stat2;
int r2 = dir2.stat(&stat2);
if (r2 != 0)
- {
- y2err("stat failed path:" << dir2.fullname() << " errno:" << errno);
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("stat failed path:%s errno:%d", dir2.fullname().c_str(), errno));
CmpData cmp_data;
cmp_data.cb = cb;
FILE* file = fdopen(info_dir.mktemp(tmp_name), "w");
if (!file)
- {
- y2err("mkstemp failed errno:" << errno << " (" << stringerror(errno) << ")");
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("mkstemp failed errno:%d (%s)", errno,
+ stringerror(errno).c_str()));
for (Files::const_iterator it = files.begin(); it != files.end(); ++it)
{
--- /dev/null
+/*
+ * Copyright (c) [2014-2015] Novell, Inc.
+ *
+ * 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.
+ */
+
+
+/*
+ * Large parts taken from libyui/YUIException.h
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+#include <sstream>
+
+#include "snapper/Exception.h"
+#include "snapper/AppUtil.h"
+#include "snapper/Log.h"
+#include "snapper/Logger.h"
+
+
+namespace snapper
+{
+
+ std::string
+ CodeLocation::asString() const
+ {
+ // Format as "MySource.cc(myFunc):177"
+ std::string str(_file);
+ str += "(" + _func + "):" + std::to_string(_line);
+
+ return str;
+ }
+
+
+ std::ostream&
+ operator<<(std::ostream& str, const CodeLocation& obj)
+ {
+ return str << obj.asString();
+ }
+
+
+ Exception::Exception()
+ {
+ }
+
+
+ Exception::Exception(const std::string& msg_r)
+ : _msg(msg_r)
+ {
+ }
+
+
+ Exception::~Exception() throw()
+ {
+ }
+
+
+ std::string
+ Exception::asString() const
+ {
+ std::ostringstream str;
+ dumpOn(str);
+ return str.str();
+ }
+
+
+ std::ostream&
+ Exception::dumpOn(std::ostream& str) const
+ {
+ return str << _msg;
+ }
+
+
+ std::ostream&
+ Exception::dumpError(std::ostream& str) const
+ {
+ return dumpOn(str << _where << ": ");
+ }
+
+
+ std::ostream&
+ operator<<(std::ostream& str, const Exception& obj)
+ {
+ return obj.dumpError(str);
+ }
+
+
+ std::string
+ Exception::strErrno(int errno_r)
+ {
+ return strerror(errno_r);
+ }
+
+
+ std::string
+ Exception::strErrno(int errno_r, const std::string& msg)
+ {
+ return msg + ": " + strErrno(errno_r);
+ }
+
+
+ void
+ Exception::log(const Exception& exception, const CodeLocation& location,
+ const char* const prefix)
+ {
+ y2log_op(WARNING, location.file().c_str(), location.line(),
+ location.func().c_str(), string(prefix) + " " + exception.asString());
+ }
+
+}
/*
* Copyright (c) [2011-2014] Novell, Inc.
+ * Copyright (c) [2015] SUSE LLC
*
* All Rights Reserved.
*
#include <exception>
+#include <string>
namespace snapper
{
+ //
+ // Macros for application use
+ //
- struct SnapperException : public std::exception
+ /**
+ * Usage summary:
+ *
+ * Use SN_THROW to throw exceptions.
+ * Use SN_CAUGHT If you caught an exceptions in order to handle it.
+ * Use SN_RETHROW to rethrow a caught exception.
+ *
+ * The use of these macros is not mandatory. But SN_THROW and SN_RETHROW
+ * will adjust the code location information stored in the exception. All
+ * three macros will drop a line in the log file.
+ *
+ * 43 try
+ * 44 {
+ * 45 try
+ * 46 {
+ * 47 SN_THROW(Exception("Something bad happened."));
+ * 48 }
+ * 49 catch (const Exception& exception)
+ * 50 {
+ * 51 SN_RETHROW(exception);
+ * 52 }
+ * 53 }
+ * 54 catch (const Exception& exception)
+ * 55 {
+ * 56 SN_CAUGHT(exception);
+ * 57 }
+ *
+ * The above produces the following log lines:
+ *
+ * Main.cc(main):47 THROW: Main.cc(main):47: Something bad happened.
+ * Main.cc(main):51 RETHROW: Main.cc(main):47: Something bad happened.
+ * Main.cc(main):56 CAUGHT: Main.cc(main):51: Something bad happened.
+ **/
+
+
+ /**
+ * Create CodeLocation object storing the current location.
+ **/
+#define SN_EXCEPTION_CODE_LOCATION \
+ CodeLocation(__FILE__, __FUNCTION__, __LINE__)
+
+
+ /**
+ * Drops a log line and throws the Exception.
+ **/
+#define SN_THROW(EXCEPTION) \
+ _SN_THROW((EXCEPTION), SN_EXCEPTION_CODE_LOCATION)
+
+ /**
+ * Drops a log line telling the Exception was caught and handled.
+ **/
+#define SN_CAUGHT(EXCEPTION) \
+ _SN_CAUGHT((EXCEPTION), SN_EXCEPTION_CODE_LOCATION)
+
+
+ /**
+ * Drops a log line and rethrows, updating the CodeLocation.
+ **/
+#define SN_RETHROW(EXCEPTION) \
+ _SN_RETHROW((EXCEPTION), SN_EXCEPTION_CODE_LOCATION)
+
+
+ /**
+ * Throw Exception built from a message string.
+ **/
+#define SN_THROW_MSG(EXCEPTION_TYPE, MSG) \
+ SN_THROW(EXCEPTION_TYPE(MSG))
+
+
+ /**
+ * Throw Exception built from errno.
+ **/
+#define SN_THROW_ERRNO(EXCEPTION_TYPE) \
+ SN_THROW(EXCEPTION_TYPE(Exception::strErrno(errno)))
+
+
+ /**
+ * Throw Exception built from errno provided as argument.
+ **/
+#define SN_THROW_ERRNO1(EXCEPTION_TYPE, ERRNO) \
+ SN_THROW(EXCEPTION_TYPE(Exception::strErrno(ERRNO)))
+
+
+ /**
+ * Throw Exception built from errno and a message string.
+ **/
+#define SN_THROW_ERRNO_MSG(EXCEPTION_TYPE, MSG) \
+ SN_THROW(EXCEPTION_TYPE(Exception::strErrno(errno, MSG)))
+
+
+ /**
+ * Throw Exception built from errno provided as argument and a message
+ * string.
+ **/
+#define SN_THROW_ERRNO_MSG1(EXCEPTION_TYPE, ERRNO, MSG) \
+ SN_THROW(EXCEPTION_TYPE(Exception::strErrno(ERRNO, MSG)))
+
+
+ /**
+ * Helper class for UI exceptions: Store _FILE_, _FUNCTION_ and _LINE_.
+ * Construct this using the SN_EXCEPTION_CODE_LOCATION macro.
+ **/
+ class CodeLocation
+ {
+ public:
+ /**
+ * Constructor.
+ * Commonly called using the SN_EXCEPTION_CODE_LOCATION macro.
+ **/
+ CodeLocation(const std::string& file_r, const std::string& func_r, int line_r)
+ : _file(file_r), _func(func_r), _line(line_r) {}
+
+ /**
+ * Default constructor.
+ ***/
+ CodeLocation()
+ : _line(0) {}
+
+ /**
+ * Returns the source file name where the exception occured.
+ **/
+ const std::string& file() const { return _file; }
+
+ /**
+ * Returns the name of the function where the exception occured.
+ **/
+ const std::string& func() const { return _func; }
+
+ /**
+ * Returns the source line number where the exception occured.
+ **/
+ int line() const { return _line; }
+
+ /**
+ * Returns the location in normalized string format.
+ **/
+ std::string asString() const;
+
+ /**
+ * Stream output
+ **/
+ friend std::ostream& operator<<(std::ostream& str, const CodeLocation& obj);
+
+ private:
+
+ std::string _file;
+ std::string _func;
+ int _line;
+
+ };
+
+
+ /**
+ * CodeLocation stream output
+ **/
+ std::ostream& operator<<(std::ostream& str, const CodeLocation& obj);
+
+
+ /**
+ * Base class for snapper exceptions.
+ *
+ * Exception offers to store a message string passed to the constructor.
+ * Derived classes may provide additional information.
+ * Overload dumpOn to provide a proper error text.
+ **/
+ class Exception : public std::exception
{
- explicit SnapperException() throw() {}
- virtual const char* what() const throw() { return "generic snapper exception"; }
+ public:
+
+ /**
+ * Default constructor.
+ * Use SN_THROW to throw exceptions.
+ **/
+ Exception();
+
+ /**
+ * Constructor taking a message.
+ * Use SN_THROW to throw exceptions.
+ **/
+ Exception(const std::string& msg);
+
+ /**
+ * Destructor.
+ **/
+ virtual ~Exception() throw();
+
+ /**
+ * Return CodeLocation.
+ **/
+ const CodeLocation& where() const { return _where; }
+
+ /**
+ * Exchange location on rethrow.
+ **/
+ void relocate(const CodeLocation& newLocation) const { _where = newLocation; }
+
+ /**
+ * Return the message string provided to the constructor.
+ * Note: This is not neccessarily the complete error message.
+ * The whole error message is provided by asString or dumpOn.
+ **/
+ const std::string& msg() const { return _msg; }
+
+ /**
+ * Set a new message string.
+ **/
+ void setMsg(const std::string& msg) { _msg = msg; }
+
+ /**
+ * Error message provided by dumpOn as string.
+ **/
+ std::string asString() const;
+
+ /**
+ * Make a string from errno_r.
+ **/
+ static std::string strErrno(int errno_r);
+
+ /**
+ * Make a string from errno_r and msg_r.
+ **/
+ static std::string strErrno(int errno_r, const std::string& msg);
+
+ /**
+ * Drop a log line on throw, catch or rethrow.
+ * Used by SN_THROW macros.
+ **/
+ static void log(const Exception& exception, const CodeLocation& location,
+ const char* const prefix);
+
+ /**
+ * Return message string.
+ *
+ * Reimplemented from std::exception.
+ **/
+ virtual const char* what() const throw() { return _msg.c_str(); }
+
+ protected:
+
+ /**
+ * Overload this to print a proper error message.
+ **/
+ virtual std::ostream& dumpOn(std::ostream& str) const;
+
+ private:
+
+ friend std::ostream& operator<<(std::ostream& str, const Exception& obj);
+
+ mutable CodeLocation _where;
+ std::string _msg;
+
+ /**
+ * Called by std::ostream& operator<<() .
+ * Prints CodeLocation and the error message provided by dumpOn.
+ **/
+ std::ostream& dumpError(std::ostream& str) const;
+
};
- struct FileNotFoundException : public SnapperException
+ /**
+ * Exception stream output
+ **/
+ std::ostream& operator<<(std::ostream& str, const Exception& obj);
+
+
+ //
+ // Helper templates
+ //
+
+
+ /**
+ * Helper for SN_THROW()
+ **/
+ template<class _Exception>
+ void _SN_THROW(const _Exception& exception, const CodeLocation& where)
+ {
+ exception.relocate(where);
+ Exception::log(exception, where, "THROW:");
+
+ throw exception;
+ }
+
+
+ /**
+ * Helper for SN_CAUGHT()
+ **/
+ template<class _Exception>
+ void _SN_CAUGHT(const _Exception& exception, const CodeLocation& where)
+ {
+ Exception::log(exception, where, "CAUGHT:");
+ }
+
+
+ /**
+ * Helper for SN_RETHROW()
+ **/
+ template<class _Exception>
+ void _SN_RETHROW(const _Exception& exception, const CodeLocation& where)
+ {
+ Exception::log(exception, where, "RETHROW:");
+ exception.relocate(where);
+
+ throw;
+ }
+
+
+ struct FileNotFoundException : public Exception
{
- explicit FileNotFoundException() throw() {}
- virtual const char* what() const throw() { return "file not found"; }
+ explicit FileNotFoundException() : Exception("file not found") {}
};
- struct IllegalSnapshotException : public SnapperException
+ struct IllegalSnapshotException : public Exception
{
- explicit IllegalSnapshotException() throw() {}
- virtual const char* what() const throw() { return "illegal snapshot"; }
+ explicit IllegalSnapshotException() : Exception("illegal snapshot") {}
};
- struct BadAllocException : public SnapperException
+ struct BadAllocException : public Exception
{
- explicit BadAllocException() throw() {}
- virtual const char* what() const throw() { return "bad alloc"; }
+ explicit BadAllocException() : Exception("bad alloc") {}
};
- struct LogicErrorException : public SnapperException
+ struct LogicErrorException : public Exception
{
- explicit LogicErrorException() throw() {}
- virtual const char* what() const throw() { return "logic error"; }
+ explicit LogicErrorException() : Exception("logic error") {}
};
- struct IOErrorException : public SnapperException
+ struct IOErrorException : public Exception
{
- explicit IOErrorException() throw() {}
- virtual const char* what() const throw() { return "IO error"; }
+ explicit IOErrorException(const std::string& msg) : Exception(msg) {}
};
struct AclException : public IOErrorException
{
- explicit AclException() throw() {}
- virtual const char* what() const throw() { return "ACL error"; }
+ explicit AclException() : IOErrorException("ACL error") {}
};
- struct ProgramNotInstalledException : public SnapperException
+ struct ProgramNotInstalledException : public Exception
{
- explicit ProgramNotInstalledException(const char* msg) throw() : msg(msg) {}
- virtual const char* what() const throw() { return msg; }
- const char* msg;
+ explicit ProgramNotInstalledException(const std::string& msg) : Exception(msg) {}
};
- struct XAttributesException : public SnapperException
+ struct XAttributesException : public Exception
{
- explicit XAttributesException() throw() {}
- virtual const char* what() const throw() { return "XAttributes error"; }
+ explicit XAttributesException() : Exception("XAttributes error") {}
};
- struct InvalidUserException : public SnapperException
+ struct InvalidUserException : public Exception
{
- explicit InvalidUserException() throw() {}
- virtual const char* what() const throw() { return "invalid user"; }
+ explicit InvalidUserException() : Exception("invalid user") {}
};
- struct InvalidGroupException : public SnapperException
+ struct InvalidGroupException : public Exception
{
- explicit InvalidGroupException() throw() {}
- virtual const char* what() const throw() { return "invalid group"; }
+ explicit InvalidGroupException() : Exception("invalid group") {}
};
}
{
dirfd = ::open(base_path.c_str(), O_RDONLY | O_NOATIME | O_CLOEXEC);
if (dirfd < 0)
- {
- y2err("open failed path:" << base_path << " error:" << stringerror(errno));
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("open failed path:%s errno:%d (%s)", base_path.c_str(),
+ errno, stringerror(errno).c_str()));
struct stat buf;
if (fstat(dirfd, &buf) != 0)
- {
- y2err("fstat failed path:" << base_path << " error:" << stringerror(errno));
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("fstat failed path:%s errno:%d (%s)", base_path.c_str(),
+ errno, stringerror(errno).c_str()));
if (!S_ISDIR(buf.st_mode))
- {
- y2err("not a directory path:" << base_path);
- throw IOErrorException();
- }
+ throw IOErrorException("not a directory path:" + base_path);
setXaStatus();
}
dirfd = ::openat(dir.dirfd, name.c_str(), O_RDONLY | O_NOFOLLOW | O_NOATIME | O_CLOEXEC);
if (dirfd < 0)
- {
- y2err("open failed path:" << dir.fullname(name) << " (" << stringerror(errno) << ")");
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("open failed path:%s errno:%d (%s)", dir.fullname().c_str(),
+ errno, stringerror(errno).c_str()));
struct stat buf;
if (fstat(dirfd, &buf) != 0)
- {
- y2err("fstat failed path:" << base_path << " error:" << stringerror(errno));
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("fstat failed path:%s errno:%d (%s)", base_path.c_str(),
+ errno, stringerror(errno).c_str()));
if (!S_ISDIR(buf.st_mode))
{
- y2err("not a directory path:" << dir.fullname(name));
close(dirfd);
- throw IOErrorException();
+ throw IOErrorException("not a directory path:" + dir.fullname(name));
}
xastatus = dir.xastatus;
{
dirfd = fcntl(dir.dirfd, F_DUPFD_CLOEXEC, 0);
if (dirfd == -1)
- {
- y2err("fcntl(F_DUPFD_CLOEXEC) failed error:" << stringerror(errno));
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("fcntl(F_DUPFD_CLOEXEC) failed error:%d (%s)", errno,
+ stringerror(errno).c_str()));
xastatus = dir.xastatus;
}
::close(dirfd);
dirfd = fcntl(dir.dirfd, F_DUPFD_CLOEXEC, 0);
if (dirfd == -1)
- {
- y2err("fcntl(F_DUPFD_CLOEXEC) failed error:" << stringerror(errno));
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("fcntl(F_DUPFD_CLOEXEC) failed error:%d (%s)", errno,
+ stringerror(errno).c_str()));
xastatus = dir.xastatus;
}
{
int fd = fcntl(dirfd, F_DUPFD_CLOEXEC, 0);
if (fd == -1)
- {
- y2err("fcntl(F_DUPFD_CLOEXEC) failed error:" << stringerror(errno));
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("fcntl(F_DUPFD_CLOEXEC) failed error:%d (%s)", errno,
+ stringerror(errno).c_str()));
DIR* dp = fdopendir(fd);
if (dp == NULL)
{
- y2err("fdopendir failed path:" << fullname() << " error:" << stringerror(errno));
::close(fd);
- throw IOErrorException();
+ throw IOErrorException(sformat("fdopendir failed path:%s error:%d (%s)",
+ fullname().c_str(), errno, stringerror(errno).c_str()));
}
vector<string> ret;
}
else
{
- y2err("Couldn't get extended attributes status for " << base_path << "/" <<
- path << stringerror(errno));
- throw IOErrorException();
+ throw IOErrorException(sformat("Couldn't get extended attributes status for %s/%s, "
+ "errno:%d (%s)", base_path.c_str(), path.c_str(),
+ errno, stringerror(errno).c_str()));
}
}
else
struct stat stat;
if (infos_dir.stat(&stat) != 0)
{
- throw IOErrorException();
+ throw IOErrorException("stat on .snapshots failed");
}
if (stat.st_uid != 0)
{
y2err(".snapshots must have owner root");
- throw IOErrorException();
+ throw IOErrorException(".snapshots must have owner root");
}
if (stat.st_gid != 0 && stat.st_mode & S_IWGRP)
{
y2err(".snapshots must have group root or must not be group-writable");
- throw IOErrorException();
+ throw IOErrorException(".snapshots must have group root or must not be group-writable");
}
if (stat.st_mode & S_IWOTH)
{
y2err(".snapshots must not be world-writable");
- throw IOErrorException();
+ throw IOErrorException(".snapshots must not be world-writable");
}
return infos_dir;
Regex.cc Regex.h \
Acls.cc Acls.h \
Hooks.cc Hooks.h \
- Exception.h \
+ Exception.cc Exception.h \
SnapperTmpl.h \
SnapperTypes.h \
SnapperDefines.h \
};
- struct ConfigNotFoundException : public SnapperException
+ struct ConfigNotFoundException : public Exception
{
- explicit ConfigNotFoundException() throw() {}
- virtual const char* what() const throw() { return "config not found"; }
+ explicit ConfigNotFoundException() : Exception("config not found") {}
};
- struct InvalidConfigException : public SnapperException
+ struct InvalidConfigException : public Exception
{
- explicit InvalidConfigException() throw() {}
- virtual const char* what() const throw() { return "invalid config"; }
+ explicit InvalidConfigException() : Exception("invalid config") {}
};
- struct InvalidConfigdataException : public SnapperException
+ struct InvalidConfigdataException : public Exception
{
- explicit InvalidConfigdataException() throw() {}
- virtual const char* what() const throw() { return "invalid configdata"; }
+ explicit InvalidConfigdataException() : Exception("invalid configdata") {}
};
- struct InvalidUserdataException : public SnapperException
+ struct InvalidUserdataException : public Exception
{
- explicit InvalidUserdataException() throw() {}
- virtual const char* what() const throw() { return "invalid userdata"; }
+ explicit InvalidUserdataException() : Exception("invalid userdata") {}
};
- struct ListConfigsFailedException : public SnapperException
+ struct ListConfigsFailedException : public Exception
{
- explicit ListConfigsFailedException(const char* msg) throw() : msg(msg) {}
- virtual const char* what() const throw() { return msg; }
- const char* msg;
+ explicit ListConfigsFailedException(const char* msg) : Exception(msg) {}
};
- struct CreateConfigFailedException : public SnapperException
+ struct CreateConfigFailedException : public Exception
{
- explicit CreateConfigFailedException(const char* msg) throw() : msg(msg) {}
- virtual const char* what() const throw() { return msg; }
- const char* msg;
+ explicit CreateConfigFailedException(const char* msg) : Exception(msg) {}
};
- struct DeleteConfigFailedException : public SnapperException
+ struct DeleteConfigFailedException : public Exception
{
- explicit DeleteConfigFailedException(const char* msg) throw() : msg(msg) {}
- virtual const char* what() const throw() { return msg; }
- const char* msg;
+ explicit DeleteConfigFailedException(const char* msg) : Exception(msg) {}
};
if (errno == EEXIST)
continue;
- y2err("mkdir failed errno:" << errno << " (" << stringerror(errno) << ")");
- throw IOErrorException();
+ throw IOErrorException(sformat("mkdir failed errno:%d (%s)", errno,
+ stringerror(errno).c_str()));
}
infos_dir.chmod(decString(num), 0755, 0);
xml.save(info_dir.mktemp(tmp_name));
if (info_dir.rename(tmp_name, file_name) != 0)
- {
- y2err("rename info.xml failed infoDir: " << info_dir.fullname() << " errno: " <<
- errno << " (" << stringerror(errno) << ")");
- throw IOErrorException();
- }
+ throw IOErrorException(sformat("rename info.xml failed infoDir:%s errno:%d (%s)",
+ info_dir.fullname().c_str(), errno,
+ stringerror(errno).c_str()));
}
enum SnapshotType { SINGLE, PRE, POST };
- struct CreateSnapshotFailedException : public SnapperException
+ struct CreateSnapshotFailedException : public Exception
{
- explicit CreateSnapshotFailedException() throw() {}
- virtual const char* what() const throw() { return "create snapshot failed"; }
+ explicit CreateSnapshotFailedException() : Exception("create snapshot failed") {}
};
- struct DeleteSnapshotFailedException : public SnapperException
+ struct DeleteSnapshotFailedException : public Exception
{
- explicit DeleteSnapshotFailedException() throw() {}
- virtual const char* what() const throw() { return "delete snapshot failed"; }
+ explicit DeleteSnapshotFailedException() : Exception("delete snapshot failed") {}
};
- struct IsSnapshotMountedFailedException : public SnapperException
+ struct IsSnapshotMountedFailedException : public Exception
{
- explicit IsSnapshotMountedFailedException() throw() {}
- virtual const char* what() const throw() { return "is snapshot mounted failed"; }
+ explicit IsSnapshotMountedFailedException() : Exception("is snapshot mounted failed") {}
};
- struct MountSnapshotFailedException : public SnapperException
+ struct MountSnapshotFailedException : public Exception
{
- explicit MountSnapshotFailedException() throw() {}
- virtual const char* what() const throw() { return "mount snapshot failed"; }
+ explicit MountSnapshotFailedException() : Exception("mount snapshot failed") {}
};
- struct UmountSnapshotFailedException : public SnapperException
+ struct UmountSnapshotFailedException : public Exception
{
- explicit UmountSnapshotFailedException() throw() {}
- virtual const char* what() const throw() { return "umount snapshot failed"; }
+ explicit UmountSnapshotFailedException() : Exception("umount snapshot failed") {}
};
close(fd);
if (!doc)
- throw IOErrorException();
+ throw IOErrorException("xmlReadFd failed");
}
: doc(xmlReadFile(filename.c_str(), NULL, XML_PARSE_NOBLANKS | XML_PARSE_NONET))
{
if (!doc)
- throw IOErrorException();
+ throw IOErrorException("xmlReadFile failed");
}
{
FILE* f = fdopen(fd, "w");
if (!f)
- throw IOErrorException();
+ throw IOErrorException("fdopen");
if (xmlDocFormatDump(f, doc, 1) == -1)
{
fclose(f);
- throw IOErrorException();
+ throw IOErrorException("xmlDocFormatDump failed");
}
fclose(f);
XmlFile::save(const string& filename)
{
if (xmlSaveFormatFile(filename.c_str(), doc, 1) == -1)
- throw IOErrorException();
+ throw IOErrorException("xmlSaveFormatFile failed");
}