Coverage Report

Created: 2026-03-07 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Olayout.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:     Messages related to data layout
15
 */
16
17
#define H5D_FRIEND     /*suppress error about including H5Dpkg       */
18
#include "H5Omodule.h" /* This source code file is part of the H5O module */
19
20
#include "H5private.h"   /* Generic Functions                        */
21
#include "H5Dpkg.h"      /* Dataset functions                        */
22
#include "H5Eprivate.h"  /* Error handling                           */
23
#include "H5FLprivate.h" /* Free Lists                               */
24
#include "H5MMprivate.h" /* Memory management                        */
25
#include "H5Opkg.h"      /* Object headers                           */
26
27
/* Local macros */
28
29
/* PRIVATE PROTOTYPES */
30
static void  *H5O__layout_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags,
31
                                 size_t p_size, const uint8_t *p);
32
static herr_t H5O__layout_encode(H5F_t *f, bool disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p,
33
                                 const void *_mesg);
34
static void  *H5O__layout_copy(const void *_mesg, void *_dest);
35
static size_t H5O__layout_size(const H5F_t *f, bool disable_shared, const void *_mesg);
36
static herr_t H5O__layout_reset(void *_mesg);
37
static herr_t H5O__layout_free(void *_mesg);
38
static herr_t H5O__layout_delete(H5F_t *f, H5O_t *open_oh, void *_mesg);
39
static herr_t H5O__layout_pre_copy_file(H5F_t *file_src, const void *mesg_src, bool *deleted,
40
                                        const H5O_copy_t *cpy_info, void *udata);
41
static void  *H5O__layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, bool *recompute_size,
42
                                    unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata);
43
static herr_t H5O__layout_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth);
44
45
/* This message derives from H5O message class */
46
const H5O_msg_class_t H5O_MSG_LAYOUT[1] = {{
47
    H5O_LAYOUT_ID,             /* message id number                    */
48
    "layout",                  /* message name for debugging           */
49
    sizeof(H5O_layout_t),      /* native message size                  */
50
    0,                         /* messages are shareable?               */
51
    H5O__layout_decode,        /* decode message                       */
52
    H5O__layout_encode,        /* encode message                       */
53
    H5O__layout_copy,          /* copy the native value                */
54
    H5O__layout_size,          /* size of message on disk              */
55
    H5O__layout_reset,         /* reset method                         */
56
    H5O__layout_free,          /* free the struct                      */
57
    H5O__layout_delete,        /* file delete method                   */
58
    NULL,                      /* link method                          */
59
    NULL,                      /* set share method                     */
60
    NULL,                      /* can share method                     */
61
    H5O__layout_pre_copy_file, /* pre copy native value to file        */
62
    H5O__layout_copy_file,     /* copy native value to file            */
63
    NULL,                      /* post copy native value to file       */
64
    NULL,                      /* get creation index                   */
65
    NULL,                      /* set creation index                   */
66
    H5O__layout_debug          /* debug the message                    */
67
}};
68
69
/* Declare a free list to manage the H5O_layout_t struct */
70
H5FL_DEFINE(H5O_layout_t);
71
72
/*-------------------------------------------------------------------------
73
 * Function:    H5O__layout_decode
74
 *
75
 * Purpose:     Decode an data layout message and return a pointer to a
76
 *              new one created with malloc().
77
 *
78
 * Return:      Success:        Pointer to new message in native order
79
 *              Failure:        NULL
80
 *-------------------------------------------------------------------------
81
 */
82
static void *
83
H5O__layout_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
84
                   unsigned H5_ATTR_UNUSED *ioflags, size_t p_size, const uint8_t *p)
85
0
{
86
0
    const uint8_t *p_end     = p + p_size - 1; /* End of the p buffer */
87
0
    H5O_layout_t  *mesg      = NULL;
88
0
    void          *ret_value = NULL;
89
90
0
    FUNC_ENTER_PACKAGE
91
92
0
    assert(f);
93
0
    assert(p);
94
95
0
    if (NULL == (mesg = H5FL_CALLOC(H5O_layout_t)))
96
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "memory allocation failed");
97
0
    mesg->storage.type = H5D_LAYOUT_ERROR;
98
99
0
    if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
100
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
101
0
    mesg->version = *p++;
102
103
0
    if (mesg->version < H5O_LAYOUT_VERSION_1 || mesg->version > H5O_LAYOUT_VERSION_LATEST)
104
0
        HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad version number for layout message");
105
106
0
    if (mesg->version < H5O_LAYOUT_VERSION_3) {
107
0
        unsigned ndims; /* Num dimensions in chunk */
108
109
        /* Dimensionality */
110
0
        if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
111
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
112
0
        ndims = *p++;
113
114
0
        if (!ndims || ndims > H5O_LAYOUT_NDIMS)
115
0
            HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "dimensionality is out of range");
116
117
        /* Layout class */
118
0
        if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
119
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
120
0
        mesg->type = (H5D_layout_t)*p++;
121
122
0
        if (H5D_CONTIGUOUS != mesg->type && H5D_CHUNKED != mesg->type && H5D_COMPACT != mesg->type)
123
0
            HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad layout type for layout message");
124
125
        /* Set the storage type */
126
0
        mesg->storage.type = mesg->type;
127
128
        /* Reserved bytes */
129
0
        if (H5_IS_BUFFER_OVERFLOW(p, 5, p_end))
130
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
131
0
        p += 5;
132
133
        /* Address */
134
0
        if (mesg->type == H5D_CONTIGUOUS) {
135
0
            if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end))
136
0
                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
137
0
            H5F_addr_decode(f, &p, &(mesg->storage.u.contig.addr));
138
139
            /* Set the layout operations */
140
0
            mesg->ops = H5D_LOPS_CONTIG;
141
0
        }
142
0
        else if (mesg->type == H5D_CHUNKED) {
143
0
            if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end))
144
0
                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
145
0
            H5F_addr_decode(f, &p, &(mesg->storage.u.chunk.idx_addr));
146
147
            /* Set the layout operations */
148
0
            mesg->ops = H5D_LOPS_CHUNK;
149
150
            /* Set the chunk operations
151
             * (Only "btree" indexing type currently supported in this version)
152
             */
153
0
            mesg->storage.u.chunk.idx_type = H5D_CHUNK_IDX_BTREE;
154
0
            mesg->storage.u.chunk.ops      = H5D_COPS_BTREE;
155
0
        }
156
0
        else if (mesg->type == H5D_COMPACT) {
157
            /* Set the layout operations */
158
0
            mesg->ops = H5D_LOPS_COMPACT;
159
0
        }
160
0
        else
161
0
            HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "invalid layout type");
162
163
        /* Read the size */
