Coverage Report

Created: 2026-01-17 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5E.c
Line
Count
Source
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the LICENSE file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/*
14
 * Purpose: Provides error handling in the form of a stack.  The
15
 *    FUNC_ENTER() macro clears the error stack whenever an API
16
 *    function is entered.  When an error is detected, an entry is
17
 *    pushed onto the stack.  As the functions unwind additional
18
 *    entries are pushed onto the stack. The API function will
19
 *    return some indication that an error occurred and the
20
 *    application can print the error stack.
21
 *
22
 *    Certain API functions in the H5E package (such as H5Eprint2())
23
 *    do not clear the error stack.  Otherwise, any function which
24
 *    doesn't have an underscore immediately after the package name
25
 *    will clear the error stack.  For instance, H5Fopen() clears
26
 *    the error stack while H5F_open() does not.
27
 *
28
 *    An error stack has a fixed maximum size.  If this size is
29
 *    exceeded then the stack will be truncated and only the
30
 *    inner-most functions will have entries on the stack. This is
31
 *    expected to be a rare condition.
32
 *
33
 *    Each thread has its own error stack, but since
34
 *    multi-threading has not been added to the library yet, this
35
 *    package maintains a single error stack. The error stack is
36
 *    statically allocated to reduce the complexity of handling
37
 *    errors within the H5E package.
38
 *
39
 */
40
41
/****************/
42
/* Module Setup */
43
/****************/
44
45
#include "H5Emodule.h" /* This source code file is part of the H5E module */
46
47
/***********/
48
/* Headers */
49
/***********/
50
#include "H5private.h"   /* Generic Functions                        */
51
#include "H5Epkg.h"      /* Error handling                           */
52
#include "H5FLprivate.h" /* Free lists                               */
53
#include "H5Iprivate.h"  /* IDs                                      */
54
#include "H5MMprivate.h" /* Memory management                        */
55
56
/****************/
57
/* Local Macros */
58
/****************/
59
60
/******************/
61
/* Local Typedefs */
62
/******************/
63
64
/********************/
65
/* Package Typedefs */
66
/********************/
67
68
/********************/
69
/* Local Prototypes */
70
/********************/
71
72
/*********************/
73
/* Package Variables */
74
/*********************/
75
76
/* Package initialization variable */
77
bool H5_PKG_INIT_VAR = false;
78
79
/* Declare extern the free list to manage the H5E_stack_t struct */
80
H5FL_EXTERN(H5E_stack_t);
81
82
/*****************************/
83
/* Library Private Variables */
84
/*****************************/
85
86
/*******************/
87
/* Local Variables */
88
/*******************/
89
90
/*-------------------------------------------------------------------------
91
 * Function:    H5Eregister_class
92
 *
93
 * Purpose:     Registers an error class.
94
 *
95
 * Return:      Success:    An ID for the error class
96
 *              Failure:    H5I_INVALID_HID
97
 *
98
 *-------------------------------------------------------------------------
99
 */
100
hid_t
101
H5Eregister_class(const char *cls_name, const char *lib_name, const char *version)
102
0
{
103
0
    H5E_cls_t *cls;                         /* Pointer to error class */
104
0
    hid_t      ret_value = H5I_INVALID_HID; /* Return value */
105
106
0
    FUNC_ENTER_API(H5I_INVALID_HID)
107
108
    /* Check arguments */
109
0
    if (cls_name == NULL || lib_name == NULL || version == NULL)
110
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid string");
111
112
    /* Create the new error class object */
113
0
    if (NULL == (cls = H5E__register_class(cls_name, lib_name, version)))
114
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, H5I_INVALID_HID, "can't create error class");
115
116
    /* Register the new error class to get an ID for it */
117
0
    if ((ret_value = H5I_register(H5I_ERROR_CLASS, cls, true)) < 0)
118
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register error class");
119
120
0
done:
121
0
    FUNC_LEAVE_API(ret_value)
122
0
} /* end H5Eregister_class() */
123
124
/*-------------------------------------------------------------------------
125
 * Function:    H5Eunregister_class
126
 *
127
 * Purpose:     Closes an error class.
128
 *
129
 * Return:      Non-negative value on success/Negative on failure
130
 *
131
 *-------------------------------------------------------------------------
132
 */
133
herr_t
134
H5Eunregister_class(hid_t class_id)
135
0
{
136
0
    herr_t ret_value = SUCCEED; /* Return value */
137
138
0
    FUNC_ENTER_API(FAIL)
139
140
    /* Check arguments */
141
0
    if (H5I_ERROR_CLASS != H5I_get_type(class_id))
142
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error class");
143
144
    /*
145
     * Decrement the counter on the dataset.  It will be freed if the count
146
     * reaches zero.
147
     */
148
0
    if (H5I_dec_app_ref(class_id) < 0)
149
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error class");
150
151
0
done:
152
0
    FUNC_LEAVE_API(ret_value)
153
0
} /* end H5Eunregister_class() */
154
155
/*-------------------------------------------------------------------------
156
 * Function:    H5Eget_class_name
157
 *
158
 * Purpose:     Retrieves error class name.
159
 *
160
 * Return:      Success:    Name length (zero means no name)
161
 *              Failure:    -1
162
 *
163
 *-------------------------------------------------------------------------
164
 */
