Coverage Report

Created: 2024-06-18 06:29

/src/hdf5/src/H5Oefl.c
Line
Count
Source (jump to first uncovered line)
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 COPYING 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
#include "H5Omodule.h" /* This source code file is part of the H5O module */
14
15
#include "H5private.h"   /* Generic Functions     */
16
#include "H5Eprivate.h"  /* Error handling        */
17
#include "H5Fprivate.h"  /* File access       */
18
#include "H5HLprivate.h" /* Local Heaps       */
19
#include "H5MMprivate.h" /* Memory management     */
20
#include "H5Opkg.h"      /* Object headers      */
21
22
/* PRIVATE PROTOTYPES */
23
static void  *H5O__efl_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags, size_t p_size,
24
                              const uint8_t *p);
25
static herr_t H5O__efl_encode(H5F_t *f, bool disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p,
26
                              const void *_mesg);
27
static void  *H5O__efl_copy(const void *_mesg, void *_dest);
28
static size_t H5O__efl_size(const H5F_t *f, bool disable_shared, const void *_mesg);
29
static herr_t H5O__efl_reset(void *_mesg);
30
static void  *H5O__efl_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, bool *recompute_size,
31
                                 unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata);
32
static herr_t H5O__efl_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth);
33
34
/* This message derives from H5O message class */
35
const H5O_msg_class_t H5O_MSG_EFL[1] = {{
36
    H5O_EFL_ID,           /*message id number   */
37
    "external file list", /*message name for debugging    */
38
    sizeof(H5O_efl_t),    /*native message size       */
39
    0,                    /* messages are shareable?       */
40
    H5O__efl_decode,      /*decode message    */
41
    H5O__efl_encode,      /*encode message    */
42
    H5O__efl_copy,        /*copy native value   */
43
    H5O__efl_size,        /*size of message on disk */
44
    H5O__efl_reset,       /*reset method          */
45
    NULL,                 /* free method      */
46
    NULL,                 /* file delete method   */
47
    NULL,                 /* link method      */
48
    NULL,                 /*set share method    */
49
    NULL,                 /*can share method    */
50
    NULL,                 /* pre copy native value to file */
51
    H5O__efl_copy_file,   /* copy native value to file    */
52
    NULL,                 /* post copy native value to file    */
53
    NULL,                 /* get creation index   */
54
    NULL,                 /* set creation index   */
55
    H5O__efl_debug        /*debug the message   */
56
}};
57
58
0
#define H5O_EFL_VERSION 1
59
60
/*-------------------------------------------------------------------------
61
 * Function:    H5O__efl_decode
62
 *
63
 * Purpose:     Decode an external file list message and return a pointer to
64
 *              the message (and some other data).
65
 *
66
 *              We allow zero dimension size starting from the 1.8.7 release.
67
 *              The dataset size of external storage can be zero.
68
 *
69
 * Return:      Success:    Pointer to a new message struct
70
 *              Failure:    NULL
71
 *-------------------------------------------------------------------------
72
 */
73
static void *
74
H5O__efl_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
75
                unsigned H5_ATTR_UNUSED *ioflags, size_t p_size, const uint8_t *p)
76
0
{
77
0
    H5O_efl_t     *mesg = NULL;
78
0
    int            version;
79
0
    const uint8_t *p_end = p + p_size - 1; /* pointer to last byte in p */
80
0
    const char    *s     = NULL;
81
0
    H5HL_t        *heap  = NULL;
82
0
    size_t         block_size;       /* Size of the heap block */
83
0
    void          *ret_value = NULL; /* Return value */
84
85
0
    FUNC_ENTER_PACKAGE
86
87
    /* Check args */
88
0
    assert(f);
89
0
    assert(p);
90
91
0
    if (NULL == (mesg = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))))
92
0
        HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "memory allocation failed");
93
94
    /* Version (1 byte) */
95
0
    if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
96
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
97
0
    version = *p++;
98
0
    if (version != H5O_EFL_VERSION)
99
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for external file list message");
100
101
    /* Reserved (3 bytes) */