164
0
        if (mesg->type != H5D_CHUNKED) {
165
            /* Don't compute size of contiguous storage here, due to possible
166
             * truncation of the dimension sizes when they were stored in this
167
             * version of the layout message.  Compute the contiguous storage
168
             * size in the dataset code, where we've got the dataspace
169
             * information available also.
170
             */
171
0
            if (H5_IS_BUFFER_OVERFLOW(p, (ndims * 4), p_end))
172
0
                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
173
0
            p += ndims * sizeof(uint32_t); /* Skip over dimension sizes */
174
0
        }
175
0
        else {
176
0
            if (ndims < 2)
177
0
                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad dimensions for chunked storage");
178
0
            mesg->u.chunk.ndims = ndims;
179
180
0
            if (H5_IS_BUFFER_OVERFLOW(p, (ndims * 4), p_end))
181
0
                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
182
0
            for (unsigned u = 0; u < ndims; u++) {
183
184
0
                UINT32DECODE(p, mesg->u.chunk.dim[u]);
185
186
                /* Just in case that something goes very wrong, such as file corruption */
187
0
                if (mesg->u.chunk.dim[u] == 0)
188
0
                    HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
189
0
                                "bad chunk dimension value when parsing layout message - chunk dimension "
190
0
                                "must be positive: mesg->u.chunk.dim[%u] = %" PRIuHSIZE,
191
0
                                u, mesg->u.chunk.dim[u]);
192
0
            }
193
194
            /* Compute chunk size */
195
0
            mesg->u.chunk.size = mesg->u.chunk.dim[0];
196
0
            for (unsigned u = 1; u < ndims; u++)
197
0
                mesg->u.chunk.size *= mesg->u.chunk.dim[u];
198
0
        }
199
200
0
        if (mesg->type == H5D_COMPACT) {
201
0
            if (H5_IS_BUFFER_OVERFLOW(p, 4, p_end))
202
0
                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
203
0
            UINT32DECODE(p, mesg->storage.u.compact.size);
204
205
0
            if (mesg->storage.u.compact.size > 0) {
206
                /* Ensure that size doesn't exceed buffer size, due to possible data corruption */
207
0
                if (H5_IS_BUFFER_OVERFLOW(p, mesg->storage.u.compact.size, p_end))
208
0
                    HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
209
210
0
                if (NULL == (mesg->storage.u.compact.buf = H5MM_malloc(mesg->storage.u.compact.size)))
211
0
                    HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL,
212
0
                                "memory allocation failed for compact data buffer");
213
0
                H5MM_memcpy(mesg->storage.u.compact.buf, p, mesg->storage.u.compact.size);
214
0
                p += mesg->storage.u.compact.size;
215
0
            }
216
0
        }
217
0
    }
218
0
    else {
219
        /* Layout & storage class */
220
0
        if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
221
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
222
0
        mesg->type = mesg->storage.type = (H5D_layout_t)*p++;
223
224
        /* Interpret the rest of the message according to the layout class */
225
0
        switch (mesg->type) {
226
0
            case H5D_COMPACT:
227
                /* Compact data size */
228
0
                if (H5_IS_BUFFER_OVERFLOW(p, 2, p_end))
229
0
                    HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
230
0
                UINT16DECODE(p, mesg->storage.u.compact.size);
231
232
0
                if (mesg->storage.u.compact.size > 0) {
233
                    /* Ensure that size doesn't exceed buffer size, due to possible data corruption */
234
0
                    if (H5_IS_BUFFER_OVERFLOW(p, mesg->storage.u.compact.size, p_end))
235
0
                        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
236
0
                                    "ran off end of input buffer while decoding");
237
238
                    /* Allocate space for compact data */
239
0
                    if (NULL == (mesg->storage.u.compact.buf = H5MM_malloc(mesg->storage.u.compact.size)))
240
0
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL,
241
0
                                    "memory allocation failed for compact data buffer");
242
243
                    /* Compact data */
244
0
                    H5MM_memcpy(mesg->storage.u.compact.buf, p, mesg->storage.u.compact.size);
245
0
                    p += mesg->storage.u.compact.size;
246
0
                }
247
248
                /* Set the layout operations */
249
0
                mesg->ops = H5D_LOPS_COMPACT;
250
0
                break;
251
252
0
            case H5D_CONTIGUOUS:
253
                /* Contiguous storage address */
254
0
                if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end))
255
0
                    HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
256
0
                H5F_addr_decode(f, &p, &(mesg->storage.u.contig.addr));
257
258
                /* Contiguous storage size */
259
0
                if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_size(f), p_end))
260
0
                    HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
261
0
                H5F_DECODE_LENGTH(f, p, mesg->storage.u.contig.size);
262
263
                /* Set the layout operations */
264
0
                mesg->ops = H5D_LOPS_CONTIG;
265
0
                break;
266
267
0
            case H5D_CHUNKED:
268
0
                if (mesg->version < H5O_LAYOUT_VERSION_4) {
269
                    /* Set the chunked layout flags */
270
0
                    mesg->u.chunk.flags = (uint8_t)0;
271
272
                    /* Dimensionality */
273
0
                    if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
274
0
                        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
275
0
                                    "ran off end of input buffer while decoding");
276
0
                    mesg->u.chunk.ndims = *p++;
277
278
0
                    if (mesg->u.chunk.ndims > H5O_LAYOUT_NDIMS)
279
0
                        HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "dimensionality is too large");
280
0
                    if (mesg->u.chunk.ndims < 2)
281
0
                        HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad dimensions for chunked storage");
282
283
                    /* B-tree address */
284
0
                    if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end))
285
0
                        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
286
0
                                    "ran off end of input buffer while decoding");
287
0
                    H5F_addr_decode(f, &p, &(mesg->storage.u.chunk.idx_addr));
288
289
0
                    if (H5_IS_BUFFER_OVERFLOW(p, (mesg->u.chunk.ndims * 4), p_end))
290
0
                        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
291
0
                                    "ran off end of input buffer while decoding");
292
293
                    /* Chunk dimensions */
294
0
                    for (unsigned u = 0; u < mesg->u.chunk.ndims; u++) {
295
296
0
                        UINT32DECODE(p, mesg->u.chunk.dim[u]);
297
298
                        /* Just in case that something goes very wrong, such as file corruption. */
299
0
                        if (mesg->u.chunk.dim[u] == 0)
300
0
                            HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
301
0
                                        "bad chunk dimension value when parsing layout message - chunk "
302
0
                                        "dimension must be positive: mesg->u.chunk.dim[%u] = %" PRIuHSIZE,
303
0
                                        u, mesg->u.chunk.dim[u]);
304
0
                    }
305
306
                    /* Compute chunk size */
307
0
                    mesg->u.chunk.size = mesg->u.chunk.dim[0];
308
0
                    for (unsigned u = 1; u < mesg->u.chunk.ndims; u++)
309
0
                        mesg->u.chunk.size *= mesg->u.chunk.dim[u];
310
311
                    /* Set the chunk operations
312
                     * (Only "btree" indexing type supported with v3 of message format)
313
                     */