165
ssize_t
166
H5Eget_class_name(hid_t class_id, char *name /*out*/, size_t size)
167
0
{
168
0
    H5E_cls_t *cls;            /* Pointer to error class */
169
0
    ssize_t    ret_value = -1; /* Return value */
170
171
0
    FUNC_ENTER_API((-1))
172
173
    /* Get the error class */
174
0
    if (NULL == (cls = (H5E_cls_t *)H5I_object_verify(class_id, H5I_ERROR_CLASS)))
175
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a error class ID");
176
177
    /* Retrieve the class name */
178
0
    if ((ret_value = H5E__get_class_name(cls, name, size)) < 0)
179
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, (-1), "can't get error class name");
180
181
0
done:
182
0
    FUNC_LEAVE_API(ret_value)
183
0
} /* end H5Eget_class_name() */
184
185
/*-------------------------------------------------------------------------
186
 * Function:    H5Eclose_msg
187
 *
188
 * Purpose:     Closes a major or minor error.
189
 *
190
 * Return:      SUCCEED/FAIL
191
 *
192
 *-------------------------------------------------------------------------
193
 */
194
herr_t
195
H5Eclose_msg(hid_t err_id)
196
0
{
197
0
    herr_t ret_value = SUCCEED; /* Return value */
198
199
0
    FUNC_ENTER_API(FAIL)
200
201
    /* Check arguments */
202
0
    if (H5I_ERROR_MSG != H5I_get_type(err_id))
203
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error class");
204
205
    /* Decrement the counter.  It will be freed if the count reaches zero. */
206
0
    if (H5I_dec_app_ref(err_id) < 0)
207
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message");
208
209
0
done:
210
0
    FUNC_LEAVE_API(ret_value)
211
0
} /* end H5Eclose_msg() */
212
213
/*-------------------------------------------------------------------------
214
 * Function:    H5Ecreate_msg
215
 *
216
 * Purpose:     Creates a major or minor error, returns an ID.
217
 *
218
 * Return:      Success:    An error ID
219
 *              Failure:    H5I_INVALID_HID
220
 *
221
 *-------------------------------------------------------------------------
222
 */
223
hid_t
224
H5Ecreate_msg(hid_t class_id, H5E_type_t msg_type, const char *msg_str)
225
0
{
226
0
    H5E_cls_t *cls;                         /* Pointer to error class */
227
0
    H5E_msg_t *msg;                         /* Pointer to new error message */
228
0
    hid_t      ret_value = H5I_INVALID_HID; /* Return value */
229
230
0
    FUNC_ENTER_API(H5I_INVALID_HID)
231
232
    /* Check arguments */
233
0
    if (msg_type != H5E_MAJOR && msg_type != H5E_MINOR)
234
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "not a valid message type");
235
0
    if (msg_str == NULL)
236
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "message is NULL");
237
238
    /* Get the error class */
239
0
    if (NULL == (cls = (H5E_cls_t *)H5I_object_verify(class_id, H5I_ERROR_CLASS)))
240
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not an error class ID");
241
242
    /* Create the new error message object */
243
0
    if (NULL == (msg = H5E__create_msg(cls, msg_type, msg_str)))
244
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, H5I_INVALID_HID, "can't create error message");
245
246
    /* Register the new error class to get an ID for it */
247
0
    if ((ret_value = H5I_register(H5I_ERROR_MSG, msg, true)) < 0)
248
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register error message");
249
250
0
done:
251
0
    FUNC_LEAVE_API(ret_value)
252
0
} /* end H5Ecreate_msg() */
253
254
/*-------------------------------------------------------------------------
255
 * Function:    H5Eget_msg
256
 *
257
 * Purpose:     Retrieves an error message.
258
 *
259
 * Return:      Success:    Message length (zero means no message)
260
 *              Failure:    -1
261
 *
262
 *-------------------------------------------------------------------------
263
 */
264
ssize_t
265
H5Eget_msg(hid_t msg_id, H5E_type_t *type /*out*/, char *msg_str /*out*/, size_t size)
266
0
{
267
0
    H5E_msg_t *msg;            /* Pointer to error message */
268
0
    ssize_t    ret_value = -1; /* Return value */
269
270
0
    FUNC_ENTER_API_NOCLEAR((-1))
271
272
    /* Get the message object */
273
0
    if (NULL == (msg = (H5E_msg_t *)H5I_object_verify(msg_id, H5I_ERROR_MSG)))
274
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a error message ID");
275
276
    /* Get the message's text */
277
0
    if ((ret_value = H5E__get_msg(msg, type, msg_str, size)) < 0)
278
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, (-1), "can't get error message text");
279
280
0
done:
281
0
    FUNC_LEAVE_API(ret_value)
