Coverage Report

Created: 2025-11-24 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Fsuper_cache.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:   H5Fsuper_cache.c
16
 *
17
 * Purpose:   Implement file superblock & driver info metadata cache methods
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5Fmodule.h" /* This source code file is part of the H5F module */
27
#define H5G_FRIEND     /*suppress error about including H5Gpkg    */
28
29
/***********/
30
/* Headers */
31
/***********/
32
#include "H5private.h"   /* Generic Functions     */
33
#include "H5Eprivate.h"  /* Error handling        */
34
#include "H5Fpkg.h"      /* File access       */
35
#include "H5FDprivate.h" /* File drivers        */
36
#include "H5FLprivate.h" /* Free Lists                           */
37
#include "H5Gpkg.h"      /* Groups          */
38
#include "H5MMprivate.h" /* Memory management                    */
39
40
/****************/
41
/* Local Macros */
42
/****************/
43
44
/******************/
45
/* Local Typedefs */
46
/******************/
47
48
/********************/
49
/* Package Typedefs */
50
/********************/
51
52
/********************/
53
/* Local Prototypes */
54
/********************/
55
56
/* Metadata cache (H5AC) callbacks */
57
static herr_t H5F__cache_superblock_get_initial_load_size(void *udata, size_t *image_len);
58
static herr_t H5F__cache_superblock_get_final_load_size(const void *image_ptr, size_t image_len, void *udata,
59
                                                        size_t *actual_len);
60
static htri_t H5F__cache_superblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
61
static void  *H5F__cache_superblock_deserialize(const void *image, size_t len, void *udata, bool *dirty);
62
static herr_t H5F__cache_superblock_image_len(const void *thing, size_t *image_len);
63
static herr_t H5F__cache_superblock_serialize(const H5F_t *f, void *image, size_t len, void *thing);
64
static herr_t H5F__cache_superblock_free_icr(void *thing);
65
66
static herr_t H5F__cache_drvrinfo_get_initial_load_size(void *udata, size_t *image_len);
67
static herr_t H5F__cache_drvrinfo_get_final_load_size(const void *image_ptr, size_t image_len, void *udata,
68
                                                      size_t *actual_len);
69
static void  *H5F__cache_drvrinfo_deserialize(const void *image, size_t len, void *udata, bool *dirty);
70
static herr_t H5F__cache_drvrinfo_image_len(const void *thing, size_t *image_len);
71
static herr_t H5F__cache_drvrinfo_serialize(const H5F_t *f, void *image, size_t len, void *thing);
72
static herr_t H5F__cache_drvrinfo_free_icr(void *thing);
73
74
/* Local encode/decode routines */
75
static herr_t H5F__superblock_prefix_decode(H5F_super_t *sblock, const uint8_t **image_ref, size_t len,
76
                                            const H5F_superblock_cache_ud_t *udata, bool extend_eoa);
77
static herr_t H5F__drvrinfo_prefix_decode(H5O_drvinfo_t *drvinfo, char *drv_name, const uint8_t **image_ref,
78
                                          size_t len, H5F_drvrinfo_cache_ud_t *udata, bool extend_eoa);
79
80
/*********************/
81
/* Package Variables */
82
/*********************/
83
84
/* H5F superblock inherits cache-like properties from H5AC */
85
const H5AC_class_t H5AC_SUPERBLOCK[1] = {{
86
    H5AC_SUPERBLOCK_ID,                          /* Metadata client ID */
87
    "Superblock",                                /* Metadata client name (for debugging) */
88
    H5FD_MEM_SUPER,                              /* File space memory type for client */
89
    H5AC__CLASS_SPECULATIVE_LOAD_FLAG,           /* Client class behavior flags */
90
    H5F__cache_superblock_get_initial_load_size, /* 'get_initial_load_size' callback */
91
    H5F__cache_superblock_get_final_load_size,   /* 'get_final_load_size' callback */
92
    H5F__cache_superblock_verify_chksum,         /* 'verify_chksum' callback */
93
    H5F__cache_superblock_deserialize,           /* 'deserialize' callback */
94
    H5F__cache_superblock_image_len,             /* 'image_len' callback */
95
    NULL,                                        /* 'pre_serialize' callback */
96
    H5F__cache_superblock_serialize,             /* 'serialize' callback */
97
    NULL,                                        /* 'notify' callback */
98
    H5F__cache_superblock_free_icr,              /* 'free_icr' callback */
99
    NULL,                                        /* 'fsf_size' callback */
100
}};
101
102
/* H5F driver info block inherits cache-like properties from H5AC */
103
const H5AC_class_t H5AC_DRVRINFO[1] = {{
104
    H5AC_DRVRINFO_ID,                          /* Metadata client ID */
105
    "Driver info block",                       /* Metadata client name (for debugging) */
106
    H5FD_MEM_SUPER,                            /* File space memory type for client */
107
    H5AC__CLASS_SPECULATIVE_LOAD_FLAG,         /* Client class behavior flags */
108
    H5F__cache_drvrinfo_get_initial_load_size, /* 'get_initial_load_size' callback */
109
    H5F__cache_drvrinfo_get_final_load_size,   /* 'get_final_load_size' callback */
110
    NULL,                                      /* 'verify_chksum' callback */
111
    H5F__cache_drvrinfo_deserialize,           /* 'deserialize' callback */
112
    H5F__cache_drvrinfo_image_len,             /* 'image_len' callback */
113
    NULL,                                      /* 'pre_serialize' callback */
114
    H5F__cache_drvrinfo_serialize,             /* 'serialize' callback */
115
    NULL,                                      /* 'notify' callback */
116
    H5F__cache_drvrinfo_free_icr,              /* 'free_icr' callback */
117
    NULL,                                      /* 'fsf_size' callback */
118
}};
119
120
/*****************************/
121
/* Library Private Variables */
122
/*****************************/
123
124
/* Declare extern the free list to manage the H5F_super_t struct */
125
H5FL_EXTERN(H5F_super_t);
126
127
/*******************/
128
/* Local Variables */
129
/*******************/
130
131
/*-------------------------------------------------------------------------
132
 * Function:    H5F__superblock_prefix_decode
133
 *
134
 * Purpose:     Decode a superblock prefix
135
 *
136
 * Return:      SUCCEED/FAIL
137
 *-------------------------------------------------------------------------
138
 */