314
0
                    mesg->storage.u.chunk.idx_type = H5D_CHUNK_IDX_BTREE;
315
0
                    mesg->storage.u.chunk.ops      = H5D_COPS_BTREE;
316
0
                }
317
0
                else {
318
                    /* Get the chunked layout flags */
319
0
                    if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
320
0
                        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
321
0
                                    "ran off end of input buffer while decoding");
322
0
                    mesg->u.chunk.flags = *p++;
323
324
                    /* Check for valid flags */
325
                    /* (Currently issues an error for all non-zero values,
326
                     *      until features are added for the flags)
327
                     */
328
0
                    if (mesg->u.chunk.flags & ~H5O_LAYOUT_ALL_CHUNK_FLAGS)
329
0
                        HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad flag value for message");
330
331
                    /* Dimensionality */
332
0
                    if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
333
0
                        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
334
0
                                    "ran off end of input buffer while decoding");
335
0
                    mesg->u.chunk.ndims = *p++;
336
337
0
                    if (mesg->u.chunk.ndims > H5O_LAYOUT_NDIMS)
338
0
                        HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "dimensionality is too large");
339
340
                    /* Encoded # of bytes for each chunk dimension */
341
0
                    if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
342
0
                        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
343
0
                                    "ran off end of input buffer while decoding");
344
0
                    mesg->u.chunk.enc_bytes_per_dim = *p++;
345
346
0
                    if (mesg->u.chunk.enc_bytes_per_dim == 0 || mesg->u.chunk.enc_bytes_per_dim > 8)
347
0
                        HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
348
0
                                    "encoded chunk dimension size is too large");
349
350
0
                    if (H5_IS_BUFFER_OVERFLOW(p, (mesg->u.chunk.ndims * mesg->u.chunk.enc_bytes_per_dim),
351
0
                                              p_end))
352
0
                        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
353
0
                                    "ran off end of input buffer while decoding");
354
355
                    /* Chunk dimensions */
356
0
                    for (unsigned u = 0; u < mesg->u.chunk.ndims; u++) {
357
0
                        UINT64DECODE_VAR(p, mesg->u.chunk.dim[u], mesg->u.chunk.enc_bytes_per_dim);
358
359
                        /* Just in case that something goes very wrong, such as file corruption. */
360
0
                        if (mesg->u.chunk.dim[u] == 0)
361
0
                            HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
362
0
                                        "bad chunk dimension value when parsing layout message - chunk "
363
0
                                        "dimension must be positive: mesg->u.chunk.dim[%u] = %" PRIuHSIZE,
364
0
                                        u, mesg->u.chunk.dim[u]);
365
0
                    }
366
367
                    /* Compute chunk size */
368
0
                    mesg->u.chunk.size = mesg->u.chunk.dim[0];
369
0
                    for (unsigned u = 1; u < mesg->u.chunk.ndims; u++)
370
0
                        mesg->u.chunk.size *= mesg->u.chunk.dim[u];
371
372
                    /* Chunk index type */
373
0
                    if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
374
0
                        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
375
0
                                    "ran off end of input buffer while decoding");
376
0
                    mesg->u.chunk.idx_type = (H5D_chunk_index_t)*p++;
377
378
0
                    if (mesg->u.chunk.idx_type >= H5D_CHUNK_IDX_NTYPES)
379
0
                        HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "unknown chunk index type");
380
0
                    mesg->storage.u.chunk.idx_type = mesg->u.chunk.idx_type;
381
382
0
                    switch (mesg->u.chunk.idx_type) {
383
0
                        case H5D_CHUNK_IDX_BTREE:
384
0
                            HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
385
0
                                        "v1 B-tree index type should never be in a v4 layout message");
386
0
                            break;
387
388
0
                        case H5D_CHUNK_IDX_NONE: /* Implicit Index */
389
0
                            mesg->storage.u.chunk.ops = H5D_COPS_NONE;
390
0
                            break;
391
392
0
                        case H5D_CHUNK_IDX_SINGLE: /* Single Chunk Index */
393
0
                            if (mesg->u.chunk.flags & H5O_LAYOUT_CHUNK_SINGLE_INDEX_WITH_FILTER) {
394
0
                                uint64_t nbytes = 0;
395
396
0
                                if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_size(f) + 4, p_end))
397
0
                                    HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
398
0
                                                "ran off end of input buffer while decoding");
399
400
0
                                H5F_DECODE_LENGTH(f, p, nbytes);
401
0
                                H5_CHECKED_ASSIGN(mesg->storage.u.chunk.u.single.nbytes, uint32_t, nbytes,
402
0
                                                  uint64_t);
403
404
0
                                UINT32DECODE(p, mesg->storage.u.chunk.u.single.filter_mask);
405
0
                            }
406
407
                            /* Set the chunk operations */
408
0
                            mesg->storage.u.chunk.ops = H5D_COPS_SINGLE;
409
0
                            break;
410
411
0
                        case H5D_CHUNK_IDX_FARRAY:
412
                            /* Fixed array creation parameters */
413
0
                            if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
414
0
                                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
415
0
                                            "ran off end of input buffer while decoding");
416
0
                            mesg->u.chunk.u.farray.cparam.max_dblk_page_nelmts_bits = *p++;
417
418
0
                            if (0 == mesg->u.chunk.u.farray.cparam.max_dblk_page_nelmts_bits)
419
0
                                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
420
0
                                            "invalid fixed array creation parameter");
421
422
                            /* Set the chunk operations */
423
0
                            mesg->storage.u.chunk.ops = H5D_COPS_FARRAY;
424
0
                            break;
425
426
0
                        case H5D_CHUNK_IDX_EARRAY:
427
                            /* Extensible array creation parameters */
428
0
                            if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
429
0
                                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
430
0
                                            "ran off end of input buffer while decoding");
431
0
                            mesg->u.chunk.u.earray.cparam.max_nelmts_bits = *p++;
432
433
0
                            if (0 == mesg->u.chunk.u.earray.cparam.max_nelmts_bits)
434
0
                                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
435
0
                                            "invalid extensible array creation parameter");
436
437
0
                            if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
438
0
                                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
439
0
                                            "ran off end of input buffer while decoding");
440
0
                            mesg->u.chunk.u.earray.cparam.idx_blk_elmts = *p++;
441
442
0
                            if (0 == mesg->u.chunk.u.earray.cparam.idx_blk_elmts)
443
0
                                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
444
0
                                            "invalid extensible array creation parameter");
445
446
0
                            if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
447
0
                                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
448
0
                                            "ran off end of input buffer while decoding");
449
0
                            mesg->u.chunk.u.earray.cparam.sup_blk_min_data_ptrs = *p++;
450
451
0
                            if (0 == mesg->u.chunk.u.earray.cparam.sup_blk_min_data_ptrs)
452
0
                                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
453
0
                                            "invalid extensible array creation parameter");
454
455
0
                            if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