282
0
} /* end H5Eget_msg() */
283
284
/*-------------------------------------------------------------------------
285
 * Function:    H5Ecreate_stack
286
 *
287
 * Purpose:     Creates a new, empty, error stack.
288
 *
289
 * Return:      Success:    An error stack ID
290
 *              Failure:    H5I_INVALID_HID
291
 *
292
 *-------------------------------------------------------------------------
293
 */
294
hid_t
295
H5Ecreate_stack(void)
296
0
{
297
0
    H5E_stack_t *stk;                         /* Error stack */
298
0
    hid_t        ret_value = H5I_INVALID_HID; /* Return value */
299
300
0
    FUNC_ENTER_API(H5I_INVALID_HID)
301
302
    /* Allocate a new error stack */
303
0
    if (NULL == (stk = H5FL_CALLOC(H5E_stack_t)))
304
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_INVALID_HID, "memory allocation failed");
305
306
    /* Set the "automatic" error reporting info to the library default */
307
0
    H5E__set_default_auto(stk);
308
309
    /* Register the stack */
310
0
    if ((ret_value = H5I_register(H5I_ERROR_STACK, stk, true)) < 0)
311
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, H5I_INVALID_HID, "can't create error stack");
312
313
0
done:
314
0
    FUNC_LEAVE_API(ret_value)
315
0
} /* end H5Ecreate_stack() */
316
317
/*-------------------------------------------------------------------------
318
 * Function:    H5Eget_current_stack
319
 *
320
 * Purpose:     Registers current error stack, returns object handle for it,
321
 *              clears it.
322
 *
323
 * Return:      Success:    An error stack ID
324
 *              Failure:    H5I_INVALID_HID
325
 *
326
 *-------------------------------------------------------------------------
327
 */
328
hid_t
329
H5Eget_current_stack(void)
330
0
{
331
0
    H5E_stack_t *stk;                         /* Error stack */
332
0
    hid_t        ret_value = H5I_INVALID_HID; /* Return value */
333
334
    /* Don't clear the error stack! :-) */
335
0
    FUNC_ENTER_API_NOCLEAR(H5I_INVALID_HID)
336
337
    /* Get the current stack */
338
0
    if (NULL == (stk = H5E__get_current_stack()))
339
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, H5I_INVALID_HID, "can't create error stack");
340
341
    /* Register the stack */
342
0
    if ((ret_value = H5I_register(H5I_ERROR_STACK, stk, true)) < 0)
343
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, H5I_INVALID_HID, "can't create error stack");
344
345
0
done:
346
0
    FUNC_LEAVE_API(ret_value)
347
0
} /* end H5Eget_current_stack() */
348
349
/*-------------------------------------------------------------------------
350
 * Function:    H5Eset_current_stack
351
 *
352
 * Purpose:     Replaces current stack with specified stack. This closes the
353
 *              stack ID also.
354
 *
355
 * Return:      Non-negative value on success/Negative on failure
356
 *
357
 *-------------------------------------------------------------------------
358
 */
