Coverage Report

Created: 2026-10-28 18:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Ostab.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
 *
15
 * Created:             H5Ostab.c
16
 *
17
 * Purpose:             Symbol table messages
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
#define H5G_FRIEND     /*suppress error about including H5Gpkg   */
23
#include "H5Omodule.h" /* This source code file is part of the H5O module */
24
25
#include "H5private.h"   /* Generic Functions     */
26
#include "H5Eprivate.h"  /* Error handling        */
27
#include "H5FLprivate.h" /* Free lists                           */
28
#include "H5Gpkg.h"      /* Groups        */
29
#include "H5HLprivate.h" /* Local Heaps       */
30
#include "H5Opkg.h"      /* Object headers      */
31
32
/* PRIVATE PROTOTYPES */
33
static void *H5O__stab_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags, size_t p_size,
34
                              const uint8_t *p);
35
static herr_t H5O__stab_encode(H5F_t *f, bool disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p,
36
                               const void *_mesg);
37
static void  *H5O__stab_copy(const void *_mesg, void *_dest);
38
static size_t H5O__stab_size(const H5F_t *f, bool disable_shared, const void *_mesg);
39
static herr_t H5O__stab_free(void *_mesg);
40
static herr_t H5O__stab_delete(H5F_t *f, H5O_t *open_oh, void *_mesg);
41
static void  *H5O__stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, bool *recompute_size,
42
                                  unsigned *mesg_flags, H5O_copy_t *cpy_info, void *_udata);
43
static herr_t H5O__stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc,
44
                                       void *mesg_dst, unsigned *mesg_flags, H5O_copy_t *cpy_info);
45
static herr_t H5O__stab_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth);
46
47
/* This message derives from H5O message class */
48
const H5O_msg_class_t H5O_MSG_STAB[1] = {{
49
    H5O_STAB_ID,              /*message id number             */
50
    "stab",                   /*message name for debugging    */
51
    sizeof(H5O_stab_t),       /*native message size           */
52
    0,                        /* messages are shareable?       */
53
    H5O__stab_decode,         /*decode message                */
54
    H5O__stab_encode,         /*encode message                */
55
    H5O__stab_copy,           /*copy the native value         */
56
    H5O__stab_size,           /*size of symbol table entry    */
57
    NULL,                     /*default reset method          */
58
    H5O__stab_free,           /* free method      */
59
    H5O__stab_delete,         /* file delete method   */
60
    NULL,                     /* link method      */
61
    NULL,                     /*set share method    */
62
    NULL,                     /*can share method    */
63
    NULL,                     /* pre copy native value to file */
64
    H5O__stab_copy_file,      /* copy native value to file    */
65
    H5O__stab_post_copy_file, /* post copy native value to file    */
66
    NULL,                     /* get creation index   */
67
    NULL,                     /* set creation index   */
68
    H5O__stab_debug           /*debug the message             */
69
}};
70
71
/* Declare a free list to manage the H5O_stab_t struct */
72
H5FL_DEFINE_STATIC(H5O_stab_t);
73
74
/*-------------------------------------------------------------------------
75
 * Function:    H5O__stab_decode
76
 *
77
 * Purpose:     Decode a symbol table message and return a pointer to
78
 *              a newly allocated one.
79
 *
80
 * Return:      Success:    Pointer to new message in native order
81
 *              Failure:    NULL
82
 *-------------------------------------------------------------------------
83
 */
84
static void *
85
H5O__stab_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
86
                 unsigned H5_ATTR_UNUSED *ioflags, size_t p_size, const uint8_t *p)
87
11.7k
{
88
11.7k
    H5O_stab_t    *stab      = NULL;
89
11.7k
    const uint8_t *p_end     = p + p_size - 1; /* End of the p buffer */
90
11.7k
    void          *ret_value = NULL;
91
92
11.7k
    FUNC_ENTER_PACKAGE
93
94
11.7k
    assert(f);
95
11.7k
    assert(p);
96
97
11.7k
    if (NULL == (stab = H5FL_CALLOC(H5O_stab_t)))
98
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
99
100
11.7k
    if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end))