456
0
                                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
457
0
                                            "ran off end of input buffer while decoding");
458
0
                            mesg->u.chunk.u.earray.cparam.data_blk_min_elmts = *p++;
459
460
0
                            if (0 == mesg->u.chunk.u.earray.cparam.data_blk_min_elmts)
461
0
                                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
462
0
                                            "invalid extensible array creation parameter");
463
464
0
                            if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
465
0
                                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
466
0
                                            "ran off end of input buffer while decoding");
467
0
                            mesg->u.chunk.u.earray.cparam.max_dblk_page_nelmts_bits = *p++;
468
469
0
                            if (0 == mesg->u.chunk.u.earray.cparam.max_dblk_page_nelmts_bits)
470
0
                                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
471
0
                                            "invalid extensible array creation parameter");
472
473
                            /* Set the chunk operations */
474
0
                            mesg->storage.u.chunk.ops = H5D_COPS_EARRAY;
475
0
                            break;
476
477
0
                        case H5D_CHUNK_IDX_BT2: /* v2 B-tree index */
478
0
                            if (H5_IS_BUFFER_OVERFLOW(p, 4, p_end))
479
0
                                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
480
0
                                            "ran off end of input buffer while decoding");
481
0
                            UINT32DECODE(p, mesg->u.chunk.u.btree2.cparam.node_size);
482
483
0
                            if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
484
0
                                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
485
0
                                            "ran off end of input buffer while decoding");
486
0
                            mesg->u.chunk.u.btree2.cparam.split_percent = *p++;
487
488
0
                            if (mesg->u.chunk.u.btree2.cparam.split_percent == 0 ||
489
0
                                mesg->u.chunk.u.btree2.cparam.split_percent > 100)
490
0
                                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
491
0
                                            "bad value for v2 B-tree split percent value - must be > 0 and "
492
0
                                            "<= 100: split percent = %" PRIu8,
493
0
                                            mesg->u.chunk.u.btree2.cparam.split_percent);
494
495
0
                            if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
496
0
                                HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
497
0
                                            "ran off end of input buffer while decoding");
498
0
                            mesg->u.chunk.u.btree2.cparam.merge_percent = *p++;
499
500
0
                            if (mesg->u.chunk.u.btree2.cparam.merge_percent == 0 ||
501
0
                                mesg->u.chunk.u.btree2.cparam.merge_percent > 100)
502
0
                                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL,
503
0
                                            "bad value for v2 B-tree merge percent value - must be > 0 and "
504
0
                                            "<= 100: merge percent = %" PRIu8,
505
0
                                            mesg->u.chunk.u.btree2.cparam.merge_percent);
506
507
                            /* Set the chunk operations */
508
0
                            mesg->storage.u.chunk.ops = H5D_COPS_BT2;
509
0
                            break;
510
511
0
                        case H5D_CHUNK_IDX_NTYPES:
512
0
                        default:
513
0
                            HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "Invalid chunk index type");
514
0
                    }
515
516
                    /* Chunk index address */
517
0
                    if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end))
518
0
                        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL,
519
0
                                    "ran off end of input buffer while decoding");
520
0
                    H5F_addr_decode(f, &p, &(mesg->storage.u.chunk.idx_addr));
521
0
                }
522
523
                /* Set the layout operations */
524
0
                mesg->ops = H5D_LOPS_CHUNK;
525
0
                break;
526
527
0
            case H5D_VIRTUAL:
528
                /* Check version */
529
0
                if (mesg->version < H5O_LAYOUT_VERSION_4)
530
0
                    HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "invalid layout version with virtual layout");
531
532
                /* Heap information */
533
0
                if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end))
534
0
                    HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
535
0
                H5F_addr_decode(f, &p, &(mesg->storage.u.virt.serial_list_hobjid.addr));
536
                /* NOTE: virtual mapping global heap entry address could be undefined */
537
538
0
                if (H5_IS_BUFFER_OVERFLOW(p, 4, p_end))
539
0
                    HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
540
0
                UINT32DECODE(p, mesg->storage.u.virt.serial_list_hobjid.idx);
541
542
                /* Initialize other fields */
543
0
                mesg->storage.u.virt.list_nused  = 0;
544
0
                mesg->storage.u.virt.list        = NULL;
545
0
                mesg->storage.u.virt.list_nalloc = 0;
546
0
                mesg->storage.u.virt.view        = H5D_VDS_ERROR;
547
0
                mesg->storage.u.virt.printf_gap  = HSIZE_UNDEF;
548
0
                mesg->storage.u.virt.source_fapl = -1;
549
0
                mesg->storage.u.virt.source_dapl = -1;
550
0
                mesg->storage.u.virt.init        = false;
551
552
                /* Set the layout operations */
553
0
                mesg->ops = H5D_LOPS_VIRTUAL;
554
555
0
                break;
556
557
0
            case H5D_LAYOUT_ERROR:
558
0
            case H5D_NLAYOUTS:
559
0
            default:
560
0
                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "Invalid layout class");
561
0
        }
562
0
    }
563
564
    /* Set return value */
565
0
    ret_value = mesg;
566
567
0
done:
568
0
    if (ret_value == NULL) {
569
0
        if (mesg) {
570
0
            if (mesg->type == H5D_VIRTUAL)
571
0
                if (H5D__virtual_reset_layout(mesg) < 0)
572
0
                    HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, NULL, "unable to reset virtual layout");
573
0
            H5FL_FREE(H5O_layout_t, mesg);
574
0
        }
575
0
    }
576
577
0
    FUNC_LEAVE_NOAPI(ret_value)
578
0
} /* end H5O__layout_decode() */
579
580
/*-------------------------------------------------------------------------
581
 * Function:    H5O__layout_encode
582
 *
583
 * Purpose:     Encodes a message.
584
 *
585
 * Return:      Non-negative on success/Negative on failure
586
 *
587
 * Note:
588
 *      We write out version 3 messages by default now.
589
 *
590
 *-------------------------------------------------------------------------
591
 */
592
static herr_t
593
H5O__layout_encode(H5F_t *f, bool H5_ATTR_UNUSED disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p,
594
                   const void *_mesg)