359
herr_t
360
H5Eset_current_stack(hid_t err_stack)
361
0
{
362
0
    H5E_stack_t *estack;
363
0
    herr_t       ret_value = SUCCEED; /* Return value */
364
365
0
    FUNC_ENTER_API(FAIL)
366
367
0
    if (err_stack != H5E_DEFAULT) {
368
0
        if (NULL == (estack = (H5E_stack_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
369
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID");
370
371
        /* Set the current error stack */
372
0
        if (H5E__set_current_stack(estack) < 0)
373
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "unable to set error stack");
374
375
        /*
376
         * Decrement the counter on the error stack.  It will be freed if the count
377
         * reaches zero.
378
         */
379
0
        if (H5I_dec_app_ref(err_stack) < 0)
380
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error stack");
381
0
    } /* end if */
382
383
0
done:
384
0
    FUNC_LEAVE_API(ret_value)
385
0
} /* end H5Eset_current_stack() */
386
387
/*-------------------------------------------------------------------------
388
 * Function:    H5Eclose_stack
389
 *
390
 * Purpose:     Closes an error stack.
391
 *
392
 * Return:      Non-negative value on success/Negative on failure
393
 *
394
 *-------------------------------------------------------------------------
395
 */
396
herr_t
397
H5Eclose_stack(hid_t stack_id)
398
0
{
399
0
    herr_t ret_value = SUCCEED; /* Return value */
400
401
0
    FUNC_ENTER_API(FAIL)
402
403
0
    if (H5E_DEFAULT != stack_id) {
404
        /* Check arguments */
405
0
        if (H5I_ERROR_STACK != H5I_get_type(stack_id))
406
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID");
407
408
        /*
409
         * Decrement the counter on the error stack.  It will be freed if the count
410
         * reaches zero.
411
         */
412
0
        if (H5I_dec_app_ref(stack_id) < 0)
413
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error stack");
414
0
    } /* end if */
415
416
0
done:
417
0
    FUNC_LEAVE_API(ret_value)
418
0
} /* end H5Eclose_stack() */
419
420
/*-------------------------------------------------------------------------
421
 * Function:    H5Eget_num
422
 *
423
 * Purpose:     Retrieves the number of error messages.
424
 *
425
 * Return:      Success:    The number of errors
426
 *              Failure:    -1
427
 *
428
 *-------------------------------------------------------------------------
429
 */
430
ssize_t
431
H5Eget_num(hid_t error_stack_id)
432
0
{
433
0
    H5E_stack_t *estack;    /* Error stack to operate on */
434
0
    ssize_t      ret_value; /* Return value */
435
436
    /* Don't clear the error stack! :-) */
437
0
    FUNC_ENTER_API_NOCLEAR((-1))
438
439
    /* Need to check for errors */
440
0
    if (error_stack_id == H5E_DEFAULT) {
441
0
        if (NULL == (estack = H5E__get_my_stack()))
442
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, (-1), "can't get current error stack");
443
0
    } /* end if */
444
0
    else {
445
        /* Only clear the error stack if it's not the default stack */
446
0
        H5E_clear_stack();
447
448
        /* Get the error stack to operate on */
449
0
        if (NULL == (estack = (H5E_stack_t *)H5I_object_verify(error_stack_id, H5I_ERROR_STACK)))
450
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not an error stack ID");
451
0
    } /* end else */
452
453
    /* Get the number of errors on stack */
454
0
    if ((ret_value = H5E__get_num(estack)) < 0)
455
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, (-1), "can't get number of errors");
456
457
0
done:
458
0
    FUNC_LEAVE_API(ret_value)
459
0
} /* end H5Eget_num() */
460
461
/*-------------------------------------------------------------------------
462
 * Function:    H5Epop
463
 *
464
 * Purpose:     Deletes some error messages from the top of error stack.
465
 *
466
 * Return:      Non-negative value on success/Negative on failure
467
 *
468
 *-------------------------------------------------------------------------
469
 */