139
static herr_t
140
H5F__superblock_prefix_decode(H5F_super_t *sblock, const uint8_t **image_ref, size_t len,
141
                              const H5F_superblock_cache_ud_t *udata, bool extend_eoa)
142
16
{
143
16
    const uint8_t *image     = (const uint8_t *)*image_ref; /* Pointer into raw data buffer */
144
16
    const uint8_t *end       = image + len - 1;             /* Pointer to end of buffer */
145
16
    htri_t         ret_value = SUCCEED;
146
147
16
    FUNC_ENTER_PACKAGE
148
149
16
    assert(sblock);
150
16
    assert(image_ref);
151
16
    assert(image);
152
16
    assert(udata);
153
16
    assert(udata->f);
154
155
    /* Skip over signature (already checked when locating the superblock) */
156
16
    if (H5_IS_BUFFER_OVERFLOW(image, H5F_SIGNATURE_LEN, end))
157
0
        HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding");
158
16
    image += H5F_SIGNATURE_LEN;
159
160
    /* Superblock version */
161
16
    if (H5_IS_BUFFER_OVERFLOW(image, 1, end))
162
0
        HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding");
163
16
    sblock->super_vers = *image++;
164
16
    if (sblock->super_vers > HDF5_SUPERBLOCK_VERSION_LATEST)
165
0
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad superblock version number");
166
167
    /* Size check */
168
16
    if (((size_t)(image - (const uint8_t *)*image_ref)) != H5F_SUPERBLOCK_FIXED_SIZE)
169
0
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad superblock (fixed) size");
170
171
    /* Determine the size of addresses & size of offsets, for computing the
172
     * variable-sized portion of the superblock.
173
     */
174
16
    if (sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) {
175
16
        if (H5_IS_BUFFER_OVERFLOW(image, 6, end))
176
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding");
177
16
        sblock->sizeof_addr = image[4];
178
16
        sblock->sizeof_size = image[5];
179
16
    }
180
0
    else {
181
0
        if (H5_IS_BUFFER_OVERFLOW(image, 2, end))
182
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding");
183
0
        sblock->sizeof_addr = image[0];
184
0
        sblock->sizeof_size = image[1];
185
0
    }
186
187
16
    if (sblock->sizeof_addr != 2 && sblock->sizeof_addr != 4 && sblock->sizeof_addr != 8 &&
188
0
        sblock->sizeof_addr != 16 && sblock->sizeof_addr != 32)
189
0
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number in an address");
190
16
    if (sblock->sizeof_size != 2 && sblock->sizeof_size != 4 && sblock->sizeof_size != 8 &&
191
0
        sblock->sizeof_size != 16 && sblock->sizeof_size != 32)
192
0
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number for object size");
193
194
    /* Check for extending the EOA for the file */
195
16
    if (extend_eoa) {
196
8
        size_t variable_size; /* Variable size of superblock */
197
198
        /* Determine the size of the variable-length part of the superblock */
199
8
        variable_size =
200
8
            (size_t)H5F_SUPERBLOCK_VARLEN_SIZE(sblock->super_vers, sblock->sizeof_addr, sblock->sizeof_size);
201
8
        if (variable_size == 0)
202
0
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "variable size can't be zero");
203
204
        /* Make certain we can read the variable-sized portion of the superblock */
205
8
        if (H5F__set_eoa(udata->f, H5FD_MEM_SUPER, (haddr_t)(H5F_SUPERBLOCK_FIXED_SIZE + variable_size)) < 0)
206
0
            HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed");
207
8
    }
208
209
    /* Update the image buffer pointer */
210
16
    *image_ref = image;
211
212
16
done:
213
16
    FUNC_LEAVE_NOAPI(ret_value)
214
16
} /* end H5F__superblock_prefix_decode() */
215
216
/*-------------------------------------------------------------------------
217
 * Function:    H5F__drvrinfo_prefix_decode
218
 *
219
 * Purpose:     Decode a driver info prefix
220
 *
221
 * Return:      SUCCEED/FAIL
222
 *-------------------------------------------------------------------------
223
 */
224
static herr_t
225
H5F__drvrinfo_prefix_decode(H5O_drvinfo_t *drvrinfo, char *drv_name, const uint8_t **image_ref, size_t len,
226
                            H5F_drvrinfo_cache_ud_t *udata, bool extend_eoa)