595
0
{
596
0
    const H5O_layout_t *mesg = (const H5O_layout_t *)_mesg;
597
0
    unsigned            u;
598
0
    herr_t              ret_value = SUCCEED; /* Return value */
599
600
0
    FUNC_ENTER_PACKAGE
601
602
    /* check args */
603
0
    assert(f);
604
0
    assert(mesg);
605
0
    assert(p);
606
607
    /* Message version */
608
0
    *p++ = (uint8_t)((mesg->version < H5O_LAYOUT_VERSION_3) ? H5O_LAYOUT_VERSION_3 : mesg->version);
609
610
    /* Layout class */
611
0
    *p++ = (uint8_t)mesg->type;
612
613
    /* Write out layout class specific information */
614
0
    switch (mesg->type) {
615
0
        case H5D_COMPACT:
616
            /* Size of raw data */
617
0
            UINT16ENCODE(p, mesg->storage.u.compact.size);
618
619
            /* Raw data */
620
0
            if (mesg->storage.u.compact.size > 0) {
621
0
                if (mesg->storage.u.compact.buf)
622
0
                    H5MM_memcpy(p, mesg->storage.u.compact.buf, mesg->storage.u.compact.size);
623
0
                else
624
0
                    memset(p, 0, mesg->storage.u.compact.size);
625
0
                p += mesg->storage.u.compact.size;
626
0
            } /* end if */
627
0
            break;
628
629
0
        case H5D_CONTIGUOUS:
630
            /* Contiguous storage address */
631
0
            H5F_addr_encode(f, &p, mesg->storage.u.contig.addr);
632
633
            /* Contiguous storage size */
634
0
            H5F_ENCODE_LENGTH(f, p, mesg->storage.u.contig.size);
635
0
            break;
636
637
0
        case H5D_CHUNKED:
638
0
            if (mesg->version < H5O_LAYOUT_VERSION_4) {
639
                /* Number of dimensions */
640
0
                assert(mesg->u.chunk.ndims > 0 && mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
641
0
                *p++ = (uint8_t)mesg->u.chunk.ndims;
642
643
                /* B-tree address */
644
0
                H5F_addr_encode(f, &p, mesg->storage.u.chunk.idx_addr);
645
646
                /* Dimension sizes */
647
0
                for (u = 0; u < mesg->u.chunk.ndims; u++)
648
0
                    UINT32ENCODE(p, mesg->u.chunk.dim[u]);
649
0
            } /* end if */
650
0
            else {
651
                /* Chunk feature flags */
652
0
                *p++ = mesg->u.chunk.flags;
653
654
                /* Number of dimensions */
655
0
                assert(mesg->u.chunk.ndims > 0 && mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
656
0
                *p++ = (uint8_t)mesg->u.chunk.ndims;
657
658
                /* Encoded # of bytes for each chunk dimension */
659
0
                assert(mesg->u.chunk.enc_bytes_per_dim > 0 && mesg->u.chunk.enc_bytes_per_dim <= 8);
660
0
                *p++ = (uint8_t)mesg->u.chunk.enc_bytes_per_dim;
661
662
                /* Dimension sizes */
663
0
                for (u = 0; u < mesg->u.chunk.ndims; u++)
664
0
                    UINT64ENCODE_VAR(p, mesg->u.chunk.dim[u], mesg->u.chunk.enc_bytes_per_dim);
665
666
                /* Chunk index type */
667
0
                *p++ = (uint8_t)mesg->u.chunk.idx_type;
668
669
0
                switch (mesg->u.chunk.idx_type) {
670
0
                    case H5D_CHUNK_IDX_BTREE:
671
0
                        HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL,
672
0
                                    "v1 B-tree index type should never be in a v4 layout message");
673
0
                        break;
674
675
0
                    case H5D_CHUNK_IDX_NONE: /* Implicit */
676
0
                        break;
677
678
0
                    case H5D_CHUNK_IDX_SINGLE: /* Single Chunk */
679
                        /* Filter information */
680
0
                        if (mesg->u.chunk.flags & H5O_LAYOUT_CHUNK_SINGLE_INDEX_WITH_FILTER) {
681
0
                            H5F_ENCODE_LENGTH(f, p, mesg->storage.u.chunk.u.single.nbytes);
682
0
                            UINT32ENCODE(p, mesg->storage.u.chunk.u.single.filter_mask);
683
0
                        } /* end if */
684
0
                        break;
685
686
0
                    case H5D_CHUNK_IDX_FARRAY:
687
                        /* Fixed array creation parameters */
688
0
                        *p++ = mesg->u.chunk.u.farray.cparam.max_dblk_page_nelmts_bits;
689
0
                        break;
690
691
0
                    case H5D_CHUNK_IDX_EARRAY:
692
                        /* Extensible array creation parameters */
693
0
                        *p++ = mesg->u.chunk.u.earray.cparam.max_nelmts_bits;
694
0
                        *p++ = mesg->u.chunk.u.earray.cparam.idx_blk_elmts;
695
0
                        *p++ = mesg->u.chunk.u.earray.cparam.sup_blk_min_data_ptrs;
696
0
                        *p++ = mesg->u.chunk.u.earray.cparam.data_blk_min_elmts;
697
0
                        *p++ = mesg->u.chunk.u.earray.cparam.max_dblk_page_nelmts_bits;
698
0
                        break;
699
700
0
                    case H5D_CHUNK_IDX_BT2: /* v2 B-tree index */
701
0
                        UINT32ENCODE(p, mesg->u.chunk.u.btree2.cparam.node_size);
702
0
                        *p++ = mesg->u.chunk.u.btree2.cparam.split_percent;
703
0
                        *p++ = mesg->u.chunk.u.btree2.cparam.merge_percent;
704
0
                        break;
705
706
0
                    case H5D_CHUNK_IDX_NTYPES:
707
0
                    default:
708
0
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "Invalid chunk index type");
709
0
                } /* end switch */
710
711
                /*
712
                 * Implicit index: Address of the chunks
713
                 * Single chunk index: address of the single chunk
714
                 * Other indexes: chunk index address
715
                 */
716
0
                H5F_addr_encode(f, &p, mesg->storage.u.chunk.idx_addr);
717
0
            } /* end else */
718
0
            break;
719
720
0
        case H5D_VIRTUAL:
721
            /* Encode heap ID for VDS info */
722
0
            H5F_addr_encode(f, &p, mesg->storage.u.virt.serial_list_hobjid.addr);
723
0
            UINT32ENCODE(p, mesg->storage.u.virt.serial_list_hobjid.idx);
724
0
            break;
725
726
0
        case H5D_LAYOUT_ERROR:
727
0
        case H5D_NLAYOUTS:
728
0
        default:
729
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "Invalid layout class");
730
0
    } /* end switch */
731
732
0
done:
733
0
    FUNC_LEAVE_NOAPI(ret_value)
734
0
} /* end H5O__layout_encode() */
735
736
/*-------------------------------------------------------------------------
737
 * Function:    H5O__layout_copy
738
 *
739
 * Purpose:     Copies a message from _MESG to _DEST, allocating _DEST if
740
 *              necessary.
741
 *
742
 * Return:      Success:        Ptr to _DEST
743
 *
744
 *              Failure:        NULL
745
 *
746
 *-------------------------------------------------------------------------
747
 */