470
herr_t
471
H5Epop(hid_t err_stack, size_t count)
472
0
{
473
0
    H5E_stack_t *estack;
474
0
    herr_t       ret_value = SUCCEED; /* Return value */
475
476
    /* Don't clear the error stack! :-) */
477
0
    FUNC_ENTER_API_NOCLEAR(FAIL)
478
479
    /* Need to check for errors */
480
0
    if (err_stack == H5E_DEFAULT) {
481
0
        if (NULL == (estack = H5E__get_my_stack()))
482
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack");
483
0
    } /* end if */
484
0
    else {
485
        /* Only clear the error stack if it's not the default stack */
486
0
        H5E_clear_stack();
487
488
        /* Get the error stack to operate on */
489
0
        if (NULL == (estack = (H5E_stack_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
490
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID");
491
0
    } /* end else */
492
493
    /* Range limit the number of errors to pop off stack */
494
0
    if (count > estack->nused)
495
0
        count = estack->nused;
496
497
    /* Pop the errors off the stack */
498
0
    if (H5E__pop(estack, count) < 0)
499
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTRELEASE, FAIL, "can't pop errors from stack");
500
501
0
done:
502
0
    FUNC_LEAVE_API(ret_value)
503
0
} /* end H5Epop() */
504
505
/*-------------------------------------------------------------------------
506
 * Function:    H5Epush2
507
 *
508
 * Purpose:     Pushes a new error record onto error stack for the current
509
 *              thread. The error has major and minor IDs MAJ_ID and
510
 *              MIN_ID, the name of a function where the error was detected,
511
 *              the name of the file where the error was detected, the
512
 *              line within that file, and an error description string.  The
513
 *              function name, file name, and error description strings must
514
 *              be statically allocated.
515
 *
516
 * Return:      Non-negative on success/Negative on failure
517
 *
518
 * Notes:       Basically a new public API wrapper around the H5E__push_stack
519
 *              function.
520
 *
521
 *-------------------------------------------------------------------------
522
 */
523
H5_ATTR_FORMAT(printf, 8, 9)
524
herr_t
525
H5Epush2(hid_t err_stack, const char *file, const char *func, unsigned line, hid_t cls_id, hid_t maj_id,
526
         hid_t min_id, const char *fmt, ...)
527
0
{
528
0
    H5E_stack_t *estack;              /* Pointer to error stack to modify */
529
0
    va_list      ap;                  /* Varargs info */
530
0
    bool         va_started = false;  /* Whether the variable argument list is open */
531
0
    const char  *tmp_file;            /* Copy of the file name */
532
0
    const char  *tmp_func;            /* Copy of the function name */
533
0
    herr_t       ret_value = SUCCEED; /* Return value */
534
535
    /* Don't clear the error stack! :-) */
536
0
    FUNC_ENTER_API_NOCLEAR(FAIL)
537
538
    /* Check for 'default' error stack */
539
0
    if (err_stack == H5E_DEFAULT) {
540
0
        if (NULL == (estack = H5E__get_my_stack()))
541
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get the default error stack");
542
0
    }
543
0
    else {
544
        /* Only clear the error stack if it's not the default stack */
545
0
        H5E_clear_stack();
546
547
        /* Get the error stack to operate on */
548
0
        if (NULL == (estack = (H5E_stack_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
549
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID");
550
0
    } /* end else */
551
552
    /* Check if error reporting is paused for this stack */
553
0
    if (!estack->paused) {
554
        /* Start the variable-argument parsing */
555
0
        va_start(ap, fmt);
556
0
        va_started = true;
557
558
        /* Duplicate string information */
559
0
        if (NULL == (tmp_file = strdup(file)))
560
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTALLOC, FAIL, "can't duplicate file string");
561
0
        if (NULL == (tmp_func = strdup(func)))
562
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTALLOC, FAIL, "can't duplicate function string");
563
564
        /* Increment refcount on non-library IDs */
565
0
        if (cls_id != H5E_ERR_CLS_g)
566
0
            if (H5I_inc_ref(cls_id, false) < 0)
567
0
                HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "can't increment class ID");
568
0
        if (maj_id < H5E_first_maj_id_g || maj_id > H5E_last_maj_id_g)
569
0
            if (H5I_inc_ref(maj_id, false) < 0)
570
0
                HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "can't increment major error ID");
571
0
        if (min_id < H5E_first_min_id_g || min_id > H5E_last_min_id_g)
572
0
            if (H5I_inc_ref(min_id, false) < 0)
573
0
                HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "can't increment minor error ID");
574
575
        /* Push the error on the stack */
576
0
        if (H5E__push_stack(estack, true, tmp_file, tmp_func, line, cls_id, maj_id, min_id, fmt, &ap) < 0)
577
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't push error on stack");
578
0
    }
579
580
0
done:
581
0
    if (va_started)
582
0
        va_end(ap);
583
584
0
    FUNC_LEAVE_API(ret_value)
585
0
} /* end H5Epush2() */
586
587
/*-------------------------------------------------------------------------
588
 * Function:    H5Eclear2
589
 *
590
 * Purpose:     Clears the error stack for the specified error stack.
591
 *
592
 * Return:      Non-negative on success/Negative on failure
593
 *
594
 *-------------------------------------------------------------------------
595
 */