227
16
{
228
16
    const uint8_t *image = (const uint8_t *)*image_ref; /* Pointer into raw data buffer */
229
16
    const uint8_t *end   = image + len - 1;             /* Pointer to end of buffer */
230
16
    unsigned       drv_vers;                            /* Version of driver info block */
231
16
    herr_t         ret_value = SUCCEED;
232
233
16
    FUNC_ENTER_PACKAGE
234
235
16
    assert(drvrinfo);
236
16
    assert(image_ref);
237
16
    assert(image);
238
16
    assert(udata);
239
16
    assert(udata->f);
240
241
    /* Version number */
242
16
    if (H5_IS_BUFFER_OVERFLOW(image, 1, end))
243
0
        HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding");
244
16
    drv_vers = *image++;
245
16
    if (drv_vers != HDF5_DRIVERINFO_VERSION_0)
246
0
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad driver information block version number");
247
248
    /* Reserved bytes */
249
16
    if (H5_IS_BUFFER_OVERFLOW(image, 3, end))
250
0
        HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding");
251
16
    image += 3;
252
253
    /* Driver info size */
254
16
    if (H5_IS_BUFFER_OVERFLOW(image, 4, end))
255
0
        HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding");
256
16
    UINT32DECODE(image, drvrinfo->len);
257
258
    /* Driver name and/or version */
259
16
    if (drv_name) {
260
8
        if (H5_IS_BUFFER_OVERFLOW(image, 8, end))
261
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding");
262
8
        H5MM_memcpy(drv_name, (const char *)image, (size_t)8);
263
8
        drv_name[8] = '\0';
264
8
        image += 8; /* advance past name/version */
265
8
    }
266
267
    /* Extend the EOA if required so that we can read the complete driver info block */
268
16
    if (extend_eoa) {
269
8
        haddr_t eoa;     /* Current EOA for the file */
270
8
        haddr_t min_eoa; /* Minimum EOA needed for reading the driver info */
271
272
        /* Get current EOA... */
273
8
        eoa = H5FD_get_eoa(udata->f->shared->lf, H5FD_MEM_SUPER);
274
8
        if (!H5_addr_defined(eoa))
275
0
            HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "driver get_eoa request failed");
276
277
        /* ... if it is too small, extend it. */
278
8
        min_eoa = udata->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drvrinfo->len;
279
280
        /* If it grew, set it */
281
8
        if (H5_addr_gt(min_eoa, eoa))
282
8
            if (H5FD_set_eoa(udata->f->shared->lf, H5FD_MEM_SUPER, min_eoa) < 0)
283
0
                HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed");
284
8
    }
285
286
    /* Update the image buffer pointer */
287
16
    *image_ref = image;
288
289
16
done:
290
16
    FUNC_LEAVE_NOAPI(ret_value)
291
16
} /* end H5F__drvrinfo_prefix_decode() */
292
293
/*-------------------------------------------------------------------------
294
 * Function:    H5F__cache_superblock_get_initial_load_size
295
 *
296
 * Purpose:     Compute the size of the data structure on disk
297
 *
298
 * Return:      SUCCEED/FAIL
299
 *-------------------------------------------------------------------------
300
 */
301
static herr_t
302
H5F__cache_superblock_get_initial_load_size(void H5_ATTR_UNUSED *_udata, size_t *image_len)
303
8
{
304
8
    FUNC_ENTER_PACKAGE_NOERR
305
306
8
    assert(image_len);
307
308
    /* Set the initial image length size */
309
8
    *image_len = H5F_SUPERBLOCK_SPEC_READ_SIZE;
310
311
8
    FUNC_LEAVE_NOAPI(SUCCEED)
312
8
} /* end H5F__cache_superblock_get_initial_load_size() */
313
314
/*-------------------------------------------------------------------------
315
 * Function:    H5F__cache_superblock_get_final_load_size
316
 *
317
 * Purpose:     Compute the final size of the data structure on disk
318
 *
319
 * Return:      SUCCEED/FAIL
320
 *-------------------------------------------------------------------------
321
 */
322
static herr_t
323
H5F__cache_superblock_get_final_load_size(const void *_image, size_t image_len, void *_udata,
324
                                          size_t *actual_len)
325
8
{
326
8
    const uint8_t             *image = _image;                              /* Pointer into raw data buffer */
327
8
    H5F_superblock_cache_ud_t *udata = (H5F_superblock_cache_ud_t *)_udata; /* User data */
328
8
    H5F_super_t                sblock;                                      /* Temporary file superblock */
329
8
    htri_t                     ret_value = SUCCEED;
330
331
8
    FUNC_ENTER_PACKAGE
332
333
8
    assert(image);
334
8
    assert(udata);
335
8
    assert(actual_len);
336
8
    assert(*actual_len == image_len);
337
8
    assert(image_len >= H5F_SUPERBLOCK_FIXED_SIZE + 6);
338
339
    /* Deserialize the file superblock's prefix */
340
8
    if (H5F__superblock_prefix_decode(&sblock, &image, image_len, udata, true) < 0)
341
0
        HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, FAIL, "can't decode file superblock prefix");
342
343
    /* Save the version to be used in verify_chksum callback */
344
8
    udata->super_vers = sblock.super_vers;
345
346
    /* Set the final size for the cache image */
347
8
    *actual_len = H5F_SUPERBLOCK_FIXED_SIZE + (size_t)H5F_SUPERBLOCK_VARLEN_SIZE(
348
8
                                                  sblock.super_vers, sblock.sizeof_addr, sblock.sizeof_size);
349
350
8
done:
351
8
    FUNC_LEAVE_NOAPI(ret_value)
352
8
} /* end H5F__cache_superblock_get_final_load_size() */
353
354
/*-------------------------------------------------------------------------
355
 * Function:    H5F__cache_superblock_verify_chksum
356
 *
357
 * Purpose:     Verify the computed checksum of the data structure is the
358
 *              same as the stored chksum.
359
 *
360
 * Return:      Success:    true/false
361
 *              Failure:    Negative
362
 *-------------------------------------------------------------------------
363
 */
364
static htri_t
365
H5F__cache_superblock_verify_chksum(const void *_image, size_t len, void *_udata)
366
8
{
367
8
    const uint8_t             *image = _image;                              /* Pointer into raw data buffer */
368
8
    H5F_superblock_cache_ud_t *udata = (H5F_superblock_cache_ud_t *)_udata; /* User data */
369
8
    uint32_t                   stored_chksum;   /* Stored metadata checksum value */
370
8
    uint32_t                   computed_chksum; /* Computed metadata checksum value */
371
8
    htri_t                     ret_value = true;
372
373
8
    FUNC_ENTER_PACKAGE
374
375
8
    assert(image);
376
8
    assert(udata);
377
378
    /* No checksum for version 0 & 1 */
379
8
    if (udata->super_vers >= HDF5_SUPERBLOCK_VERSION_2) {
380
381
        /* Get stored and computed checksums */
382
0
        if (H5F_get_checksums(image, len, &stored_chksum, &computed_chksum) < 0)
383
0
            HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get checksums");
384
385
0
        if (stored_chksum != computed_chksum)
386
0
            ret_value = false;
387
0
    }
388
389
8
done:
390
8
    FUNC_LEAVE_NOAPI(ret_value)
391
8
} /* end H5F__cache_superblock_verify_chksum() */
392
393
/*-------------------------------------------------------------------------
394
 * Function:    H5F__cache_superblock_deserialize
395
 *
396
 * Purpose:     Load an object from the disk
397
 *
398
 * Return:      Success:    Pointer to new object
399
 *              Failure:    NULL
400
 *-------------------------------------------------------------------------
401
 */