101
17
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
102
11.6k
    H5F_addr_decode(f, &p, &(stab->btree_addr));
103
104
11.6k
    if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end))
105
83
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
106
11.6k
    H5F_addr_decode(f, &p, &(stab->heap_addr));
107
108
11.6k
    ret_value = stab;
109
110
11.7k
done:
111
11.7k
    if (!ret_value && stab)
112
100
        H5FL_FREE(H5O_stab_t, stab);
113
114
11.7k
    FUNC_LEAVE_NOAPI(ret_value)
115
11.7k
} /* end H5O__stab_decode() */
116
117
/*-------------------------------------------------------------------------
118
 * Function:    H5O__stab_encode
119
 *
120
 * Purpose:     Encodes a symbol table message.
121
 *
122
 * Return:      Non-negative on success/Negative on failure
123
 *
124
 *-------------------------------------------------------------------------
125
 */
126
static herr_t
127
H5O__stab_encode(H5F_t *f, bool H5_ATTR_UNUSED disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p,
128
                 const void *_mesg)
129
0
{
130
0
    const H5O_stab_t *stab = (const H5O_stab_t *)_mesg;
131
132
0
    FUNC_ENTER_PACKAGE_NOERR
133
134
    /* check args */
135
0
    assert(f);
136
0
    assert(p);
137
0
    assert(stab);
138
139
    /* encode */
140
0
    H5F_addr_encode(f, &p, stab->btree_addr);
141
0
    H5F_addr_encode(f, &p, stab->heap_addr);
142
143
0
    FUNC_LEAVE_NOAPI(SUCCEED)
144
0
} /* end H5O__stab_encode() */
145
146
/*-------------------------------------------------------------------------
147
 * Function:    H5O__stab_copy
148
 *
149
 * Purpose:     Copies a message from _MESG to _DEST, allocating _DEST if
150
 *              necessary.
151
 *
152
 * Return:      Success:        Ptr to _DEST
153
 *
154
 *              Failure:        NULL
155
 *
156
 *-------------------------------------------------------------------------
157
 */
158
static void *
159
H5O__stab_copy(const void *_mesg, void *_dest)
160
356k
{
161
356k
    const H5O_stab_t *stab      = (const H5O_stab_t *)_mesg;
162
356k
    H5O_stab_t       *dest      = (H5O_stab_t *)_dest;
163
356k
    void             *ret_value = NULL; /* Return value */
164
165
356k
    FUNC_ENTER_PACKAGE
166
167
    /* check args */
168
356k
    assert(stab);
169
356k
    if (!dest && NULL == (dest = H5FL_MALLOC(H5O_stab_t)))
170
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
171
172
    /* copy */
173
356k
    *dest = *stab;
174
175
    /* Set return value */
176
356k
    ret_value = dest;
177
178
356k
done:
179
356k
    FUNC_LEAVE_NOAPI(ret_value)
180
356k
} /* end H5O__stab_copy() */
181
182
/*-------------------------------------------------------------------------
183
 * Function:    H5O__stab_size
184
 *
185
 * Purpose:     Returns the size of the raw message in bytes not counting
186
 *              the message type or size fields, but only the data fields.
187
 *              This function doesn't take into account alignment.
188
 *
189
 * Return:      Success:        Message data size in bytes without alignment.
190
 *
191
 *              Failure:        zero
192
 *
193
 *-------------------------------------------------------------------------
194
 */
195
static size_t
196
H5O__stab_size(const H5F_t *f, bool H5_ATTR_UNUSED disable_shared, const void H5_ATTR_UNUSED *_mesg)
197
0
{
198
0
    size_t ret_value = 0; /* Return value */
199
200
0
    FUNC_ENTER_PACKAGE_NOERR
201
202
    /* Set return value */
203
0
    ret_value = (size_t)(2 * H5F_SIZEOF_ADDR(f));
204
205
0
    FUNC_LEAVE_NOAPI(ret_value)
206
0
} /* end H5O__stab_size() */
207
208
/*-------------------------------------------------------------------------
209
 * Function:  H5O__stab_free
210
 *
211
 * Purpose: Frees the message
212
 *
213
 * Return:  Non-negative on success/Negative on failure
214
 *
215
 *-------------------------------------------------------------------------
216
 */