596
herr_t
597
H5Eclear2(hid_t err_stack)
598
0
{
599
0
    H5E_stack_t *estack;              /* Error stack to operate on */
600
0
    herr_t       ret_value = SUCCEED; /* Return value */
601
602
    /* Don't clear the error stack! :-) */
603
0
    FUNC_ENTER_API_NOCLEAR(FAIL)
604
605
    /* Need to check for errors */
606
0
    if (err_stack == H5E_DEFAULT)
607
0
        estack = NULL;
608
0
    else {
609
        /* Only clear the error stack if it's not the default stack */
610
0
        H5E_clear_stack();
611
612
0
        if (NULL == (estack = (H5E_stack_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
613
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID");
614
0
    } /* end else */
615
616
    /* Clear the error stack */
617
0
    if (H5E__destroy_stack(estack) < 0)
618
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't clear error stack");
619
620
0
done:
621
0
    FUNC_LEAVE_API(ret_value)
622
0
} /* end H5Eclear2() */
623
624
/*-------------------------------------------------------------------------
625
 * Function:    H5Eprint2
626
 *
627
 * Purpose:     Prints the error stack in some default way. This is just a
628
 *              convenience function for H5Ewalk() with a function that
629
 *              prints error messages. Users are encouraged to write their
630
 *              own more specific error handlers.
631
 *
632
 * Return:      Non-negative on success/Negative on failure
633
 *
634
 *-------------------------------------------------------------------------
635
 */
636
herr_t
637
H5Eprint2(hid_t err_stack, FILE *stream)
638
0
{
639
0
    herr_t ret_value = SUCCEED; /* Return value */
640
641
    /* Don't clear the error stack! :-) */
642
0
    FUNC_ENTER_API_NOCLEAR(FAIL)
643
644
    /* Print error stack */
645
0
    if ((ret_value = H5E__print2(err_stack, stream)) < 0)
646
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't display error stack");
647
648
0
done:
649
0
    FUNC_LEAVE_API(ret_value)
650
0
} /* end H5Eprint2() */
651
652
/*-------------------------------------------------------------------------
653
 * Function:    H5Ewalk2
654
 *
655
 * Purpose:     Walks the error stack for the current thread and calls some
656
 *              function for each error along the way.
657
 *
658
 * Return:      Non-negative on success/Negative on failure
659
 *
660
 *-------------------------------------------------------------------------
661
 */
662
herr_t
663
H5Ewalk2(hid_t err_stack, H5E_direction_t direction, H5E_walk2_t stack_func, void *client_data)
664
0
{
665
0
    H5E_stack_t  *estack;              /* Error stack to operate on */
666
0
    H5E_walk_op_t op;                  /* Operator for walking error stack */
667
0
    herr_t        ret_value = SUCCEED; /* Return value */
668
669
    /* Don't clear the error stack! :-) */
670
0
    FUNC_ENTER_API_NOCLEAR(FAIL)
671
672
    /* Need to check for errors */
673
0
    if (err_stack == H5E_DEFAULT) {
674
0
        if (NULL == (estack = H5E__get_my_stack()))
675
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack");
676
0
    } /* end if */
677
0
    else {
678
        /* Only clear the error stack if it's not the default stack */
679
0
        H5E_clear_stack();
680
681
0
        if (NULL == (estack = (H5E_stack_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
682
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID");
683
0
    } /* end else */
684
685
    /* Walk the error stack */
686
0
    op.vers    = 2;
687
0
    op.u.func2 = stack_func;
688
0
    if ((ret_value = H5E__walk(estack, direction, &op, client_data)) < 0)
689
0
        HERROR(H5E_ERROR, H5E_CANTLIST, "can't walk error stack");
690
691
0
done:
692
0
    FUNC_LEAVE_API(ret_value)
693
0
} /* end H5Ewalk2() */
694
695
/*-------------------------------------------------------------------------
696
 * Function:    H5Eget_auto2
697
 *
698
 * Purpose:     Returns the current settings for the automatic error stack
699
 *              traversal function and its data for specific error stack.
700
 *              Either (or both) arguments may be null in which case the
701
 *              value is not returned.
702
 *
703
 * Return:      Non-negative value on success/Negative on failure
704
 *
705
 *-------------------------------------------------------------------------
706
 */
707
herr_t
708
H5Eget_auto2(hid_t estack_id, H5E_auto2_t *func /*out*/, void **client_data /*out*/)
709
0
{
710
0
    H5E_stack_t  *estack;              /* Error stack to operate on */
711
0
    H5E_auto_op_t op;                  /* Error stack function */
712
0
    herr_t        ret_value = SUCCEED; /* Return value */
713
714
    /* Don't clear the error stack! :-) */
715
0
    FUNC_ENTER_API_NOCLEAR(FAIL)
716
717
0
    if (estack_id == H5E_DEFAULT) {
718
0
        if (NULL == (estack = H5E__get_my_stack()))
719
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack");
720
0
    } /* end if */
721
0
    else {
722
        /* Only clear the error stack if it's not the default stack */
723
0
        H5E_clear_stack();
724
725
0
        if (NULL == (estack = (H5E_stack_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK)))
726
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID");
727
0
    } /* end else */
728
729
    /* Get the automatic error reporting information */
730
0
    if (H5E__get_auto(estack, &op, client_data) < 0)
731
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info");
732
733
0
#ifndef H5_NO_DEPRECATED_SYMBOLS
734
    /* Fail if the printing function isn't the default(user-set) and set through H5Eset_auto1 */
735
0
    if (!op.is_default && op.vers == 1)
736
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "wrong API function, H5Eset_auto1 has been called");
737
0
#endif /* H5_NO_DEPRECATED_SYMBOLS */
738
739
0
    if (func)
740
0
        *func = op.func2;
741
742
0
done:
743
0
    FUNC_LEAVE_API(ret_value)
744
0
} /* end H5Eget_auto2() */
745
746
/*-------------------------------------------------------------------------
747
 * Function:    H5Eset_auto2
748
 *
749
 * Purpose:     Turns on or off automatic printing of errors for certain
750
 *              error stack.  When turned on (non-null FUNC pointer) any
751
 *              API function which returns an error indication will first
752
 *              call FUNC passing it CLIENT_DATA as an argument.
753
 *
754
 *              The default values before this function is called are
755
 *              H5Eprint2() with client data being the standard error stream,
756
 *              stderr.
757
 *
758
 *              Automatic stack traversal is always in the H5E_WALK_DOWNWARD
759
 *              direction.
760
 *
761
 * Return:      Non-negative value on success/Negative on failure
762
 *
763
 *-------------------------------------------------------------------------
764
 */
765
herr_t
766
H5Eset_auto2(hid_t estack_id, H5E_auto2_t func, void *client_data)
767
0
{
768
0
    H5E_stack_t  *estack;              /* Error stack to operate on */
769
0
    H5E_auto_op_t op;                  /* Error stack operator */
770
0
    herr_t        ret_value = SUCCEED; /* Return value */
771
772
    /* Don't clear the error stack! :-) */
773
0
    FUNC_ENTER_API_NOCLEAR(FAIL)
774
775
0
    if (estack_id == H5E_DEFAULT) {
776
0
        if (NULL == (estack = H5E__get_my_stack()))
777
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack");
778
0
    } /* end if */
779
0
    else {
780
        /* Only clear the error stack if it's not the default stack */
781
0
        H5E_clear_stack();
782
783
0
        if (NULL == (estack = (H5E_stack_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK)))
784
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID");
785
0
    } /* end else */
786
787
0
#ifndef H5_NO_DEPRECATED_SYMBOLS
788
    /* Get the automatic error reporting information */
789
0
    if (H5E__get_auto(estack, &op, NULL) < 0)
790
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info");
791
792
    /* Set the automatic error reporting information */
793
0
    if (func != op.func2_default)
794
0
        op.is_default = false;
795
0
    else
796
0
        op.is_default = true;
797
798
0
    op.vers = 2;
799
0
#endif /* H5_NO_DEPRECATED_SYMBOLS */
800
801
    /* Set the automatic error reporting function */
802
0
    op.func2 = func;
803
804
0
    if (H5E__set_auto(estack, &op, client_data) < 0)
805
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set automatic error info");
806
807
0
done:
808
0
    FUNC_LEAVE_API(ret_value)
809
0
} /* end H5Eset_auto2() */
810
811
/*-------------------------------------------------------------------------
812
 * Function:    H5Eauto_is_v2
813
 *
814
 * Purpose:     Determines if the error auto reporting function for an
815
 *              error stack conforms to the H5E_auto_stack_t typedef
816
 *              or the H5E_auto_t typedef.  The IS_STACK parameter is set
817
 *              to 1 for the first case and 0 for the latter case.
818
 *
819
 * Return:      Non-negative value on success/Negative on failure
820
 *
821
 *-------------------------------------------------------------------------
822
 */
823
herr_t
824
H5Eauto_is_v2(hid_t estack_id, unsigned *is_stack)
825
0
{
826
0
    H5E_stack_t *estack;              /* Error stack to operate on */
827
0
    herr_t       ret_value = SUCCEED; /* Return value */
828
829
    /* Don't clear the error stack! :-) */
830
0
    FUNC_ENTER_API_NOCLEAR(FAIL)
831
832
0
    if (estack_id == H5E_DEFAULT) {
833
0
        if (NULL == (estack = H5E__get_my_stack()))
834
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack");
835
0
    } /* end if */
836
0
    else {
837
        /* Only clear the error stack if it's not the default stack */
838
0
        H5E_clear_stack();
839
840
0
        if (NULL == (estack = (H5E_stack_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK)))
841
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID");
842
0
    } /* end else */
843
844
    /* Check if the error stack reporting function is the "newer" stack type */
845
0
    if (is_stack)
846
0
#ifndef H5_NO_DEPRECATED_SYMBOLS
847
0
        *is_stack = estack->auto_op.vers > 1;
848
#else
849
        *is_stack = 1;
850
#endif
851
852
0
done:
853
0
    FUNC_LEAVE_API(ret_value)
854
0
} /* end H5Eauto_is_v2() */
855
856
/*-------------------------------------------------------------------------
857
 * Function:    H5Eappend_stack
858
 *
859
 * Purpose:     Appends one error stack to another, optionally closing the
860
 *              source stack.
861
 *
862
 * Return:      Non-negative value on success/Negative on failure
863
 *
864
 *-------------------------------------------------------------------------
865
 */
866
herr_t
867
H5Eappend_stack(hid_t dst_stack_id, hid_t src_stack_id, bool close_source_stack)
868
0
{
869
0
    H5E_stack_t *dst_stack, *src_stack; /* Error stacks */
870
0
    herr_t       ret_value = SUCCEED;   /* Return value */
871
872
0
    FUNC_ENTER_API(FAIL)
873
874
    /* Check args */
875
0
    if (NULL == (dst_stack = (H5E_stack_t *)H5I_object_verify(dst_stack_id, H5I_ERROR_STACK)))
876
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dst_stack_id not a error stack ID");
877
0
    if (NULL == (src_stack = (H5E_stack_t *)H5I_object_verify(src_stack_id, H5I_ERROR_STACK)))
878
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "src_stack_id not a error stack ID");
879
880
    /* Append the source stack to the destination stack */
881
0
    if (H5E__append_stack(dst_stack, src_stack) < 0)
882
0
        HGOTO_ERROR(H5E_ERROR, H5E_CANTAPPEND, FAIL, "can't append stack");
883
884
    /* Close source error stack, if requested */
885
0
    if (close_source_stack)
886
        /* Decrement the counter on the error stack.  It will be freed if the
887
         * count reaches zero.
888
         */
889
0
        if (H5I_dec_app_ref(src_stack_id) < 0)
890
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on source error stack");
891
892
0
done:
893
0
    FUNC_LEAVE_API(ret_value)
894
0
} /* end H5Eappend_stack() */
895
896
/*-------------------------------------------------------------------------
897
 * Function:    H5Eis_paused
898
 *
899
 * Purpose:     Check if pushing errors on an error stack is paused
900
 *
901
 * Return:      Non-negative value on success/Negative on failure
902
 *
903
 *-------------------------------------------------------------------------
904
 */
905
herr_t
906
H5Eis_paused(hid_t stack_id, bool *is_paused)
907
0
{
908
0
    H5E_stack_t *stack;               /* Error stack */
909
0
    herr_t       ret_value = SUCCEED; /* Return value */
910
911
    /* Don't clear the error stack! :-) */
912
0
    FUNC_ENTER_API_NOCLEAR(FAIL)
913
914
    /* Get the correct error stack */
915
0
    if (stack_id == H5E_DEFAULT) {
916
0
        if (NULL == (stack = H5E__get_my_stack()))
917
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack");
918
0
    } /* end if */
919
0
    else {
920
        /* Only clear the error stack if it's not the default stack */
921
0
        H5E_clear_stack();
922
923
        /* Get the error stack to operate on */
924
0
        if (NULL == (stack = (H5E_stack_t *)H5I_object_verify(stack_id, H5I_ERROR_STACK)))
925
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error stack ID");
926
0
    } /* end else */
927
928
    /* Check arguments */
929
0
    if (NULL == is_paused)
930
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "is_paused parameter is NULL");
931
932
    /* Check if the stack is paused */
933
0
    *is_paused = (stack->paused > 0);
934
935
0
done:
936
0
    FUNC_LEAVE_API(ret_value)
937
0
} /* end H5Eis_paused() */
938
939
/*-------------------------------------------------------------------------
940
 * Function:    H5Epause_stack
941
 *
942
 * Purpose:     Pause pushing errors on an error stack
943
 *
944
 * Return:      Non-negative value on success/Negative on failure
945
 *
946
 *-------------------------------------------------------------------------
947
 */
948
herr_t
949
H5Epause_stack(hid_t stack_id)
950
0
{
951
0
    H5E_stack_t *stack;               /* Error stack */
952
0
    herr_t       ret_value = SUCCEED; /* Return value */
953
954
0
    FUNC_ENTER_API(FAIL)
955
956
    /* Get the correct error stack */
957
0
    if (stack_id == H5E_DEFAULT) {
958
0
        if (NULL == (stack = H5E__get_my_stack()))
959
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack");
960
0
    } /* end if */
961
0
    else
962
        /* Get the error stack to operate on */
963
0
        if (NULL == (stack = (H5E_stack_t *)H5I_object_verify(stack_id, H5I_ERROR_STACK)))
964
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error stack ID");
965
966
    /* Increment pause counter */
967
0
    stack->paused++;
968
969
0
done:
970
0
    FUNC_LEAVE_API(ret_value)
971
0
} /* end H5Epause_stack() */
972
973
/*-------------------------------------------------------------------------
974
 * Function:    H5Eresume_stack
975
 *
976
 * Purpose:     Resume pushing errors on an error stack
977
 *
978
 * Return:      Non-negative value on success/Negative on failure
979
 *
980
 *-------------------------------------------------------------------------
981
 */
982
herr_t
983
H5Eresume_stack(hid_t stack_id)
984
0
{
985
0
    H5E_stack_t *stack;               /* Error stack */
986
0
    herr_t       ret_value = SUCCEED; /* Return value */
987
988
0
    FUNC_ENTER_API(FAIL)
989
990
    /* Get the correct error stack */
991
0
    if (stack_id == H5E_DEFAULT) {
992
0
        if (NULL == (stack = H5E__get_my_stack()))
993
0
            HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack");
994
0
    } /* end if */
995
0
    else
996
        /* Get the error stack to operate on */
997
0
        if (NULL == (stack = (H5E_stack_t *)H5I_object_verify(stack_id, H5I_ERROR_STACK)))
998
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error stack ID");
999
1000
    /* Check for pause/resume imbalance */
1001
0
    if (0 == stack->paused)
1002
0
        HGOTO_ERROR(H5E_ERROR, H5E_BADRANGE, FAIL, "resuming more than paused");
1003
1004
    /* Decrement pause counter */
1005
0
    stack->paused--;
1006
1007
0
done:
1008
    FUNC_LEAVE_API(ret_value)
1009
0
} /* end H5Eresume_stack() */