748
static void *
749
H5O__layout_copy(const void *_mesg, void *_dest)
750
1
{
751
1
    const H5O_layout_t *mesg      = (const H5O_layout_t *)_mesg;
752
1
    H5O_layout_t       *dest      = (H5O_layout_t *)_dest;
753
1
    void               *ret_value = NULL; /* Return value */
754
755
1
    FUNC_ENTER_PACKAGE
756
757
    /* check args */
758
1
    assert(mesg);
759
760
    /* Allocate destination message, if necessary */
761
1
    if (!dest && NULL == (dest = H5FL_MALLOC(H5O_layout_t)))
762
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "layout message allocation failed");
763
764
    /* copy */
765
1
    *dest = *mesg;
766
767
    /* Special actions for each type of layout */
768
1
    switch (mesg->type) {
769
0
        case H5D_COMPACT:
770
            /* Deep copy the buffer for compact datasets also */
771
0
            if (mesg->storage.u.compact.size > 0) {
772
                /* Sanity check */
773
0
                assert(mesg->storage.u.compact.buf);
774
775
                /* Allocate memory for the raw data */
776
0
                if (NULL == (dest->storage.u.compact.buf = H5MM_malloc(dest->storage.u.compact.size)))
777
0
                    HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "unable to allocate memory for compact dataset");
778
779
                /* Copy over the raw data */
780
0
                H5MM_memcpy(dest->storage.u.compact.buf, mesg->storage.u.compact.buf,
781
0
                            dest->storage.u.compact.size);
782
0
            } /* end if */
783
0
            else
784
0
                assert(dest->storage.u.compact.buf == NULL);
785
0
            break;
786
787
1
        case H5D_CONTIGUOUS:
788
            /* Nothing required */
789
1
            break;
790
791
0
        case H5D_CHUNKED:
792
            /* Reset the pointer of the chunked storage index but not the address */
793
0
            if (dest->storage.u.chunk.ops)
794
0
                H5D_chunk_idx_reset(&dest->storage.u.chunk, false);
795
0
            break;
796
797
0
        case H5D_VIRTUAL:
798
0
            if (H5D__virtual_copy_layout(dest) < 0)
799
0
                HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy virtual layout");
800
0
            break;
801
802
0
        case H5D_LAYOUT_ERROR:
803
0
        case H5D_NLAYOUTS:
804
0
        default:
805
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, NULL, "Invalid layout class");
806
1
    } /* end switch */
807
808
    /* Set return value */
809
1
    ret_value = dest;
810
811
1
done:
812
1
    if (ret_value == NULL)
813
0
        if (NULL == _dest)
814
0
            dest = H5FL_FREE(H5O_layout_t, dest);
815
816
1
    FUNC_LEAVE_NOAPI(ret_value)
817
1
} /* end H5O__layout_copy() */
818
819
/*-------------------------------------------------------------------------
820
 * Function:    H5O__layout_size
821
 *
822
 * Purpose:     Returns the size of the raw message in bytes.  If it's
823
 *              compact dataset, the data part is also included.
824
 *              This function doesn't take into account message alignment.
825
 *
826
 * Return:      Success:        Message data size in bytes
827
 *
828
 *              Failure:        0
829
 *
830
 *-------------------------------------------------------------------------
831
 */
832
static size_t
833
H5O__layout_size(const H5F_t *f, bool H5_ATTR_UNUSED disable_shared, const void *_mesg)
834
0
{
835
0
    const H5O_layout_t *mesg      = (const H5O_layout_t *)_mesg;
836
0
    size_t              ret_value = 0; /* Return value */
837
838
0
    FUNC_ENTER_PACKAGE_NOERR
839
840
    /* check args */
841
0
    assert(f);
842
0
    assert(mesg);
843
844
    /* Compute serialized size */
845
    /* (including possibly compact data) */
846
0
    ret_value = H5D__layout_meta_size(f, mesg, true);
847
848
0
    FUNC_LEAVE_NOAPI(ret_value)
849
0
} /* end H5O__layout_size() */
850
851
/*-------------------------------------------------------------------------
852
 * Function:    H5O__layout_reset
853
 *
854
 * Purpose:     Frees resources within a data type message, but doesn't free
855
 *              the message itself.
856
 *
857
 * Return:      Non-negative on success/Negative on failure
858
 *
859
 *-------------------------------------------------------------------------
860
 */
861
static herr_t
862
H5O__layout_reset(void *_mesg)
863
1
{
864
1
    H5O_layout_t *mesg      = (H5O_layout_t *)_mesg;
865
1
    herr_t        ret_value = SUCCEED; /* Return value */
866
867
1
    FUNC_ENTER_PACKAGE
868
869
1
    if (mesg) {
870
        /* Free the compact storage buffer */
871
1
        if (H5D_COMPACT == mesg->type)
872
0
            mesg->storage.u.compact.buf = H5MM_xfree(mesg->storage.u.compact.buf);
873
1
        else if (H5D_VIRTUAL == mesg->type)
874
            /* Free the virtual entry list */
875
0
            if (H5D__virtual_reset_layout(mesg) < 0)
876
0
                HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to reset virtual layout");
877
878
        /* Reset the message */
879
1
        mesg->type    = H5D_CONTIGUOUS;
880
1
        mesg->version = H5O_LAYOUT_VERSION_DEFAULT;
881
1
    } /* end if */
882
883
1
done:
884
1
    FUNC_LEAVE_NOAPI(ret_value)
885
1
} /* end H5O__layout_reset() */
886
887
/*-------------------------------------------------------------------------
888
 * Function:    H5O__layout_free
889
 *
890
 * Purpose:     Free's the message
891
 *
892
 * Return:      Non-negative on success/Negative on failure
893
 *
894
 *-------------------------------------------------------------------------
895
 */
896
static herr_t
897
H5O__layout_free(void *_mesg)
898
0
{
899
0
    H5O_layout_t *mesg = (H5O_layout_t *)_mesg;
900
901
0
    FUNC_ENTER_PACKAGE_NOERR
902
903
0
    assert(mesg);
904
905
    /* Free resources within the message */
906
0
    H5O__layout_reset(mesg);
907
908
0
    (void)H5FL_FREE(H5O_layout_t, mesg);
909
910
0
    FUNC_LEAVE_NOAPI(SUCCEED)
911
0
} /* end H5O__layout_free() */
912
913
/*-------------------------------------------------------------------------
914
 * Function:    H5O__layout_delete
915
 *
916
 * Purpose:     Free file space referenced by message
917
 *
918
 * Return:      Non-negative on success/Negative on failure
919
 *
920
 *-------------------------------------------------------------------------
921
 */