217
static herr_t
218
H5O__stab_free(void *mesg)
219
11.6k
{
220
11.6k
    FUNC_ENTER_PACKAGE_NOERR
221
222
11.6k
    assert(mesg);
223
224
11.6k
    mesg = H5FL_FREE(H5O_stab_t, mesg);
225
226
11.6k
    FUNC_LEAVE_NOAPI(SUCCEED)
227
11.6k
} /* end H5O__stab_free() */
228
229
/*-------------------------------------------------------------------------
230
 * Function:    H5O__stab_delete
231
 *
232
 * Purpose:     Free file space referenced by message
233
 *
234
 * Return:      Non-negative on success/Negative on failure
235
 *
236
 *-------------------------------------------------------------------------
237
 */
238
static herr_t
239
H5O__stab_delete(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, void *mesg)
240
0
{
241
0
    herr_t ret_value = SUCCEED; /* Return value */
242
243
0
    FUNC_ENTER_PACKAGE
244
245
    /* check args */
246
0
    assert(f);
247
0
    assert(mesg);
248
249
    /* Free the file space for the symbol table */
250
0
    if (H5G__stab_delete(f, (const H5O_stab_t *)mesg) < 0)
251
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free symbol table");
252
253
0
done:
254
0
    FUNC_LEAVE_NOAPI(ret_value)
255
0
} /* end H5O__stab_delete() */
256
257
/*-------------------------------------------------------------------------
258
 * Function:    H5O__stab_copy_file
259
 *
260
 * Purpose:     Copies a message from _MESG to _DEST in file
261
 *
262
 * Return:      Success:        Ptr to _DEST
263
 *
264
 *              Failure:        NULL
265
 *
266
 *-------------------------------------------------------------------------
267
 */
268
static void *
269
H5O__stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, bool H5_ATTR_UNUSED *recompute_size,
270
                    unsigned H5_ATTR_UNUSED *mesg_flags, H5O_copy_t H5_ATTR_UNUSED *cpy_info, void *_udata)
271
0
{
272
0
    H5O_stab_t         *stab_src = (H5O_stab_t *)native_src;
273
0
    H5O_stab_t         *stab_dst = NULL;
274
0
    H5G_copy_file_ud_t *udata    = (H5G_copy_file_ud_t *)_udata;
275
0
    size_t              size_hint;        /* Local heap initial size */
276
0
    void               *ret_value = NULL; /* Return value */
277
278
0
    FUNC_ENTER_PACKAGE
279
280
    /* check args */
281
0
    assert(stab_src);
282
0
    assert(file_dst);
283
284
    /* Allocate space for the destination stab */
285
0
    if (NULL == (stab_dst = H5FL_MALLOC(H5O_stab_t)))
286
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
287
288
    /* Get the old local heap's size and use that as the hint for the new heap */
289
0
    if (H5HL_get_size(file_src, stab_src->heap_addr, &size_hint) < 0)
290
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGETSIZE, NULL, "can't query local heap size");
291
292
    /* Set copy metadata tag */
293
0
    H5_BEGIN_TAG(H5AC__COPIED_TAG)
294
295
    /* Create components of symbol table message */
296
0
    if (H5G__stab_create_components(file_dst, stab_dst, size_hint) < 0)
297
0
        HGOTO_ERROR_TAG(H5E_SYM, H5E_CANTINIT, NULL, "can't create symbol table components");
298
299
    /* Reset metadata tag */
300
0
    H5_END_TAG
301
302
    /* Cache stab in udata */
303
0
    udata->cache_type            = H5G_CACHED_STAB;
304
0
    udata->cache.stab.btree_addr = stab_dst->btree_addr;
305
0
    udata->cache.stab.heap_addr  = stab_dst->heap_addr;
306
307
    /* Set return value */
308
0
    ret_value = stab_dst;
309
310
0
done:
311
0
    if (!ret_value)