402
static void *
403
H5F__cache_superblock_deserialize(const void *_image, size_t len, void *_udata, bool H5_ATTR_UNUSED *dirty)
404
8
{
405
8
    H5F_super_t               *sblock    = NULL;                                /* File's superblock */
406
8
    H5F_superblock_cache_ud_t *udata     = (H5F_superblock_cache_ud_t *)_udata; /* User data */
407
8
    const uint8_t             *image     = _image;          /* Pointer into raw data buffer */
408
8
    const uint8_t             *end       = image + len - 1; /* Pointer to end of buffer */
409
8
    H5F_super_t               *ret_value = NULL;
410
411
8
    FUNC_ENTER_PACKAGE
412
413
8
    assert(image);
414
8
    assert(udata);
415
8
    assert(udata->f);
416
8
    assert(len >= H5F_SUPERBLOCK_FIXED_SIZE + 6);
417
418
    /* Allocate space for the superblock */
419
8
    if (NULL == (sblock = H5FL_CALLOC(H5F_super_t)))
420
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
421
422
    /* Deserialize the file superblock's prefix */
423
8
    if (H5F__superblock_prefix_decode(sblock, &image, len, udata, false) < 0)
424
0
        HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode file superblock prefix");
425
426
    /* Check for older version of superblock format */
427
8
    if (sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) {
428
8
        uint32_t status_flags;  /* File status flags     */
429
8
        unsigned sym_leaf_k;    /* Symbol table leaf node's 'K' value */
430
8
        unsigned snode_btree_k; /* B-tree symbol table internal node 'K' value */
431
8
        unsigned chunk_btree_k; /* B-tree chunk internal node 'K' value */
432
433
        /* Freespace version (hard-wired) */
434
8
        if (H5_IS_BUFFER_OVERFLOW(image, 1, end))
435
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
436
8
        if (HDF5_FREESPACE_VERSION != *image++)
437
0
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad free space version number");
438
439
        /* Root group version number (hard-wired) */
440
8
        if (H5_IS_BUFFER_OVERFLOW(image, 1, end))
441
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
442
8
        if (HDF5_OBJECTDIR_VERSION != *image++)
443
0
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad object directory version number");
444
445
        /* Skip over reserved byte */
446
8
        if (H5_IS_BUFFER_OVERFLOW(image, 1, end))
447
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
448
8
        image++;
449
450
        /* Shared header version number (hard-wired) */
451
8
        if (H5_IS_BUFFER_OVERFLOW(image, 1, end))
452
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
453
8
        if (HDF5_SHAREDHEADER_VERSION != *image++)
454
0
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad shared-header format version number");
455
456
        /* Skip over size of file addresses (already decoded) */
457
8
        if (H5_IS_BUFFER_OVERFLOW(image, 1, end))
458
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
459
8
        image++;
460
8
        udata->f->shared->sizeof_addr = sblock->sizeof_addr; /* Keep a local copy also */
461
462
        /* Skip over size of file sizes (already decoded) */
463
8
        if (H5_IS_BUFFER_OVERFLOW(image, 1, end))
464
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
465
8
        image++;
466
8
        udata->f->shared->sizeof_size = sblock->sizeof_size; /* Keep a local copy also */
467
468
        /* Skip over reserved byte */
469
8
        if (H5_IS_BUFFER_OVERFLOW(image, 1, end))
470
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
471
8
        image++;
472
473
        /* Various B-tree sizes */
474
8
        if (H5_IS_BUFFER_OVERFLOW(image, 2, end))
475
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
476
8
        UINT16DECODE(image, sym_leaf_k);
477
8
        if (sym_leaf_k == 0)
478
0
            HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad symbol table leaf node 1/2 rank");
479
8
        udata->sym_leaf_k = sym_leaf_k; /* Keep a local copy also */
480
481
        /* Need 'get' call to set other array values */
482
8
        if (H5_IS_BUFFER_OVERFLOW(image, 2, end))
483
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
484
8
        UINT16DECODE(image, snode_btree_k);
485
8
        if (snode_btree_k == 0)
486
0
            HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad 1/2 rank for btree internal nodes");
487
8
        udata->btree_k[H5B_SNODE_ID] = snode_btree_k;
488
489
        /* Delay setting the value in the property list until we've checked
490
         * for the indexed storage B-tree internal 'K' value later.
491
         */
492
493
        /* File status flags (not really used yet) */
494
8
        if (H5_IS_BUFFER_OVERFLOW(image, 4, end))
495
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
496
8
        UINT32DECODE(image, status_flags);
497
8
        if (status_flags > 255)
498
0
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad superblock status flags");
499
8
        sblock->status_flags = (uint8_t)status_flags;
500
8
        if (sblock->status_flags & ~H5F_SUPER_ALL_FLAGS)
501
0
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock");
502
503
        /* If the superblock version # is greater than 0, read in the indexed
504
         * storage B-tree internal 'K' value
505
         */
506
8
        if (sblock->super_vers > HDF5_SUPERBLOCK_VERSION_DEF) {
507
0
            if (H5_IS_BUFFER_OVERFLOW(image, 2, end))
508
0
                HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
509
0
            UINT16DECODE(image, chunk_btree_k);
510
511
            /* Reserved bytes are present only in version 1 */
512
0
            if (sblock->super_vers == HDF5_SUPERBLOCK_VERSION_1) {
513
                /* Reserved */
514
0
                if (H5_IS_BUFFER_OVERFLOW(image, 2, end))
515
0
                    HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
516
0
                image += 2;
517
0
            }
518
0
        }
519
8
        else
520
8
            chunk_btree_k = HDF5_BTREE_CHUNK_IK_DEF;
521
8
        udata->btree_k[H5B_CHUNK_ID] = chunk_btree_k;
522
523
        /* Remainder of "variable-sized" portion of superblock */
524
8
        if (H5_IS_BUFFER_OVERFLOW(image, H5F_sizeof_addr(udata->f) * 4, end))
525
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
526
8
        H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->base_addr /*out*/);
527
8
        H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->ext_addr /*out*/);