102
0
    if (H5_IS_BUFFER_OVERFLOW(p, 3, p_end))
103
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
104
0
    p += 3;
105
106
    /* Number of slots (2x 2 bytes) */
107
0
    if (H5_IS_BUFFER_OVERFLOW(p, 2, p_end))
108
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
109
0
    UINT16DECODE(p, mesg->nalloc);
110
0
    if (mesg->nalloc <= 0)
111
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad number of allocated slots when parsing efl msg");
112
113
0
    if (H5_IS_BUFFER_OVERFLOW(p, 2, p_end))
114
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
115
0
    UINT16DECODE(p, mesg->nused);
116
0
    if (mesg->nused > mesg->nalloc)
117
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad number of in-use slots when parsing efl msg");
118
119
    /* Heap address */
120
0
    if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end))
121
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
122
0
    H5F_addr_decode(f, &p, &(mesg->heap_addr));
123
0
    if (H5_addr_defined(mesg->heap_addr) == false)
124
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad local heap address when parsing efl msg");
125
126
    /* Decode the file list */
127
0
    mesg->slot = (H5O_efl_entry_t *)H5MM_calloc(mesg->nalloc * sizeof(H5O_efl_entry_t));
128
0
    if (NULL == mesg->slot)
129
0
        HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "memory allocation failed");
130
131
0
    if (NULL == (heap = H5HL_protect(f, mesg->heap_addr, H5AC__READ_ONLY_FLAG)))
132
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect local heap");
133
134
#ifdef H5O_DEBUG
135
    /* Verify that the name at offset 0 in the local heap is the empty string */
136
    s = (const char *)H5HL_offset_into(heap, 0);
137
    if (s == NULL)
138
        HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "could not obtain pointer into local heap");
139
    if (*s != '\0')
140
        HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "entry at offset 0 in local heap not an empty string");
141
#endif
142
143
    /* Get the size of the heap block */
144
0
    block_size = H5HL_heap_get_size(heap);
145
146
0
    for (size_t u = 0; u < mesg->nused; u++) {
147
148
0
        hsize_t offset = 0;
149
150
        /* Name */
151
0
        if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_size(f), p_end))
152
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
153
0
        H5F_DECODE_LENGTH(f, p, mesg->slot[u].name_offset);
154
155
0
        if ((s = (const char *)H5HL_offset_into(heap, mesg->slot[u].name_offset)) == NULL)
156
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get external file name");
157
0
        if (*s == '\0')
158
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "invalid external file name");
159
0
        mesg->slot[u].name = H5MM_strndup(s, (block_size - mesg->slot[u].name_offset));
160
0
        if (mesg->slot[u].name == NULL)
161
0
            HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "string duplication failed");
162
163
        /* File offset */
164
0
        if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_size(f), p_end))
165
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
166
0
        H5F_DECODE_LENGTH(f, p, offset); /* Decode into an hsize_t to avoid sign warnings */
167
0
        mesg->slot[u].offset = (HDoff_t)offset;
168
169
        /* Size */
170
0
        if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_size(f), p_end))
171
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
172
0
        H5F_DECODE_LENGTH(f, p, mesg->slot[u].size);
173
0
    }
174
175
0
    if (H5HL_unprotect(heap) < 0)
176
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to unprotect local heap");
177
178
    /* Set return value */
179
0
    ret_value = mesg;
180
181
0
done:
182
0
    if (ret_value == NULL) {
183
0
        if (mesg != NULL) {
184
0
            if (mesg->slot != NULL) {
185
0
                for (size_t u = 0; u < mesg->nused; u++)
186
0
                    H5MM_xfree(mesg->slot[u].name);
187
0
                H5MM_xfree(mesg->slot);
188
0
            }
189
0
            H5MM_xfree(mesg);
190
0
        }
191
0
        if (heap != NULL)
192
0
            if (H5HL_unprotect(heap) < 0)
193
0
                HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to unprotect local heap");
194
0
    }
195
196
0
    FUNC_LEAVE_NOAPI(ret_value)