312
0
        if (stab_dst)
313
0
            stab_dst = H5FL_FREE(H5O_stab_t, stab_dst);
314
315
0
    FUNC_LEAVE_NOAPI(ret_value)
316
0
} /* H5O__stab_copy_file() */
317
318
/*-------------------------------------------------------------------------
319
 * Function:    H5O__stab_post_copy_file
320
 *
321
 * Purpose:     Finish copying a message from between files
322
 *
323
 * Return:      Non-negative on success/Negative on failure
324
 *
325
 *-------------------------------------------------------------------------
326
 */
327
static herr_t
328
H5O__stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst,
329
                         unsigned H5_ATTR_UNUSED *mesg_flags, H5O_copy_t *cpy_info)
330
0
{
331
0
    const H5O_stab_t *stab_src = (const H5O_stab_t *)mesg_src;
332
0
    H5O_stab_t       *stab_dst = (H5O_stab_t *)mesg_dst;
333
0
    H5G_bt_it_cpy_t   udata;               /* B-tree user data */
334
0
    H5HL_t           *heap      = NULL;    /* Pointer to source group's heap */
335
0
    herr_t            ret_value = SUCCEED; /* Return value */
336
337
0
    FUNC_ENTER_PACKAGE
338
339
    /* check args */
340
0
    assert(stab_src);
341
0
    assert(H5_addr_defined(dst_oloc->addr));
342
0
    assert(dst_oloc->file);
343
0
    assert(stab_dst);
344
0
    assert(cpy_info);
345
346
    /* If we are performing a 'shallow hierarchy' copy, get out now */
347
0
    if (cpy_info->max_depth >= 0 && cpy_info->curr_depth >= cpy_info->max_depth)
348
0
        HGOTO_DONE(SUCCEED);
349
350
    /* Get the heap for the copy*/
351
0
    if (NULL == (heap = H5HL_protect(src_oloc->file, stab_src->heap_addr, H5AC__READ_ONLY_FLAG)))
352
0
        HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect local heap");
353
354
    /* Set up B-tree iteration user data */
355
0
    udata.src_oloc       = src_oloc;
356
0
    udata.src_heap       = heap;
357
0
    udata.src_block_size = H5HL_heap_get_size(heap);
358
0
    udata.dst_file       = dst_oloc->file;
359
0
    udata.dst_stab       = stab_dst;
360
0
    udata.cpy_info       = cpy_info;
361
362
    /* Iterate over objects in group, copying them */
363
0
    if ((H5B_iterate(src_oloc->file, H5B_SNODE, stab_src->btree_addr, H5G__node_copy, &udata)) < 0)
364
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed");
365
366
0
done:
367
0
    if (heap && H5HL_unprotect(heap) < 0)
368
0
        HDONE_ERROR(H5E_SYM, H5E_CANTUNPROTECT, FAIL, "unable to unprotect local heap");
369
370
0
    FUNC_LEAVE_NOAPI(ret_value)
371
0
} /* H5O__stab_post_copy_file() */
372
373
/*-------------------------------------------------------------------------
374
 * Function:    H5O__stab_debug
375
 *
376
 * Purpose:     Prints debugging info for a symbol table message.
377
 *
378
 * Return:      Non-negative on success/Negative on failure
379
 *
380
 *-------------------------------------------------------------------------
381
 */
382
static herr_t
383
H5O__stab_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE *stream, int indent, int fwidth)
384
0
{
385
0
    const H5O_stab_t *stab = (const H5O_stab_t *)_mesg;
386
387
0
    FUNC_ENTER_PACKAGE_NOERR
388
389
    /* check args */
390
0
    assert(f);
391
0
    assert(stab);
392
0
    assert(stream);
393
0
    assert(indent >= 0);
394
0
    assert(fwidth >= 0);
395
396
0
    fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, "B-tree address:", stab->btree_addr);
397
398
0
    fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, "Name heap address:", stab->heap_addr);
399
400
0
    FUNC_LEAVE_NOAPI(SUCCEED)
401
0
} /* end H5O__stab_debug() */