922
static herr_t
923
H5O__layout_delete(H5F_t *f, H5O_t *open_oh, void *_mesg)
924
0
{
925
0
    H5O_layout_t *mesg      = (H5O_layout_t *)_mesg;
926
0
    herr_t        ret_value = SUCCEED; /* Return value */
927
928
0
    FUNC_ENTER_PACKAGE
929
930
    /* check args */
931
0
    assert(f);
932
0
    assert(open_oh);
933
0
    assert(mesg);
934
935
    /* Perform different actions, depending on the type of storage */
936
0
    switch (mesg->type) {
937
0
        case H5D_COMPACT: /* Compact data storage */
938
            /* Nothing required */
939
0
            break;
940
941
0
        case H5D_CONTIGUOUS: /* Contiguous block on disk */
942
            /* Free the file space for the raw data */
943
0
            if (H5D__contig_delete(f, &mesg->storage) < 0)
944
0
                HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free raw data");
945
0
            break;
946
947
0
        case H5D_CHUNKED: /* Chunked blocks on disk */
948
            /* Free the file space for the index & chunk raw data */
949
0
            if (H5D__chunk_delete(f, open_oh, mesg) < 0)
950
0
                HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free raw data");
951
0
            break;
952
953
0
        case H5D_VIRTUAL: /* Virtual dataset */
954
            /* Free the file space virtual dataset */
955
0
            if (H5D__virtual_delete(f, &mesg->storage) < 0)
956
0
                HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free raw data");
957
0
            break;
958
959
0
        case H5D_LAYOUT_ERROR:
960
0
        case H5D_NLAYOUTS:
961
0
        default:
962
0
            HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "not valid storage type");
963
0
    } /* end switch */
964
965
0
done:
966
0
    FUNC_LEAVE_NOAPI(ret_value)
967
0
} /* end H5O__layout_delete() */
968
969
/*-------------------------------------------------------------------------
970
 * Function:    H5O__layout_pre_copy_file
971
 *
972
 * Purpose:     Perform any necessary actions before copying message between
973
 *              files.
974
 *
975
 * Return:      Success:        Non-negative
976
 *              Failure:        Negative
977
 *
978
 *-------------------------------------------------------------------------
979
 */
980
static herr_t
981
H5O__layout_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src, bool H5_ATTR_UNUSED *deleted,
982
                          const H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
983
0
{
984
0
    const H5O_layout_t *layout_src = (const H5O_layout_t *)mesg_src; /* Source layout */
985
0
    herr_t              ret_value  = SUCCEED;                        /* Return value */
986
987
0
    FUNC_ENTER_PACKAGE
988
989
    /* check args */
990
0
    assert(cpy_info);
991
0
    assert(cpy_info->file_dst);
992
993
    /* Check to ensure that the version of the message to be copied does not exceed
994
       the message version allowed by the destination file's high bound */
995
0
    if (layout_src->version > H5O_layout_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)])
996
0
        HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "layout message version out of bounds");
997
998
0
done:
999
0
    FUNC_LEAVE_NOAPI(ret_value)
1000
0
} /* end H5O__layout_pre_copy_file() */
1001
1002
/*-------------------------------------------------------------------------
1003
 * Function:    H5O__layout_copy_file
1004
 *
1005
 * Purpose:     Copies a message from _MESG to _DEST in file
1006
 *
1007
 * Return:      Success:        Ptr to _DEST
1008
 *
1009
 *              Failure:        NULL
1010
 *
1011
 *-------------------------------------------------------------------------
1012
 */
1013
static void *
1014
H5O__layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, bool H5_ATTR_UNUSED *recompute_size,
1015
                      unsigned H5_ATTR_UNUSED *mesg_flags, H5O_copy_t *cpy_info, void *_udata)
1016
0
{
1017
0
    H5D_copy_file_ud_t *udata      = (H5D_copy_file_ud_t *)_udata; /* Dataset copying user data */
1018
0
    H5O_layout_t       *layout_src = (H5O_layout_t *)mesg_src;
1019
0
    H5O_layout_t       *layout_dst = NULL;
1020
0
    void               *ret_value  = NULL; /* Return value */
1021
1022
0
    FUNC_ENTER_PACKAGE
1023
1024
    /* check args */
1025
0
    assert(file_src);
1026
0
    assert(layout_src);
1027
0
    assert(file_dst);
1028
1029
0
    if (layout_src->type == H5D_VIRTUAL)
1030
0
        if (H5D__virtual_load_layout(file_src, layout_src) < 0)
1031
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTLOAD, NULL, "unable to load virtual layout information");
1032
1033
    /* Copy the layout information */
1034
0
    if (NULL == (layout_dst = (H5O_layout_t *)H5O__layout_copy(layout_src, NULL)))
1035
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy layout");
1036
1037
    /* Copy the layout type specific information */
1038
0
    switch (layout_src->type) {
1039
0
        case H5D_COMPACT:
1040
0
            if (layout_src->storage.u.compact.buf) {
1041
                /* copy compact raw data */
1042
0
                if (H5D__compact_copy(file_src, &layout_src->storage.u.compact, file_dst,
1043
0
                                      &layout_dst->storage.u.compact, udata->src_dtype, cpy_info) < 0)
1044
0
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy chunked storage");
1045
0
            } /* end if */
1046
0
            break;
1047
1048
0
        case H5D_CONTIGUOUS: {
1049
0
            hsize_t nelmts;  /* Number of elements in dataset's extent */
1050
0
            size_t  dt_size; /* Size of dataset's datatype in bytes */
1051
            /* Sanity check the dataset's info */
1052
0
            if (H5D__contig_check(file_src, layout_src, udata->src_space_extent, udata->src_dtype) < 0)
1053
0
                HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "invalid layout / dataspace / datatype info");
1054
1055
            /* Compute the size of the contiguous storage for versions of the
1056
             * layout message less than version 3 because versions 1 & 2 would
1057
             * truncate the dimension sizes to 32-bits of information. - QAK 5/26/04
1058
             */
1059
0
            nelmts  = H5S_extent_nelem(udata->src_space_extent);
1060
0
            dt_size = H5T_get_size(udata->src_dtype);
1061
0
            if (layout_src->version < H5O_LAYOUT_VERSION_3)
1062
0
                layout_dst->storage.u.contig.size = nelmts * dt_size;
1063
0
            else
1064
                /* Sanity check layout storage size */
1065
0
                if (layout_dst->storage.u.contig.size != (nelmts * dt_size))
1066
0
                    HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "invalid layout storage size ");
1067
1068
0
            if (H5D__contig_is_space_alloc(&layout_src->storage) ||
1069
0
                (cpy_info->shared_fo &&
1070
0
                 H5D__contig_is_data_cached((const H5D_shared_t *)cpy_info->shared_fo))) {
1071
                /* copy contiguous raw data */
1072
0
                if (H5D__contig_copy(file_src, &layout_src->storage.u.contig, file_dst,
1073
0
                                     &layout_dst->storage.u.contig, udata->src_dtype, cpy_info) < 0)
1074
0
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy contiguous storage");
1075
0
            } /* end if */
1076
0
        } break;
1077
1078
0
        case H5D_CHUNKED:
1079
0
            if (H5D__chunk_is_space_alloc(&layout_src->storage) ||
1080
0
                (cpy_info->shared_fo &&
1081
0
                 H5D__chunk_is_data_cached((const H5D_shared_t *)cpy_info->shared_fo))) {
1082
                /* Create chunked layout */
1083
0
                if (H5D__chunk_copy(file_src, layout_src, file_dst, layout_dst, udata->src_space_extent,
1084
0
                                    udata->src_dtype, udata->common.src_pline, cpy_info) < 0)
1085
0
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy chunked storage");
1086
0
            } /* end if */
1087
0
            break;
1088
1089
0
        case H5D_VIRTUAL:
1090
            /* Copy virtual layout.  Always copy so the memory fields get copied
1091
             * properly. */
1092
0
            if (H5D__virtual_copy(file_dst, layout_dst) < 0)
1093
0
                HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy virtual storage");
1094
0
            break;
1095
1096
0
        case H5D_LAYOUT_ERROR:
1097
0
        case H5D_NLAYOUTS:
1098
0
        default:
1099
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "Invalid layout class");
1100
0
    } /* end switch */
1101
1102
    /* Set return value */
1103
0
    ret_value = layout_dst;
1104
1105
0
done:
1106
0
    if (!ret_value)
1107
0
        if (layout_dst)
1108
0
            layout_dst = H5FL_FREE(H5O_layout_t, layout_dst);
1109
1110
0
    FUNC_LEAVE_NOAPI(ret_value)
1111
0
} /* end H5O__layout_copy_file() */
1112
1113
/*-------------------------------------------------------------------------
1114
 * Function:    H5O__layout_debug
1115
 *
1116
 * Purpose:     Prints debugging info for a message.
1117
 *
1118
 * Return:      Non-negative on success/Negative on failure
1119
 *
1120
 *-------------------------------------------------------------------------
1121
 */
1122
static herr_t
1123
H5O__layout_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE *stream, int indent, int fwidth)
1124
0
{
1125
0
    const H5O_layout_t *mesg = (const H5O_layout_t *)_mesg;
1126
0
    size_t              u;
1127
1128
0
    FUNC_ENTER_PACKAGE_NOERR
1129
1130
    /* check args */
1131
0
    assert(f);
1132
0
    assert(mesg);
1133
0
    assert(stream);
1134
0
    assert(indent >= 0);
1135
0
    assert(fwidth >= 0);
1136
1137
0
    fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Version:", mesg->version);
1138
0
    switch (mesg->type) {
1139
0
        case H5D_CHUNKED:
1140
0
            fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Type:", "Chunked");
1141
1142
            /* Chunk # of dims & size */
1143
0
            fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
1144
0
                    "Number of dimensions:", (unsigned long)(mesg->u.chunk.ndims));
1145
0
            fprintf(stream, "%*s%-*s {", indent, "", fwidth, "Size:");
1146
0
            for (u = 0; u < (size_t)mesg->u.chunk.ndims; u++)
1147
0
                fprintf(stream, "%s%" PRIuHSIZE, u ? ", " : "", mesg->u.chunk.dim[u]);
1148
0
            fprintf(stream, "}\n");
1149
1150
            /* Index information */
1151
0
            switch (mesg->u.chunk.idx_type) {
1152
0
                case H5D_CHUNK_IDX_BTREE:
1153
0
                    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Index Type:", "v1 B-tree");
1154
0
                    break;
1155
1156
0
                case H5D_CHUNK_IDX_NONE:
1157
0
                    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Index Type:", "Implicit");
1158
0
                    break;
1159
1160
0
                case H5D_CHUNK_IDX_SINGLE:
1161
0
                    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Index Type:", "Single Chunk");
1162
0
                    break;
1163
1164
0
                case H5D_CHUNK_IDX_FARRAY:
1165
0
                    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Index Type:", "Fixed Array");
1166
                    /* (Should print the fixed array creation parameters) */
1167
0
                    break;
1168
1169
0
                case H5D_CHUNK_IDX_EARRAY:
1170
0
                    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Index Type:", "Extensible Array");
1171
                    /* (Should print the extensible array creation parameters) */
1172
0
                    break;
1173
1174
0
                case H5D_CHUNK_IDX_BT2:
1175
0
                    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Index Type:", "v2 B-tree");
1176
                    /* (Should print the v2-Btree creation parameters) */
1177
0
                    break;
1178
1179
0
                case H5D_CHUNK_IDX_NTYPES:
1180
0
                default:
1181
0
                    fprintf(stream, "%*s%-*s %s (%u)\n", indent, "", fwidth, "Index Type:", "Unknown",
1182
0
                            (unsigned)mesg->u.chunk.idx_type);
1183
0
                    break;
1184
0
            } /* end switch */
1185
0
            fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth,
1186
0
                    "Index address:", mesg->storage.u.chunk.idx_addr);
1187
0
            break;
1188
1189
0
        case H5D_CONTIGUOUS:
1190
0
            fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Type:", "Contiguous");
1191
0
            fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth,
1192
0
                    "Data address:", mesg->storage.u.contig.addr);
1193
0
            fprintf(stream, "%*s%-*s %" PRIuHSIZE "\n", indent, "", fwidth,
1194
0
                    "Data Size:", mesg->storage.u.contig.size);
1195
0
            break;
1196
1197
0
        case H5D_COMPACT:
1198
0
            fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Type:", "Compact");
1199
0
            fprintf(stream, "%*s%-*s %zu\n", indent, "", fwidth, "Data Size:", mesg->storage.u.compact.size);
1200
0
            break;
1201
1202
0
        case H5D_VIRTUAL:
1203
0
            fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Type:", "Virtual");
1204
0
            fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth,
1205
0
                    "Global heap address:", mesg->storage.u.virt.serial_list_hobjid.addr);
1206
0
            fprintf(stream, "%*s%-*s %zu\n", indent, "", fwidth,
1207
0
                    "Global heap index:", mesg->storage.u.virt.serial_list_hobjid.idx);
1208
0
            for (u = 0; u < mesg->storage.u.virt.list_nused; u++) {
1209
0
                fprintf(stream, "%*sMapping %zu:\n", indent, "", u);
1210
0
                fprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth - 3,
1211
0
                        "Virtual selection:", "<Not yet implemented>");
1212
0
                fprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth - 3,
1213
0
                        "Source file name:", mesg->storage.u.virt.list[u].source_file_name);
1214
0
                fprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth - 3,
1215
0
                        "Source dataset name:", mesg->storage.u.virt.list[u].source_dset_name);
1216
0
                fprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth - 3,
1217
0
                        "Source selection:", "<Not yet implemented>");
1218
0
            } /* end for */
1219
0
            break;
1220
1221
0
        case H5D_LAYOUT_ERROR:
1222
0
        case H5D_NLAYOUTS:
1223
0
        default:
1224
0
            fprintf(stream, "%*s%-*s %s (%u)\n", indent, "", fwidth, "Type:", "Unknown",
1225
0
                    (unsigned)mesg->type);
1226
0
            break;
1227
0
    } /* end switch */
1228
1229
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1230
0
} /* end H5O__layout_debug() */