197
0
} /* end H5O__efl_decode() */
198
199
/*-------------------------------------------------------------------------
200
 * Function:  H5O__efl_encode
201
 *
202
 * Purpose: Encodes a message.
203
 *
204
 * Return:  Non-negative on success/Negative on failure
205
 *
206
 *-------------------------------------------------------------------------
207
 */
208
static herr_t
209
H5O__efl_encode(H5F_t *f, bool H5_ATTR_UNUSED disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p,
210
                const void *_mesg)
211
0
{
212
0
    const H5O_efl_t *mesg = (const H5O_efl_t *)_mesg;
213
0
    size_t           u; /* Local index variable */
214
215
0
    FUNC_ENTER_PACKAGE_NOERR
216
217
    /* check args */
218
0
    assert(f);
219
0
    assert(mesg);
220
0
    assert(p);
221
222
    /* Version */
223
0
    *p++ = H5O_EFL_VERSION;
224
225
    /* Reserved */
226
0
    *p++ = 0;
227
0
    *p++ = 0;
228
0
    *p++ = 0;
229
230
    /* Number of slots */
231
0
    assert(mesg->nalloc > 0);
232
0
    UINT16ENCODE(p, mesg->nused); /*yes, twice*/
233
0
    assert(mesg->nused > 0 && mesg->nused <= mesg->nalloc);
234
0
    UINT16ENCODE(p, mesg->nused);
235
236
    /* Heap address */
237
0
    assert(H5_addr_defined(mesg->heap_addr));
238
0
    H5F_addr_encode(f, &p, mesg->heap_addr);
239
240
    /* Encode file list */
241
0
    for (u = 0; u < mesg->nused; u++) {
242
        /*
243
         * The name should have been added to the heap when the dataset was
244
         * created.
245
         */
246
0
        assert(mesg->slot[u].name_offset);
247
0
        H5F_ENCODE_LENGTH(f, p, mesg->slot[u].name_offset);
248
0
        H5F_ENCODE_LENGTH(f, p, (hsize_t)mesg->slot[u].offset);
249
0
        H5F_ENCODE_LENGTH(f, p, mesg->slot[u].size);
250
0
    } /* end for */
251
252
0
    FUNC_LEAVE_NOAPI(SUCCEED)
253
0
} /* end H5O__efl_encode() */
254
255
/*-------------------------------------------------------------------------
256
 * Function:  H5O__efl_copy
257
 *
258
 * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
259
 *    necessary.
260
 *
261
 * Return:  Success:  Ptr to _DEST
262
 *
263
 *    Failure:  NULL
264
 *
265
 *-------------------------------------------------------------------------
266
 */
267
static void *
268
H5O__efl_copy(const void *_mesg, void *_dest)
269
93
{
270
93
    const H5O_efl_t *mesg = (const H5O_efl_t *)_mesg;
271
93
    H5O_efl_t       *dest = (H5O_efl_t *)_dest;
272
93
    size_t           u;                      /* Local index variable */
273
93
    bool             slot_allocated = false; /* Flag to indicate that dynamic allocation has begun */
274
93
    void            *ret_value      = NULL;  /* Return value */
275
276
93
    FUNC_ENTER_PACKAGE
277
278
    /* check args */
279
93
    assert(mesg);
280
281
    /* Allocate destination message, if necessary */
282
93
    if (!dest && NULL == (dest = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))))
283
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't allocate efl message");
284
285
    /* copy */
286
93
    *dest = *mesg;
287
288
    /* Deep copy allocated information */
289
93
    if (dest->nalloc > 0) {
290
0
        if (NULL == (dest->slot = (H5O_efl_entry_t *)H5MM_calloc(dest->nalloc * sizeof(H5O_efl_entry_t))))
291
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't allocate efl message slots");
292
0
        slot_allocated = true;
293
0
        for (u = 0; u < mesg->nused; u++) {
294
0
            dest->slot[u] = mesg->slot[u];
295
0
            if (NULL == (dest->slot[u].name = H5MM_xstrdup(mesg->slot[u].name)))
296
0
                HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't allocate efl message slot name");
297
0
        } /* end for */
298
0
    }     /* end if */
