1 /*********************************************************************/
2 // dar - disk archive - a backup/restoration program
3 // Copyright (C) 2002-2052 Denis Corbin
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 //
19 // to contact the author : http://dar.linux.free.fr/email.html
20 /*********************************************************************/
21 
22     /// \file erreurs.hpp
23     /// \brief contains all the excetion class thrown by libdar
24     /// \ingroup API
25 
26 #ifndef ERREURS_HPP
27 #define ERREURS_HPP
28 
29 #include "../my_config.h"
30 
31 #include <string>
32 #include <list>
33 #include "integers.hpp"
34 #include "erreurs.hpp"
35 
36 namespace libdar
37 {
38 
39 	/// \addtogroup API
40 	/// @{
41 
42 	/// a routine to change NLS domaine forth and back for inline routines
43     extern const char *dar_gettext(const char *);
44 
45 	/// this is the parent class of all exception classes.
46 
47 	/// this is a pure virtual class that provide some simple
48 	/// mechanisme to carry the information about the cause of the exception,
49 	/// as well as some a complex mechanim which not used often in libdar
50 	/// that keep trace, for each exception throwing process, of the different
51 	/// calls by which the current exception has been exiting.
52     class Egeneric
53     {
54     public :
55 	    /// the constructor
56         Egeneric(const std::string &source, const std::string &message);
57 	    /// the destructor
~Egeneric()58         virtual ~Egeneric() {};
59 
60 	    /// add more detailed couple of information to the exception
stack(const std::string & passage,const std::string & message="")61         virtual void stack(const std::string & passage, const std::string & message = "") { pile.push_back(niveau(passage, message)); };
62 
63 	    /// get the message explaing the nature of the exception
64 
65 	    /// This is probably the only method you will use for all the
66 	    /// the exception, as you will not have to create such objects
67 	    /// and will only need to get the error message thanks to this
68 	    /// method
get_message() const69         const std::string & get_message() const { return pile.front().objet; };
70 
71 	    /// get the call function which has thrown this exception
get_source() const72 	const std::string & get_source() const { return pile.front().lieu; };
73 
74 	    /// retrieve the objet (object) associated to a given "lieu" (location) from the stack
75 
76 	    /// \param[in] location key to look for the value of
77 	    /// \return returns an empty string if key is not found in the stack
78 	const std::string & find_object(const std::string & location) const;
79 
80 	    /// prepend error message by the given string
81 	void prepend_message(const std::string & context);
82 
83 	    /// dump all information of the exception to the standard error
84 	    ///
85 	    /// \note deprecated call, replaced by dump_str()
86 	void dump() const;
87 
88 	    /// return a string result of the exception information dump
89 	std::string dump_str() const;
90 
91     protected :
92         virtual std::string exceptionID() const = 0;
93 
94     private :
95         struct niveau
96         {
niveaulibdar::Egeneric::niveau97             niveau(const std::string &ou, const std::string &quoi) { lieu = ou; objet = quoi; };
98             std::string lieu, objet;
99         };
100 
101         std::list<niveau> pile;
102 
103 	static const std::string empty_string;
104     };
105 
106 
107 	/// exception used when memory has been exhausted
108 
109 	/// the inherited get_message() method is probably
110 	/// the only one you will need to use
111     class Ememory : public Egeneric
112     {
113     public:
Ememory(const std::string & source)114         Ememory(const std::string &source) : Egeneric(source, dar_gettext("Lack of Memory")) {};
115 
116     protected:
Ememory(const std::string & source,const std::string & message)117         Ememory(const std::string &source, const std::string & message) : Egeneric(source, message) {};
exceptionID() const118         std::string exceptionID() const { return "MEMORY"; };
119     };
120 
121 	/// exception used when secure memory has been exhausted
122 
123     class Esecu_memory : public Ememory
124     {
125     public:
Esecu_memory(const std::string & source)126         Esecu_memory(const std::string &source) : Ememory(source, dar_gettext("Lack of Secured Memory")) {};
127 
128     protected:
exceptionID() const129         std::string exceptionID() const { return "SECU_MEMORY"; };
130     };
131 
132 
133 #define SRC_BUG Ebug(__FILE__, __LINE__)
134 // #define XMT_BUG(exception, call) exception.stack(call, __FILE__, __LINE__)
135 
136 	/// exception used to signal a bug. A bug is triggered when reaching some code that should never be reached
137     class Ebug : public Egeneric
138     {
139     public :
140         Ebug(const std::string & file, S_I line);
141 
142 	using Egeneric::stack; // to avoid warning with clang
143         void stack(const std::string & passage, const std::string & file, const std::string & line);
144 
145     protected :
exceptionID() const146         std::string exceptionID() const { return "BUG"; };
147     };
148 
149 	/// exception used when arithmetic error is detected when operating on infinint
150 
151 	/// the inherited get_message() method is probably
152 	/// the only one you will need to use
153     class Einfinint : public Egeneric
154     {
155     public :
Einfinint(const std::string & source,const std::string & message)156         Einfinint(const std::string & source, const std::string & message) : Egeneric(source, message) {};
157 
158     protected :
exceptionID() const159         std::string exceptionID() const { return "INFININT"; };
160     };
161 
162 	/// exception used when a limitint overflow is detected, the maximum value of the limitint has been exceeded
163 
164 	/// the inherited get_message() method is probably
165 	/// the only one you will need to use
166     class Elimitint : public Egeneric
167     {
168     public :
Elimitint()169         Elimitint() : Egeneric("", dar_gettext("Cannot handle such a too large integer. Use a full version of libdar (compiled to rely on the \"infinint\" integer type) to solve this problem")) {};
170 
171     protected :
exceptionID() const172         std::string exceptionID() const { return "LIMITINT"; };
173     };
174 
175 	/// exception used to signal range error
176 
177 	/// the inherited get_message() method is probably
178 	/// the only one you will need to use
179     class Erange : public Egeneric
180     {
181     public :
Erange(const std::string & source,const std::string & message)182         Erange(const std::string & source, const std::string & message) : Egeneric(source, message) {};
183 
184     protected :
exceptionID() const185         std::string exceptionID() const { return "RANGE"; };
186     };
187 
188 	/// exception used to signal convertion problem between infinint and string (decimal representation)
189 
190 	/// the inherited get_message() method is probably
191 	/// the only one you will need to use
192 	/// see also the class deci
193     class Edeci : public Egeneric
194     {
195     public :
Edeci(const std::string & source,const std::string & message)196         Edeci(const std::string & source, const std::string & message) : Egeneric(source, message) {};
197 
198     protected :
exceptionID() const199         std::string exceptionID() const { return "DECI"; };
200     };
201 
202 	/// exception used when a requested feature is not (yet) implemented
203 
204 	/// the inherited get_message() method is probably
205 	/// the only one you will need to use
206     class Efeature : public Egeneric
207     {
208     public :
Efeature(const std::string & message)209         Efeature(const std::string & message) : Egeneric("", message) {};
210 
211     protected :
exceptionID() const212         std::string exceptionID() const { return "UNIMPLEMENTED FEATURE"; };
213     };
214 
215 	/// exception used when hardware problem is found
216 
217 	/// the inherited get_message() method is probably
218 	/// the only one you will need to use
219     class Ehardware : public Egeneric
220     {
221     public :
Ehardware(const std::string & source,const std::string & message)222         Ehardware(const std::string & source, const std::string & message) : Egeneric(source, message) {};
223 
224     protected :
exceptionID() const225         std::string exceptionID() const { return "HARDWARE ERROR"; };
226     };
227 
228 	/// exception used to signal that the user has aborted the operation
229 
230 	/// the inherited get_message() method is probably
231 	/// the only one you will need to use
232     class Euser_abort : public Egeneric
233     {
234     public :
Euser_abort(const std::string & msg)235         Euser_abort(const std::string & msg) : Egeneric("",msg) {};
236 
237     protected :
exceptionID() const238         std::string exceptionID() const { return "USER ABORTED OPERATION"; };
239     };
240 
241 
242 	/// exception used when an error concerning the treated data has been met
243 
244 	/// the inherited get_message() method is probably
245 	/// the only one you will need to use
246     class Edata : public Egeneric
247     {
248     public :
Edata(const std::string & msg)249         Edata(const std::string & msg) : Egeneric("", msg) {};
250 
251     protected :
exceptionID() const252         std::string exceptionID() const { return "ERROR IN TREATED DATA"; };
253     };
254 
255 	/// exception used when error the inter-slice user command returned an error code
256 
257 	/// the inherited get_message() method is probably
258 	/// the only one you will need to use
259     class Escript : public Egeneric
260     {
261     public :
Escript(const std::string & source,const std::string & msg)262         Escript(const std::string & source, const std::string & msg) : Egeneric(source ,msg) {};
263 
264     protected :
exceptionID() const265         std::string exceptionID() const { return "USER ABORTED OPERATION"; };
266     };
267 
268 	/// exception used to signal an error in the argument given to libdar call of the API
269 
270 	/// the inherited get_message() method is probably
271 	/// the only one you will need to use
272     class Elibcall : public Egeneric
273     {
274     public :
Elibcall(const std::string & source,const std::string & msg)275         Elibcall(const std::string & source, const std::string & msg) : Egeneric(source ,msg) {};
276 
277     protected :
exceptionID() const278         std::string exceptionID() const { return "USER ABORTED OPERATION"; };
279     };
280 
281 	/// exception used when a requested fearture has not beed activated at compilation time
282 
283 	/// the inherited get_message() method is probably
284 	/// the only one you will need to use
285     class Ecompilation : public Egeneric
286     {
287     public :
Ecompilation(const std::string & msg)288         Ecompilation(const std::string & msg) : Egeneric("" ,msg) {};
289 
290     protected :
exceptionID() const291         std::string exceptionID() const { return "FEATURE DISABLED AT COMPILATION TIME"; };
292     };
293 
294 
295 	/// exception used when the thread libdar is running in is asked to stop
296 
297     class Ethread_cancel : public Egeneric
298     {
299     public:
Ethread_cancel(bool now,U_64 x_flag)300 	Ethread_cancel(bool now, U_64 x_flag) : Egeneric("", now ? dar_gettext("Thread cancellation requested, aborting as soon as possible") : dar_gettext("Thread cancellation requested, aborting as properly as possible")) { immediate = now; flag = x_flag; };
301 
immediate_cancel() const302 	bool immediate_cancel() const { return immediate; };
get_flag() const303 	U_64 get_flag() const { return flag; };
304 
305     protected:
exceptionID() const306 	std::string exceptionID() const { return "THREAD CANCELLATION REQUESTED, ABORTING"; };
307 
308     private:
309 	bool immediate;
310 	U_64 flag;
311     };
312 
313 	/// exception used to carry system error
314 
315     class Esystem : public Egeneric
316     {
317     public:
318 	enum io_error
319 	{
320 	    io_exist,  //< file already exists (write mode)
321 	    io_absent, //< file does not exist (read mode)
322 	    io_access  //< permission denied (any mode)
323 	};
324 
325 	Esystem(const std::string & source, const std::string & message, io_error code);
326 
get_code() const327 	io_error get_code() const { return x_code; };
328 
329     protected:
exceptionID() const330 	virtual std::string exceptionID() const { return "SYSTEM ERROR MET"; };
331 
332     private:
333 	io_error x_code;
334     };
335 
336 
337 	/// @}
338 
339 } // end of namespace
340 
341 #endif
342