528
8
        H5F_addr_decode(udata->f, (const uint8_t **)&image, &udata->stored_eof /*out*/);
529
8
        H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->driver_addr /*out*/);
530
531
        /* Allocate space for the root group symbol table entry */
532
8
        if (sblock->root_ent)
533
0
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "root entry should not exist yet");
534
8
        if (NULL == (sblock->root_ent = (H5G_entry_t *)H5MM_calloc(sizeof(H5G_entry_t))))
535
0
            HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL,
536
8
                        "can't allocate space for root group symbol table entry");
537
538
        /* Decode the root group symbol table entry */
539
8
        if (H5G_ent_decode(udata->f, (const uint8_t **)&image, sblock->root_ent, end) < 0)
540
0
            HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode root group symbol table entry");
541
542
        /* Set the root group address to the correct value */
543
8
        sblock->root_addr = sblock->root_ent->header;
544
545
        /* This step is for h5repart tool only. If user wants to change file driver
546
         *  from family to sec2 while using h5repart, set the driver address to
547
         *  undefined to let the library ignore the family driver information saved
548
         *  in the superblock.
549
         */
550
8
        if (udata->ignore_drvrinfo && H5_addr_defined(sblock->driver_addr)) {
551
            /* Eliminate the driver info */
552
0
            sblock->driver_addr     = HADDR_UNDEF;
553
0
            udata->drvrinfo_removed = true;
554
0
        }
555
556
        /* NOTE: Driver info block is decoded separately, later */
557
8
    }
558
0
    else {
559
0
        uint32_t read_chksum; /* Checksum read from file  */
560
561
        /* Skip over size of file addresses (already decoded) */
562
0
        image++;
563
0
        udata->f->shared->sizeof_addr = sblock->sizeof_addr; /* Keep a local copy also */
564
        /* Skip over size of file sizes (already decoded) */
565
0
        image++;
566
0
        udata->f->shared->sizeof_size = sblock->sizeof_size; /* Keep a local copy also */
567
568
        /* Check whether the image pointer is out of bounds */
569
0
        if (H5_IS_BUFFER_OVERFLOW(image, 1, end))
570
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
571
572
        /* File status flags (not really used yet) */
573
0
        sblock->status_flags = *image++;
574
0
        if (sblock->status_flags & ~H5F_SUPER_ALL_FLAGS)
575
0
            HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock");
576
577
        /* Check whether the image pointer will be out of bounds */
578
0
        if (H5_IS_BUFFER_OVERFLOW(image, H5F_SIZEOF_ADDR(udata->f) * 4, end))
579
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
580
581
        /* Base, superblock extension, end of file & root group object header addresses */
582
0
        H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->base_addr /*out*/);
583
0
        H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->ext_addr /*out*/);
584
0
        H5F_addr_decode(udata->f, (const uint8_t **)&image, &udata->stored_eof /*out*/);
585
0
        H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->root_addr /*out*/);
586
587
        /* checksum verification already done in verify_chksum cb */
588
589
        /* Check whether the image pointer will be out of bounds */
590
0
        if (H5_IS_BUFFER_OVERFLOW(image, sizeof(uint32_t), end))
591
0
            HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds");
592
593
        /* Decode checksum */
594
0
        UINT32DECODE(image, read_chksum);
595
596
        /* The Driver Information Block may not appear with the version
597
         * 2 super block.  Thus we set the driver_addr field of the in
598
         * core representation of the super block HADDR_UNDEF to prevent
599
         * any attempt to load the Driver Information Block.
600
         */
601
0
        sblock->driver_addr = HADDR_UNDEF;
602
0
    }
603
604
    /* Size check */
605
8
    if ((size_t)(image - (const uint8_t *)_image) > len)
606
0
        HDONE_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad decoded superblock size");
607
608
8
    ret_value = sblock;
609
610
8
done:
611
    /* Release the [possibly partially initialized] superblock on error */
612
8
    if (!ret_value && sblock)
613
0
        if (H5F__super_free(sblock) < 0)
614
0
            HDONE_ERROR(H5E_FILE, H5E_CANTFREE, NULL, "unable to destroy superblock data");
615
616
8
    FUNC_LEAVE_NOAPI(ret_value)
617
8
} /* end H5F__cache_superblock_deserialize() */
618
619
/*-------------------------------------------------------------------------
620
 * Function:    H5F__cache_superblock_image_len
621
 *
622
 * Purpose:     Compute the size of the data structure on disk
623
 *
624
 * Return:      SUCCEED/FAIL
625
 *-------------------------------------------------------------------------
626
 */