299
300
    /* Set return value */
301
93
    ret_value = dest;
302
303
93
done:
304
93
    if (NULL == ret_value) {
305
0
        if (slot_allocated) {
306
0
            for (u = 0; u < dest->nused; u++)
307
0
                if (dest->slot[u].name != NULL && dest->slot[u].name != mesg->slot[u].name)
308
0
                    dest->slot[u].name = (char *)H5MM_xfree(dest->slot[u].name);
309
0
            dest->slot = (H5O_efl_entry_t *)H5MM_xfree(dest->slot);
310
0
        } /* end if */
311
0
        if (NULL == _dest)
312
0
            dest = (H5O_efl_t *)H5MM_xfree(dest);
313
0
    } /* end if */
314
315
93
    FUNC_LEAVE_NOAPI(ret_value)
316
93
} /* end H5O__efl_copy() */
317
318
/*-------------------------------------------------------------------------
319
 * Function:  H5O__efl_size
320
 *
321
 * Purpose: Returns the size of the raw message in bytes not counting the
322
 *    message type or size fields, but only the data fields.  This
323
 *    function doesn't take into account message alignment. This
324
 *    function doesn't count unused slots.
325
 *
326
 * Return:  Success:  Message data size in bytes.
327
 *
328
 *    Failure:  0
329
 *
330
 *-------------------------------------------------------------------------
331
 */
332
static size_t
333
H5O__efl_size(const H5F_t *f, bool H5_ATTR_UNUSED disable_shared, const void *_mesg)
334
0
{
335
0
    const H5O_efl_t *mesg      = (const H5O_efl_t *)_mesg;
336
0
    size_t           ret_value = 0;
337
338
0
    FUNC_ENTER_PACKAGE_NOERR
339
340
    /* check args */
341
0
    assert(f);
342
0
    assert(mesg);
343
344
0
    ret_value = (size_t)H5F_SIZEOF_ADDR(f) +                /*heap address */
345
0
                2 +                                         /*slots allocated*/
346
0
                2 +                                         /*num slots used*/
347
0
                4 +                                         /*reserved  */
348
0
                mesg->nused * ((size_t)H5F_SIZEOF_SIZE(f) + /*name offset */
349
0
                               (size_t)H5F_SIZEOF_SIZE(f) + /*file offset */
350
0
                               (size_t)H5F_SIZEOF_SIZE(f)); /*file size */
351
352
0
    FUNC_LEAVE_NOAPI(ret_value)
353
0
} /* end H5O__efl_size() */
354
355
/*-------------------------------------------------------------------------
356
 * Function:  H5O__efl_reset
357
 *
358
 * Purpose: Frees internal pointers and resets the message to an
359
 *    initial state.
360
 *
361
 * Return:  Non-negative on success/Negative on failure
362
 *
363
 *-------------------------------------------------------------------------
364
 */
365
static herr_t
366
H5O__efl_reset(void *_mesg)
367
145
{
368
145
    H5O_efl_t *mesg = (H5O_efl_t *)_mesg;
369
145
    size_t     u; /* Local index variable */
370
371
145
    FUNC_ENTER_PACKAGE_NOERR
372
373
    /* check args */
374
145
    assert(mesg);
375
376
    /* reset */
377
145
    if (mesg->slot) {
378
0
        for (u = 0; u < mesg->nused; u++) {
379
0
            mesg->slot[u].name        = (char *)H5MM_xfree(mesg->slot[u].name);
380
0
            mesg->slot[u].name_offset = 0;
381
0
        } /* end for */
382
0
        mesg->slot = (H5O_efl_entry_t *)H5MM_xfree(mesg->slot);
383
0
    } /* end if */
384
145
    mesg->heap_addr = HADDR_UNDEF;
385
145
    mesg->nused = mesg->nalloc = 0;
386
387
145
    FUNC_LEAVE_NOAPI(SUCCEED)
388
145
} /* end H5O__efl_reset() */
389
390
/*-------------------------------------------------------------------------
391
 * Function:  H5O_efl_total_size
392
 *
393
 * Purpose: Query the total size of the external file list by summing
394
 *    the sizes of all of the files.
395
 *
396
 * Return:  Non-negative on success/Negative on failure
397
 *
398
 *-------------------------------------------------------------------------
399
 */
