2 libparted - a library for manipulating disk partitions
3 Copyright (C) 1999-2000, 2007-2012 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 /** \file exception.c */
22 * \addtogroup PedException
24 * \brief Exception handling.
26 * There are a few types of exceptions: PED_EXCEPTION_INFORMATION,
27 * PED_EXCEPTION_WARNING, PED_EXCEPTION_ERROR, PED_EXCEPTION_FATAL,
30 * They are "thrown" when one of the above events occur while executing
31 * a libparted function. For example, if ped_device_open() fails
32 * because the device doesn't exist, an exception will be thrown.
33 * Exceptions contain text describing what the event was. It will give
34 * at least one option for resolving the exception: PED_EXCEPTION_FIX,
35 * PED_EXCEPTION_YES, PED_EXCEPTION_NO, PED_EXCEPTION_OK, PED_EXCEPTION_RETRY,
36 * PED_EXCEPTION_IGNORE, PED_EXCEPTION_CANCEL. After an exception is thrown,
37 * there are two things that can happen:
39 * -# an exception handler is called, which selects how the exception should be
40 * resolved (usually by asking the user). Also note: an exception handler may
41 * choose to return PED_EXCEPTION_UNHANDLED. In this case, a default action
42 * will be taken by libparted (respectively the code that threw the
43 * exception). In general, a default action will be "safe".
44 * -# the exception is not handled, because the caller of the function wants to
45 * handle everything itself. In this case, PED_EXCEPTION_UNHANDLED is
53 #include <parted/parted.h>
54 #include <parted/debug.h>
55 #include <parted/exception.h>
57 #define N_(String) String
60 # define _(String) dgettext (PACKAGE, String)
62 # define _(String) (String)
63 #endif /* ENABLE_NLS */
69 int ped_exception = 0;
71 static PedExceptionOption default_handler (PedException* ex);
73 static PedExceptionHandler* ex_handler = default_handler;
74 static PedException* ex = NULL;
75 static int ex_fetch_count = 0;
77 static const char *const type_strings [] = {
83 N_("No Implementation")
86 static const char *const option_strings [] = {
97 * Return a string describing an exception type.
100 ped_exception_get_type_string (PedExceptionType ex_type)
102 return (char *) type_strings [ex_type - 1];
105 /* FIXME: move this out to the prospective math.c */
106 /* FIXME: this can probably be done more efficiently */
107 static int _GL_ATTRIBUTE_PURE
114 for (x=0; 1 << x <= n; x++);
120 * Return a string describing an exception option.
123 ped_exception_get_option_string (PedExceptionOption ex_opt)
125 return (char *) option_strings [ped_log2 (ex_opt)];
128 static PedExceptionOption
129 default_handler (PedException* e)
131 if (e->type == PED_EXCEPTION_BUG)
133 _("A bug has been detected in GNU Parted. "
134 "Refer to the web site of parted "
135 "http://www.gnu.org/software/parted/parted.html "
136 "for more information of what could be useful "
137 "for bug submitting! "
138 "Please email a bug report to "
139 "%s containing at least the "
140 "version (%s) and the following message: "),
141 PACKAGE_BUGREPORT, VERSION);
143 fprintf (stderr, "%s: ",
144 ped_exception_get_type_string (e->type));
145 fprintf (stderr, "%s\n", e->message);
147 switch (e->options) {
148 case PED_EXCEPTION_OK:
149 case PED_EXCEPTION_CANCEL:
150 case PED_EXCEPTION_IGNORE:
154 return PED_EXCEPTION_UNHANDLED;
159 * Set the exception handler.
161 * The exception handler should return ONE of the options set in ex->options,
162 * indicating the way the event should be resolved.
165 ped_exception_set_handler (PedExceptionHandler* handler)
168 ex_handler = handler;
170 ex_handler = default_handler;
174 * Get the current exception handler.
176 PedExceptionHandler *
177 ped_exception_get_handler (void)
181 return default_handler;
185 * Assert that the current exception has been resolved.
188 ped_exception_catch ()
198 static PedExceptionOption
201 PedExceptionOption ex_opt;
205 if (ex_fetch_count) {
206 return PED_EXCEPTION_UNHANDLED;
208 ex_opt = ex_handler (ex);
209 ped_exception_catch ();
215 * Throw an exception.
217 * You can also use this in a program using libparted.
218 * "message" is a printf-like format string, so you can do
221 * ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_CANCEL,
222 * "Can't open %s", file_name);
225 * Returns the option selected to resolve the exception. If the exception was
226 * unhandled, PED_EXCEPTION_UNHANDLED is returned.
229 ped_exception_throw (PedExceptionType ex_type,
230 PedExceptionOption ex_opts, const char* message, ...)
234 static int size = 1000;
237 ped_exception_catch ();
239 ex = (PedException*) malloc (sizeof (PedException));
244 ex->options = ex_opts;
247 ex->message = (char*) malloc (size * sizeof (char));
251 va_start (arg_list, message);
252 result = vsnprintf (ex->message, size, message, arg_list);
255 if (result > -1 && result < size)
265 fputs ("Out of memory in exception handler!\n", stderr);
267 va_start (arg_list, message);
268 vfprintf (stderr, message, arg_list);
271 return PED_EXCEPTION_UNHANDLED;
275 * Rethrow an unhandled exception.
276 * This means repeating the last ped_exception_throw() statement.
279 ped_exception_rethrow ()
285 * Indicates that exceptions should not go to the exception handler, but
286 * passed up to the calling function(s). All calls to
287 * ped_exception_throw() will return PED_EXCEPTION_UNHANDLED.
290 ped_exception_fetch_all ()
296 * Indicates that the calling function does not want to accept any
297 * responsibility for exceptions any more.
299 * \note a caller of that function may still want responsibility, so
300 * ped_exception_throw() may not invoke the exception handler.
302 * \warning every call to this function must have a preceding
303 * ped_exception_fetch_all().
306 ped_exception_leave_all ()
308 PED_ASSERT (ex_fetch_count > 0);