627
static herr_t
628
H5F__cache_superblock_image_len(const void *_thing, size_t *image_len)
629
8
{
630
8
    const H5F_super_t *sblock = (const H5F_super_t *)_thing; /* Pointer to the object */
631
632
8
    FUNC_ENTER_PACKAGE_NOERR
633
634
8
    assert(sblock);
635
8
    assert(sblock->cache_info.type == H5AC_SUPERBLOCK);
636
8
    assert(image_len);
637
638
    /* Set the image length size */
639
8
    *image_len = (size_t)H5F_SUPERBLOCK_SIZE(sblock);
640
641
8
    FUNC_LEAVE_NOAPI(SUCCEED)
642
8
} /* end H5F__cache_superblock_image_len() */
643
644
/*-------------------------------------------------------------------------
645
 * Function:  H5F__cache_superblock_serialize
646
 *
647
 * Purpose:     Flush a dirty object to disk
648
 *
649
 * Return:      SUCCEED/FAIL
650
 *-------------------------------------------------------------------------
651
 */
652
static herr_t
653
H5F__cache_superblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len, void *_thing)
654
8
{
655
8
    H5F_super_t *sblock = (H5F_super_t *)_thing; /* Pointer to the object */
656
8
    uint8_t     *image  = _image;                /* Pointer into raw data buffer */
657
8
    haddr_t      rel_eof;                        /* Relative EOF for file */
658
8
    herr_t       ret_value = SUCCEED;
659
660
8
    FUNC_ENTER_PACKAGE
661
662
8
    assert(f);
663
8
    assert(image);
664
8
    assert(sblock);
665
666
    /* Assert that the superblock is marked as being flushed last (and
667
       collectively in parallel) */
668
    /* (We'll rely on the cache to make sure it actually *is* flushed
669
       last (and collectively in parallel), but this check doesn't hurt) */
670
8
    assert(sblock->cache_info.flush_me_last);
671
672
    /* Encode the common portion of the file superblock for all versions */
673
8
    H5MM_memcpy(image, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN);
674
8
    image += H5F_SIGNATURE_LEN;
675
8
    *image++ = (uint8_t)sblock->super_vers;
676
677
    /* Check for older version of superblock format */
678
8
    if (sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) {
679
8
        *image++ = (uint8_t)HDF5_FREESPACE_VERSION; /* (hard-wired) */
680
8
        *image++ = (uint8_t)HDF5_OBJECTDIR_VERSION; /* (hard-wired) */
681
8
        *image++ = 0;                               /* reserved*/
682
683
8
        *image++ = (uint8_t)HDF5_SHAREDHEADER_VERSION; /* (hard-wired) */
684
8
        *image++ = sblock->sizeof_addr;
685
8
        *image++ = sblock->sizeof_size;
686
8
        *image++ = 0; /* reserved */
687
688
8
        UINT16ENCODE(image, sblock->sym_leaf_k);
689
8
        UINT16ENCODE(image, sblock->btree_k[H5B_SNODE_ID]);
690
8
        UINT32ENCODE(image, (uint32_t)sblock->status_flags);
691
692
        /*
693
         * Versions of the superblock >0 have the indexed storage B-tree
694
         * internal 'K' value stored
695
         */
696
8
        if (sblock->super_vers > HDF5_SUPERBLOCK_VERSION_DEF) {
697
0
            UINT16ENCODE(image, sblock->btree_k[H5B_CHUNK_ID]);
698
0
            *image++ = 0; /*reserved */
699
0
            *image++ = 0; /*reserved */
700
0
        }                 /* end if */
701
702
        /* Encode the base address */
703
8
        H5F_addr_encode(f, &image, sblock->base_addr);
704
705
        /* Encode the address of global free-space index */
706
8
        H5F_addr_encode(f, &image, sblock->ext_addr);
707
708
        /* Encode the end-of-file address. Note that at this point in time,
709
         * the EOF value itself may not be reflective of the file's size, as
710
         * we will eventually truncate the file to match the EOA value. As
711
         * such, use the EOA value in its place, knowing that the current EOF
712
         * value will ultimately match it. */
713
8
        if ((rel_eof = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER)) == HADDR_UNDEF)
714
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed");
715
8
        H5F_addr_encode(f, &image, (rel_eof + sblock->base_addr));
716
717
        /* Encode the driver information block address */
718
8
        H5F_addr_encode(f, &image, sblock->driver_addr);
719
720
        /* Encode the root group object entry, including the cached stab info */
721
8
        if (H5G_ent_encode(f, &image, sblock->root_ent) < 0)
722
0
            HGOTO_ERROR(H5E_FILE, H5E_CANTENCODE, FAIL, "can't encode root group symbol table entry");
723
724
        /* NOTE: Driver info block is handled separately */
725
726
8
    }                         /* end if */
727
0
    else {                    /* sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2 */
728
0
        uint32_t   chksum;    /* Checksum temporary variable      */
729
0
        H5O_loc_t *root_oloc; /* Pointer to root group's object location */
730
731
        /* Size of file addresses & offsets, and status flags */
732
0
        *image++ = sblock->sizeof_addr;
733
0
        *image++ = sblock->sizeof_size;
734
0
        *image++ = sblock->status_flags;
735
736
        /* Encode the base address */
737
0
        H5F_addr_encode(f, &image, sblock->base_addr);
738
739
        /* Encode the address of the superblock extension */
740
0
        H5F_addr_encode(f, &image, sblock->ext_addr);
741
742
        /* At this point in time, the EOF value itself may
743
         * not be reflective of the file's size, since we'll eventually
744
         * truncate it to match the EOA value. As such, use the EOA value
745
         * in its place, knowing that the current EOF value will
746
         * ultimately match it. */
747
0
        if ((rel_eof = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER)) == HADDR_UNDEF)
748
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed");
749
0
        H5F_addr_encode(f, &image, (rel_eof + sblock->base_addr));
750
751
        /* Retrieve information for root group */
752
0
        if (NULL == (root_oloc = H5G_oloc(f->shared->root_grp)))
753
0
            HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to retrieve root group information");
754
755
        /* Encode address of root group's object header */
756
0
        H5F_addr_encode(f, &image, root_oloc->addr);