400
herr_t
401
H5O_efl_total_size(const H5O_efl_t *efl, hsize_t *size)
402
0
{
403
0
    hsize_t total_size = 0, tmp;
404
0
    herr_t  ret_value  = SUCCEED; /* Return value */
405
406
0
    FUNC_ENTER_NOAPI(FAIL)
407
408
0
    if (efl->nused > 0 && H5O_EFL_UNLIMITED == efl->slot[efl->nused - 1].size)
409
0
        *size = H5O_EFL_UNLIMITED;
410
0
    else {
411
0
        size_t u; /* Local index variable */
412
413
0
        for (u = 0; u < efl->nused; u++, total_size = tmp) {
414
0
            tmp = total_size + efl->slot[u].size;
415
0
            if (tmp < total_size)
416
0
                HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "total external storage size overflowed");
417
0
        } /* end for */
418
419
        /* Set the size to return */
420
0
        *size = total_size;
421
0
    } /* end else */
422
423
0
done:
424
0
    FUNC_LEAVE_NOAPI(ret_value)
425
0
} /* end H5O_efl_total_size() */
426
427
/*-------------------------------------------------------------------------
428
 * Function:    H5O__efl_copy_file
429
 *
430
 * Purpose:     Copies an efl message from _MESG to _DEST in file
431
 *
432
 * Return:      Success:        Ptr to _DEST
433
 *
434
 *              Failure:        NULL
435
 *
436
 *-------------------------------------------------------------------------
437
 */
438
static void *
439
H5O__efl_copy_file(H5F_t H5_ATTR_UNUSED *file_src, void *mesg_src, H5F_t *file_dst,
440
                   bool H5_ATTR_UNUSED *recompute_size, unsigned H5_ATTR_UNUSED *mesg_flags,
441
                   H5O_copy_t H5_ATTR_UNUSED *cpy_info, void H5_ATTR_UNUSED *_udata)
442
0
{
443
0
    H5O_efl_t *efl_src = (H5O_efl_t *)mesg_src;
444
0
    H5O_efl_t *efl_dst = NULL;
445
0
    H5HL_t    *heap    = NULL; /* Pointer to local heap for EFL file names */
446
0
    size_t     idx, size, name_offset, heap_size;
447
0
    void      *ret_value = NULL; /* Return value */
448
449
0
    FUNC_ENTER_PACKAGE_TAG(H5AC__COPIED_TAG)
450
451
    /* check args */
452
0
    assert(efl_src);
453
0
    assert(file_dst);
454
455
    /* Allocate space for the destination efl */
456
0
    if (NULL == (efl_dst = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))))
457
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
458
459
    /* Copy the "top level" information */
460
0
    H5MM_memcpy(efl_dst, efl_src, sizeof(H5O_efl_t));
461
462
    /* Determine size needed for destination heap */
463
0
    heap_size = H5HL_ALIGN(1); /* "empty" name */
464
0
    for (idx = 0; idx < efl_src->nused; idx++)
465
0
        heap_size += H5HL_ALIGN(strlen(efl_src->slot[idx].name) + 1);
466
467
    /* Create name heap */
468
0
    if (H5HL_create(file_dst, heap_size, &efl_dst->heap_addr /*out*/) < 0)
469
0
        HGOTO_ERROR(H5E_EFL, H5E_CANTINIT, NULL, "can't create heap");
470
471
    /* Pin the heap down in memory */
472
0
    if (NULL == (heap = H5HL_protect(file_dst, efl_dst->heap_addr, H5AC__NO_FLAGS_SET)))
473
0
        HGOTO_ERROR(H5E_EFL, H5E_PROTECT, NULL, "unable to protect EFL file name heap");
474
475
    /* Insert "empty" name first */
476
0
    if (H5HL_insert(file_dst, heap, (size_t)1, "", &name_offset) < 0)