757
758
        /* Compute superblock checksum */
759
0
        chksum = H5_checksum_metadata(_image, ((size_t)H5F_SUPERBLOCK_SIZE(sblock) - H5F_SIZEOF_CHKSUM), 0);
760
761
        /* Superblock checksum */
762
0
        UINT32ENCODE(image, chksum);
763
764
        /* Sanity check */
765
0
        assert((size_t)(image - (uint8_t *)_image) == (size_t)H5F_SUPERBLOCK_SIZE(sblock));
766
0
    }
767
768
    /* Sanity check */
769
8
    assert((size_t)(image - (uint8_t *)_image) == len);
770
771
8
done:
772
8
    FUNC_LEAVE_NOAPI(ret_value)
773
8
} /* H5F__cache_superblock_serialize() */
774
775
/*-------------------------------------------------------------------------
776
 * Function:  H5F__cache_superblock_free_icr
777
 *
778
 * Purpose:     Destroy/release an "in core representation" of a data
779
 *              structure
780
 *
781
 * Return:      SUCCEED/FAIL
782
 *-------------------------------------------------------------------------
783
 */
784
static herr_t
785
H5F__cache_superblock_free_icr(void *_thing)
786
6
{
787
6
    H5F_super_t *sblock    = (H5F_super_t *)_thing; /* Pointer to the object */
788
6
    herr_t       ret_value = SUCCEED;
789
790
6
    FUNC_ENTER_PACKAGE
791
792
6
    assert(sblock);
793
6
    assert(sblock->cache_info.type == H5AC_SUPERBLOCK);
794
795
    /* Destroy superblock */
796
6
    if (H5F__super_free(sblock) < 0)
797
0
        HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free superblock");
798
799
6
done:
800
6
    FUNC_LEAVE_NOAPI(ret_value)
801
6
} /* H5F__cache_superblock_free_icr() */
802
803
/*-------------------------------------------------------------------------
804
 * Function:    H5F__cache_drvrinfo_get_initial_load_size
805
 *
806
 * Purpose:     Compute the initial size of the data structure on disk.
807
 *
808
 * Return:      SUCCEED/FAIL
809
 *-------------------------------------------------------------------------
810
 */
811
static herr_t
812
H5F__cache_drvrinfo_get_initial_load_size(void H5_ATTR_UNUSED *_udata, size_t *image_len)
813
8
{
814
8
    FUNC_ENTER_PACKAGE_NOERR
815
816
8
    assert(image_len);
817
818
    /* Set the initial image length size */
819
8
    *image_len = H5F_DRVINFOBLOCK_HDR_SIZE; /* Fixed size portion of driver info block */
820
821
8
    FUNC_LEAVE_NOAPI(SUCCEED)
822
8
} /* end H5F__cache_drvrinfo_get_initial_load_size() */
823
824
/*-------------------------------------------------------------------------
825
 * Function:    H5F__cache_drvrinfo_get_final_load_size
826
 *
827
 * Purpose:     Compute the final size of the data structure on disk.
828
 *
829
 * Return:      SUCCEED/FAIL
830
 *-------------------------------------------------------------------------
831
 */
832
static herr_t
833
H5F__cache_drvrinfo_get_final_load_size(const void *_image, size_t image_len, void *_udata,
834
                                        size_t *actual_len)
835
8
{
836
8
    const uint8_t           *image = _image;                            /* Pointer into raw data buffer */
837
8
    H5F_drvrinfo_cache_ud_t *udata = (H5F_drvrinfo_cache_ud_t *)_udata; /* User data */
838
8
    H5O_drvinfo_t            drvrinfo;                                  /* Driver info */
839
8
    herr_t                   ret_value = SUCCEED;
840
841
8
    FUNC_ENTER_PACKAGE
842
843
8
    assert(image);
844
8
    assert(udata);
845
8
    assert(actual_len);
846
8
    assert(*actual_len == image_len);
847
8
    assert(image_len == H5F_DRVINFOBLOCK_HDR_SIZE);
848
849
    /* Deserialize the file driver info's prefix */
850
8
    if (H5F__drvrinfo_prefix_decode(&drvrinfo, NULL, &image, image_len, udata, true) < 0)
851
0
        HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, FAIL, "can't decode file driver info prefix");
852
853
    /* Set the final size for the cache image */
854
8
    *actual_len = H5F_DRVINFOBLOCK_HDR_SIZE + drvrinfo.len;
855
856
8
done:
857
8
    FUNC_LEAVE_NOAPI(ret_value)
858
8
} /* end H5F__cache_drvrinfo_get_final_load_size() */
859
860
/*-------------------------------------------------------------------------
861
 * Function:  H5F__cache_drvrinfo_deserialize
862
 *
863
 * Purpose:     Loads an object from the disk
864
 *
865
 * Return:      Success:    Pointer to a new driver info struct
866
 *              Failure:    NULL
867
 *-------------------------------------------------------------------------
868
 */
869
static void *
870
H5F__cache_drvrinfo_deserialize(const void *_image, size_t len, void *_udata, bool H5_ATTR_UNUSED *dirty)
871
8
{
872
8
    H5O_drvinfo_t           *drvinfo = NULL;                              /* Driver info */
873
8
    H5F_drvrinfo_cache_ud_t *udata   = (H5F_drvrinfo_cache_ud_t *)_udata; /* User data */
874
8
    const uint8_t           *image   = _image;                            /* Pointer into raw data buffer */
875
8
    char                     drv_name[9];                                 /* Name of driver */
876
8
    H5O_drvinfo_t           *ret_value = NULL;
877
878
8
    FUNC_ENTER_PACKAGE
879
880
8
    assert(image);
881
8
    assert(len >= H5F_DRVINFOBLOCK_HDR_SIZE);
882
8
    assert(udata);
883
8
    assert(udata->f);
884
885
    /* Allocate space for the driver info */
886
8
    if (NULL == (drvinfo = (H5O_drvinfo_t *)H5MM_calloc(sizeof(H5O_drvinfo_t))))
887
0
        HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "memory allocation failed for driver info message");
888
889
    /* Deserialize the file driver info's prefix */
890
8
    if (H5F__drvrinfo_prefix_decode(drvinfo, drv_name, &image, len, udata, false) < 0)
891
0
        HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode file driver info prefix");
892
893
    /* Sanity check */
894
8
    assert(len == (H5F_DRVINFOBLOCK_HDR_SIZE + drvinfo->len));
895
896
    /* Validate and decode driver information */
897
8
    if (H5FD_sb_load(udata->f->shared->lf, drv_name, image) < 0)
898
0
        HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "unable to decode driver information");
899
900
    /* Sanity check */
901
8
    assert((size_t)(image - (const uint8_t *)_image) <= len);
902
903
8
    ret_value = drvinfo;
904
905
8
done:
906
    /* Release the [possibly partially initialized] driver info message on error */
907
8
    if (!ret_value && drvinfo)
908
0
        H5MM_xfree(drvinfo);
909
910
8
    FUNC_LEAVE_NOAPI(ret_value)
911
8
} /* end H5F__cache_drvrinfo_deserialize() */
912
913
/*-------------------------------------------------------------------------
914
 * Function:    H5F__cache_drvrinfo_image_len
915
 *
916
 * Purpose:     Compute the size of the data structure on disk
917
 *
918
 * Return:      SUCCEED/FAIL
919
 *-------------------------------------------------------------------------
920
 */
921
static herr_t
922
H5F__cache_drvrinfo_image_len(const void *_thing, size_t *image_len)
923
0
{
924
0
    const H5O_drvinfo_t *drvinfo = (const H5O_drvinfo_t *)_thing; /* Pointer to the object */
925
926
0
    FUNC_ENTER_PACKAGE_NOERR
927
928
0
    assert(drvinfo);
929
0
    assert(drvinfo->cache_info.type == H5AC_DRVRINFO);
930
0
    assert(image_len);
931
932
    /* Set the image length size */
933
0
    *image_len = (size_t)(H5F_DRVINFOBLOCK_HDR_SIZE + /* Fixed-size portion of driver info block */
934
0
                          drvinfo->len);              /* Variable-size portion of driver info block */
935
936
0
    FUNC_LEAVE_NOAPI(SUCCEED)
937
0
} /* end H5F__cache_drvrinfo_image_len() */
938
939
/*-------------------------------------------------------------------------
940
 * Function:  H5F__cache_drvrinfo_serialize
941
 *
942
 * Purpose:     Flush a dirty object to disk
943
 *
944
 * Return:      SUCCEED/FAIL
945
 *-------------------------------------------------------------------------
946
 */
947
static herr_t
948
H5F__cache_drvrinfo_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_NDEBUG_UNUSED len, void *_thing)
949
2
{
950
2
    H5O_drvinfo_t *drvinfo = (H5O_drvinfo_t *)_thing; /* Pointer to the object */
951
2
    uint8_t       *image   = _image;                  /* Pointer into raw data buffer */
952
2
    uint8_t       *dbuf;                              /* Pointer to beginning of driver info */
953
2
    herr_t         ret_value = SUCCEED;
954
955
2
    FUNC_ENTER_PACKAGE
956
957
2
    assert(f);
958
2
    assert(image);
959
2
    assert(drvinfo);
960
2
    assert(drvinfo->cache_info.type == H5AC_DRVRINFO);
961
2
    assert(len == (size_t)(H5F_DRVINFOBLOCK_HDR_SIZE + drvinfo->len));
962
963
    /* Save pointer to beginning of driver info */
964
2
    dbuf = image;
965
966
    /* Encode the driver information block */
967
2
    *image++ = HDF5_DRIVERINFO_VERSION_0; /* Version */
968
2
    *image++ = 0;                         /* reserved */
969
2
    *image++ = 0;                         /* reserved */
970
2
    *image++ = 0;                         /* reserved */
971
972
    /* Driver info size, excluding header */
973
2
    UINT32ENCODE(image, drvinfo->len);
974
975
    /* Encode driver-specific data */
976
2
    if (H5FD_sb_encode(f->shared->lf, (char *)image, dbuf + H5F_DRVINFOBLOCK_HDR_SIZE) < 0)
977
0
        HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information");
978
979
    /* Advance buffer pointer past name & variable-sized portion of driver info */
980
2
    image += 8 + drvinfo->len;
981
982
    /* Sanity check */
983
2
    assert((size_t)(image - (uint8_t *)_image) == len);
984
985
2
done:
986
2
    FUNC_LEAVE_NOAPI(ret_value)
987
2
} /* H5F__cache_drvrinfo_serialize() */
988
989
/*-------------------------------------------------------------------------
990
 * Function:  H5F__cache_drvrinfo_free_icr
991
 *
992
 * Purpose:     Destroy/release an "in core representation" of a data
993
 *              structure
994
 *
995
 * Return:      SUCCEED/FAIL
996
 *-------------------------------------------------------------------------
997
 */
998
static herr_t
999
H5F__cache_drvrinfo_free_icr(void *_thing)
1000
6
{
1001
6
    H5O_drvinfo_t *drvinfo = (H5O_drvinfo_t *)_thing; /* Pointer to the object */
1002
1003
6
    FUNC_ENTER_PACKAGE_NOERR
1004
1005
6
    assert(drvinfo);
1006
6
    assert(drvinfo->cache_info.type == H5AC_DRVRINFO);
1007
1008
    /* Destroy driver info message */
1009
6
    H5MM_xfree(drvinfo);
1010
1011
6
    FUNC_LEAVE_NOAPI(SUCCEED)
1012
6
} /* H5F__cache_drvrinfo_free_icr() */