477
0
        HGOTO_ERROR(H5E_EFL, H5E_CANTINSERT, NULL, "can't insert file name into heap");
478
0
    assert(0 == name_offset);
479
480
    /* allocate array of external file entries */
481
0
    if (efl_src->nalloc > 0) {
482
0
        size = efl_src->nalloc * sizeof(H5O_efl_entry_t);
483
0
        if ((efl_dst->slot = (H5O_efl_entry_t *)H5MM_calloc(size)) == NULL)
484
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
485
486
        /* copy content from the source. Need to update later */
487
0
        H5MM_memcpy(efl_dst->slot, efl_src->slot, size);
488
0
    } /* end if */
489
490
    /* copy the name from the source */
491
0
    for (idx = 0; idx < efl_src->nused; idx++) {
492
0
        efl_dst->slot[idx].name = H5MM_xstrdup(efl_src->slot[idx].name);
493
0
        if (H5HL_insert(file_dst, heap, strlen(efl_dst->slot[idx].name) + 1, efl_dst->slot[idx].name,
494
0
                        &(efl_dst->slot[idx].name_offset)) < 0)
495
0
            HGOTO_ERROR(H5E_EFL, H5E_CANTINSERT, NULL, "can't insert file name into heap");
496
0
    }
497
498
    /* Set return value */
499
0
    ret_value = efl_dst;
500
501
0
done:
502
    /* Release resources */
503
0
    if (heap && H5HL_unprotect(heap) < 0)
504
0
        HDONE_ERROR(H5E_EFL, H5E_PROTECT, NULL, "unable to unprotect EFL file name heap");
505
0
    if (!ret_value)
506
0
        if (efl_dst)
507
0
            H5MM_xfree(efl_dst);
508
509
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
510
0
} /* end H5O__efl_copy_file() */
511
512
/*-------------------------------------------------------------------------
513
 * Function:  H5O__efl_debug
514
 *
515
 * Purpose: Prints debugging info for a message.
516
 *
517
 * Return:  Non-negative on success/Negative on failure
518
 *
519
 *-------------------------------------------------------------------------
520
 */
521
static herr_t
522
H5O__efl_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE *stream, int indent, int fwidth)
523
0
{
524
0
    const H5O_efl_t *mesg = (const H5O_efl_t *)_mesg;
525
0
    size_t           u;
526
527
0
    FUNC_ENTER_PACKAGE_NOERR
528
529
    /* check args */
530
0
    assert(f);
531
0
    assert(mesg);
532
0
    assert(stream);
533
0
    assert(indent >= 0);
534
0
    assert(fwidth >= 0);
535
536
0
    fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, "Heap address:", mesg->heap_addr);
537
538
0
    fprintf(stream, "%*s%-*s %zu/%zu\n", indent, "", fwidth, "Slots used/allocated:", mesg->nused,
539
0
            mesg->nalloc);
540
541
0
    for (u = 0; u < mesg->nused; u++) {
542
0
        char buf[64];
543
544
0
        snprintf(buf, sizeof(buf), "File %zu", u);
545
0
        fprintf(stream, "%*s%s:\n", indent, "", buf);
546
547
0
        fprintf(stream, "%*s%-*s \"%s\"\n", indent + 3, "", MAX(fwidth - 3, 0), "Name:", mesg->slot[u].name);
548
549
0
        fprintf(stream, "%*s%-*s %zu\n", indent + 3, "", MAX(fwidth - 3, 0),
550
0
                "Name offset:", mesg->slot[u].name_offset);
551
552
0
        fprintf(stream, "%*s%-*s %" PRIdMAX "\n", indent + 3, "", MAX(fwidth - 3, 0),
553
0
                "Offset of data in file:", (intmax_t)(mesg->slot[u].offset));
554
555
0
        fprintf(stream, "%*s%-*s %" PRIuHSIZE "\n", indent + 3, "", MAX(fwidth - 3, 0),
556
0
                "Bytes reserved for data:", (mesg->slot[u].size));
557
0
    } /* end for */
558
559
0
    FUNC_LEAVE_NOAPI(SUCCEED)
560
0
} /* end H5O__efl_debug() */