Coverage Report

Created: 2026-09-14 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Oattr.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
#define H5A_FRIEND     /*suppress error about including H5Apkg   */
14
#include "H5Omodule.h" /* This source code file is part of the H5O module */
15
#define H5S_FRIEND     /*suppress error about including H5Spkg    */
16
17
#include "H5private.h"   /* Generic Functions     */
18
#include "H5Apkg.h"      /* Attributes        */
19
#include "H5Eprivate.h"  /* Error handling        */
20
#include "H5FLprivate.h" /* Free Lists                               */
21
#include "H5MMprivate.h" /* Memory management     */
22
#include "H5Opkg.h"      /* Object headers      */
23
#include "H5Spkg.h"      /* Dataspaces        */
24
25
/* PRIVATE PROTOTYPES */
26
static herr_t H5O__attr_encode(H5F_t *f, uint8_t *p, const void *mesg);
27
static void *H5O__attr_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags, size_t p_size,
28
                              const uint8_t *p);
29
static void *H5O__attr_copy(const void *_mesg, void *_dest);
30
static size_t H5O__attr_size(const H5F_t *f, const void *_mesg);
31
static herr_t H5O__attr_free(void *mesg);
32
static herr_t H5O__attr_pre_copy_file(H5F_t *file_src, const void *mesg_src, bool *deleted,
33
                                      const H5O_copy_t *cpy_info, void *udata);
34
static void  *H5O__attr_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, void *native_src,
35
                                  H5F_t *file_dst, bool *recompute_size, H5O_copy_t *cpy_info, void *udata);
36
static herr_t H5O__attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc,
37
                                       void *mesg_dst, H5O_copy_t *cpy_info);
38
static herr_t H5O__attr_get_crt_index(const void *_mesg, H5O_msg_crt_idx_t *crt_idx);
39
static herr_t H5O__attr_set_crt_index(void *_mesg, H5O_msg_crt_idx_t crt_idx);
40
static herr_t H5O__attr_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth);
41
42
/* Set up & include shared message "interface" info */
43
0
#define H5O_SHARED_TYPE                H5O_MSG_ATTR
44
#define H5O_SHARED_DECODE              H5O__attr_shared_decode
45
0
#define H5O_SHARED_DECODE_REAL         H5O__attr_decode
46
#define H5O_SHARED_ENCODE              H5O__attr_shared_encode
47
0
#define H5O_SHARED_ENCODE_REAL         H5O__attr_encode
48
#define H5O_SHARED_SIZE                H5O__attr_shared_size
49
0
#define H5O_SHARED_SIZE_REAL           H5O__attr_size
50
#define H5O_SHARED_DELETE              H5O__attr_shared_delete
51
0
#define H5O_SHARED_DELETE_REAL         H5O__attr_delete
52
#define H5O_SHARED_LINK                H5O__attr_shared_link
53
0
#define H5O_SHARED_LINK_REAL           H5O__attr_link
54
#define H5O_SHARED_COPY_FILE           H5O__attr_shared_copy_file
55
0
#define H5O_SHARED_COPY_FILE_REAL      H5O__attr_copy_file
56
#define H5O_SHARED_POST_COPY_FILE      H5O__attr_shared_post_copy_file
57
0
#define H5O_SHARED_POST_COPY_FILE_REAL H5O__attr_post_copy_file
58
#undef H5O_SHARED_POST_COPY_FILE_UPD
59
#define H5O_SHARED_DEBUG      H5O__attr_shared_debug
60
0
#define H5O_SHARED_DEBUG_REAL H5O__attr_debug
61
#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
62
63
/* This message derives from H5O message class */
64
const H5O_msg_class_t H5O_MSG_ATTR[1] = {{
65
    H5O_ATTR_ID,                     /* message id number                */
66
    "attribute",                     /* message name for debugging       */
67
    sizeof(H5A_t),                   /* native message size              */
68
    H5O_SHARE_IS_SHARABLE,           /* messages are shareable?           */
69
    H5O__attr_shared_decode,         /* decode message                   */
70
    H5O__attr_shared_encode,         /* encode message                   */
71
    H5O__attr_copy,                  /* copy the native value            */
72
    H5O__attr_shared_size,           /* size of raw message              */
73
    H5O__attr_reset,                 /* reset method                     */
74
    H5O__attr_free,                  /* free method                      */
75
    H5O__attr_shared_delete,         /* file delete method               */
76
    H5O__attr_shared_link,           /* link method                      */
77
    NULL,                            /* set share method                 */
78
    NULL,                            /* can share method                 */
79
    H5O__attr_pre_copy_file,         /* pre copy native value to file    */
80
    H5O__attr_shared_copy_file,      /* copy native value to file        */
81
    H5O__attr_shared_post_copy_file, /* post copy native value to file   */
82
    H5O__attr_get_crt_index,         /* get creation index               */
83
    H5O__attr_set_crt_index,         /* set creation index               */
84
    H5O__attr_shared_debug           /* debug the message                */
85
}};
86
87
/* Flags for attribute flag encoding */
88
0
#define H5O_ATTR_FLAG_TYPE_SHARED  0x01
89
0
#define H5O_ATTR_FLAG_SPACE_SHARED 0x02
90
0
#define H5O_ATTR_FLAG_ALL          0x03
91
92
/* Declare external the free list for H5S_t's */
93
H5FL_EXTERN(H5S_t);
94
95
/* Declare external the free list for H5S_extent_t's */
96
H5FL_EXTERN(H5S_extent_t);
97
98
/*--------------------------------------------------------------------------
99
 NAME
100
    H5O__attr_decode
101
 PURPOSE
102
    Decode a attribute message and return a pointer to a memory struct
103
        with the decoded information
104
 USAGE
105
    void *H5O__attr_decode(f, mesg_flags, p)
106
        H5F_t    *f;            IN: pointer to the HDF5 file struct
107
        H5O_t    *open_oh;      IN: pointer to the object header
108
        unsigned mesg_flags;    IN: message flags to influence decoding
109
        unsigned *ioflags;      IN/OUT: flags for decoding
110
        size_t   p_size;        IN: size of buffer *p
111
        const uint8_t *p;       IN: the raw information buffer
112
 RETURNS
113
    Pointer to the new message in native order on success, NULL on failure
114
 DESCRIPTION
115
        This function decodes the "raw" disk form of a attribute message
116
        into a struct in memory native format.  The struct is allocated within this
117
        function using malloc() and is returned to the caller.
118
--------------------------------------------------------------------------*/
119
static void *
120
H5O__attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, unsigned *ioflags,
121
                 size_t p_size, const uint8_t *p)
122
0
{
123
0
    H5A_t         *attr   = NULL;
124
0
    const uint8_t *p_end  = p + p_size - 1; /* End of input buffer */
125
0
    size_t         delta  = 0;              /* Amount to move p in next field */
126
0
    H5S_extent_t  *extent = NULL;           /* Extent dimensionality information */
127
0
    size_t         name_len;                /* Attribute name length */
128
0
    size_t         dt_size;                 /* Datatype size */
129
0
    hssize_t       sds_size;                /* Signed Dataspace size */
130
0
    hsize_t        ds_size;                 /* Dataspace size */
131
0
    unsigned       flags     = 0;           /* Attribute flags */
132
0
    H5A_t         *ret_value = NULL;        /* Return value */
133
134
0
    FUNC_ENTER_PACKAGE
135
136
0
    assert(f);
137
0
    assert(p);
138
139
0
    if (NULL == (attr = H5FL_CALLOC(H5A_t)))
140
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
141
0
    if (NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t)))
142
0
        HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared attr structure");
143
144
    /* Version number */
145
0
    if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
146
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
147
0
    attr->shared->version = *p++;
148
0
    if (attr->shared->version < H5O_ATTR_VERSION_1 || attr->shared->version > H5O_ATTR_VERSION_LATEST)
149
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "bad version number for attribute message");
150
151
    /* Get the flags byte if we have a later version of the attribute */
152
0
    if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
153
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
154
0
    if (attr->shared->version >= H5O_ATTR_VERSION_2) {
155
0
        flags = *p++;
156
157
        /* Check for unknown flag */
158
0
        if (flags & (unsigned)~H5O_ATTR_FLAG_ALL)
159
0
            HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "unknown flag for attribute message");
160
0
    }
161
0
    else
162
0
        p++; /* Byte is unused when version < 2 */
163
164
    /* Decode the sizes of the parts of the attribute.  The sizes stored in
165
     * the file are exact but the parts are aligned on 8-byte boundaries.
166
     */
167
0
    if (H5_IS_BUFFER_OVERFLOW(p, 2, p_end))
168
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
169
0
    UINT16DECODE(p, name_len); /* Including null */
170
171
    /* Verify that retrieved name length (including null byte) is valid */
172
0
    if (name_len <= 1)
173
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "decoded name length is invalid");
174
175
0
    if (H5_IS_BUFFER_OVERFLOW(p, 2, p_end))
176
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
177
0
    UINT16DECODE(p, attr->shared->dt_size);
178
0
    if (H5_IS_BUFFER_OVERFLOW(p, 2, p_end))
179
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
180
0
    UINT16DECODE(p, attr->shared->ds_size);
181
182
    /* Decode the character encoding for the name for versions 3 or later,
183
     * as well as some reserved bytes.
184
     */
185
0
    if (attr->shared->version >= H5O_ATTR_VERSION_3) {
186
0
        if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
187
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
188
0
        attr->shared->encoding = (H5T_cset_t)*p++;
189
0
    }
190
191
    /* Decode and store the name
192
     *
193
     * NOTE: If the buffer overflow error message changes, test_corrupted_attnamelen()
194
     *       in titerate.c will fail since it looks for it explicitly.
195
     */
196
0
    if (H5_IS_BUFFER_OVERFLOW(p, name_len, p_end))
197
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
198
199
0
    if (NULL == (attr->shared->name = H5MM_strndup((const char *)p, name_len - 1)))
200
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
201
202
    /* Make an attempt to detect corrupted name or name length - HDFFV-10588 */
203
0
    if (name_len != (strnlen(attr->shared->name, name_len) + 1))
204
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "attribute name has different length than stored length");
205
206
    /* Determine pointer movement and check if it's valid */
207
0
    if (attr->shared->version < H5O_ATTR_VERSION_2)
208
0
        delta = H5O_ALIGN_OLD(name_len);
209
0
    else
210
0
        delta = name_len;
211
0
    if (H5_IS_BUFFER_OVERFLOW(p, delta, p_end))
212
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
213
0
    p += delta;
214
215
    /* Decode the attribute's datatype */
216
0
    if (H5_IS_BUFFER_OVERFLOW(p, attr->shared->dt_size, p_end))
217
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
218
0
    if (NULL == (attr->shared->dt = (H5T_t *)(H5O_MSG_DTYPE->decode)(
219
0
                     f, open_oh, ((flags & H5O_ATTR_FLAG_TYPE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), ioflags,
220
0
                     attr->shared->dt_size, p)))
221
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype");
222
223
    /* Determine pointer movement and check if it's valid */
224
0
    if (attr->shared->version < H5O_ATTR_VERSION_2)
225
0
        delta = H5O_ALIGN_OLD(attr->shared->dt_size);
226
0
    else
227
0
        delta = attr->shared->dt_size;
228
0
    if (H5_IS_BUFFER_OVERFLOW(p, delta, p_end))
229
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
230
0
    p += delta;
231
232
    /* Decode the attribute dataspace.  It can be shared in versions >= 3
233
     * What's actually shared, though, is only the extent.
234
     */
235
0
    if (NULL == (attr->shared->ds = H5FL_CALLOC(H5S_t)))
236
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
237
238
    /* Decode attribute's dataspace extent */
239
0
    if (H5_IS_BUFFER_OVERFLOW(p, attr->shared->ds_size, p_end))
240
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
241
0
    if ((extent = (H5S_extent_t *)(H5O_MSG_SDSPACE->decode)(
242
0
             f, open_oh, ((flags & H5O_ATTR_FLAG_SPACE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), ioflags,
243
0
             attr->shared->ds_size, p)) == NULL)
244
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace");
245
246
    /* Copy the extent information to the dataspace */
247
0
    H5MM_memcpy(&(attr->shared->ds->extent), extent, sizeof(H5S_extent_t));
248
249
    /* Release temporary extent information */
250
0
    extent = H5FL_FREE(H5S_extent_t, extent);
251
252
    /* Default to entire dataspace being selected */
253
0
    if (H5S_select_all(attr->shared->ds, false) < 0)
254
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection");
255
256
    /* Determine pointer movement and check if it's valid */
257
0
    if (attr->shared->version < H5O_ATTR_VERSION_2)
258
0
        delta = H5O_ALIGN_OLD(attr->shared->ds_size);
259
0
    else
260
0
        delta = attr->shared->ds_size;
261
0
    if (H5_IS_BUFFER_OVERFLOW(p, delta, p_end))
262
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
263
0
    p += delta;
264
265
    /* Get the datatype & dataspace sizes */
266
0
    if (0 == (dt_size = H5T_get_size(attr->shared->dt)))
267
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "unable to get datatype size");
268
0
    if ((sds_size = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
269
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "unable to get dataspace size");
270
0
    ds_size = (hsize_t)sds_size;
271
272
    /* Compute the size of the data */
273
0
    H5_CHECKED_ASSIGN(attr->shared->data_size, size_t, ds_size * (hsize_t)dt_size, hsize_t);
274
    /* Check if multiplication has overflown */
275
0
    if ((attr->shared->data_size / dt_size) != ds_size)
276
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_OVERFLOW, NULL, "data size exceeds addressable range");
277
278
    /* Get the data */
279
0
    if (attr->shared->data_size) {
280
        /* Ensure that data size doesn't exceed buffer size, in case of
281
         * it's being corrupted in the file
282
         */
283
0
        if (H5_IS_BUFFER_OVERFLOW(p, attr->shared->data_size, p_end))
284
0
            HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
285
286
0
        if (NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, attr->shared->data_size)))
287
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
288
0
        H5MM_memcpy(attr->shared->data, p, attr->shared->data_size);
289
0
    }
290
291
    /* Increment the reference count for this object header message in cache(compact
292
       storage) or for the object from dense storage. */
293
0
    attr->shared->nrefs++;
294
295
    /* Set return value */
296
0
    ret_value = attr;
297
298
0
done:
299
0
    if (NULL == ret_value) {
300
0
        if (attr) {
301
0
            if (attr->shared)
302
0
                if (H5A__shared_free(attr) < 0)
303
0
                    HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't release attribute info");
304
0
            attr = H5FL_FREE(H5A_t, attr);
305
0
        }
306
0
        if (extent)
307
0
            extent = H5FL_FREE(H5S_extent_t, extent);
308
0
    }
309
310
0
    FUNC_LEAVE_NOAPI(ret_value)
311
0
} /* end H5O__attr_decode() */
312
313
/*--------------------------------------------------------------------------
314
 NAME
315
    H5O__attr_encode
316
 PURPOSE
317
    Encode a simple attribute message
318
 USAGE
319
    herr_t H5O__attr_encode(f, p, mesg)
320
        H5F_t *f;         IN: pointer to the HDF5 file struct
321
        const uint8 *p;         IN: the raw information buffer
322
        const void *mesg;       IN: Pointer to the simple datatype struct
323
 RETURNS
324
    Non-negative on success/Negative on failure
325
 DESCRIPTION
326
        This function encodes the native memory form of the attribute
327
    message in the "raw" disk form.
328
--------------------------------------------------------------------------*/
329
static herr_t
330
H5O__attr_encode(H5F_t *f, uint8_t *p, const void *mesg)
331
0
{
332
0
    const H5A_t *attr = (const H5A_t *)mesg;
333
0
    size_t       name_len;        /* Attribute name length */
334
0
    htri_t       is_type_shared;  /* Flag to indicate that a shared datatype is used for this attribute */
335
0
    htri_t       is_space_shared; /* Flag to indicate that a shared dataspace is used for this attribute */
336
0
    unsigned     flags     = 0;   /* Attribute flags */
337
0
    herr_t       ret_value = SUCCEED; /* Return value */
338
339
0
    FUNC_ENTER_PACKAGE
340
341
    /* check args */
342
0
    assert(f);
343
0
    assert(p);
344
0
    assert(attr);
345
346
    /* Check whether datatype and dataspace are shared */
347
0
    if ((is_type_shared = H5O_msg_is_shared(H5O_DTYPE_ID, attr->shared->dt)) < 0)
348
0
        HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if datatype is shared");
349
350
0
    if ((is_space_shared = H5O_msg_is_shared(H5O_SDSPACE_ID, attr->shared->ds)) < 0)
351
0
        HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if dataspace is shared");
352
353
    /* Encode Version */
354
0
    *p++ = attr->shared->version;
355
356
    /* Set attribute flags if version >1 */
357
0
    if (attr->shared->version >= H5O_ATTR_VERSION_2) {
358
0
        flags = (is_type_shared ? H5O_ATTR_FLAG_TYPE_SHARED : 0);
359
0
        flags |= (is_space_shared ? H5O_ATTR_FLAG_SPACE_SHARED : 0);
360
0
        *p++ = (uint8_t)flags; /* Set flags for attribute */
361
0
    }                          /* end if */
362
0
    else
363
0
        *p++ = 0; /* Reserved, for version <2 */
364
365
    /*
366
     * Encode the lengths of the various parts of the attribute message. The
367
     * encoded lengths are exact but we pad each part except the data to be a
368
     * multiple of eight bytes (in the first version).
369
     */
370
0
    name_len = strlen(attr->shared->name) + 1;
371
0
    UINT16ENCODE(p, name_len);
372
0
    UINT16ENCODE(p, attr->shared->dt_size);
373
0
    UINT16ENCODE(p, attr->shared->ds_size);
374
375
    /* The character encoding for the attribute's name, in later versions */
376
0
    if (attr->shared->version >= H5O_ATTR_VERSION_3)
377
0
        *p++ = (uint8_t)attr->shared->encoding;
378
379
    /* Write the name including null terminator */
380
0
    H5MM_memcpy(p, attr->shared->name, name_len);
381
0
    if (attr->shared->version < H5O_ATTR_VERSION_2) {
382
        /* Pad to the correct number of bytes */
383
0
        memset(p + name_len, 0, H5O_ALIGN_OLD(name_len) - name_len);
384
0
        p += H5O_ALIGN_OLD(name_len);
385
0
    } /* end if */
386
0
    else
387
0
        p += name_len;
388
389
    /* encode the attribute datatype */
390
0
    if ((H5O_MSG_DTYPE->encode)(f, false, SIZE_MAX, p, attr->shared->dt) < 0)
391
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute datatype");
392
393
0
    if (attr->shared->version < H5O_ATTR_VERSION_2) {
394
0
        memset(p + attr->shared->dt_size, 0, H5O_ALIGN_OLD(attr->shared->dt_size) - attr->shared->dt_size);
395
0
        p += H5O_ALIGN_OLD(attr->shared->dt_size);
396
0
    } /* end if */
397
0
    else
398
0
        p += attr->shared->dt_size;
399
400
    /* encode the attribute dataspace */
401
0
    if ((H5O_MSG_SDSPACE->encode)(f, false, SIZE_MAX, p, &(attr->shared->ds->extent)) < 0)
402
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute dataspace");
403
404
0
    if (attr->shared->version < H5O_ATTR_VERSION_2) {
405
0
        memset(p + attr->shared->ds_size, 0, H5O_ALIGN_OLD(attr->shared->ds_size) - attr->shared->ds_size);
406
0
        p += H5O_ALIGN_OLD(attr->shared->ds_size);
407
0
    } /* end if */
408
0
    else
409
0
        p += attr->shared->ds_size;
410
411
    /* Store attribute data.  If there's no data, store 0 as fill value. */
412
0
    if (attr->shared->data)
413
0
        H5MM_memcpy(p, attr->shared->data, attr->shared->data_size);
414
0
    else
415
0
        memset(p, 0, attr->shared->data_size);
416
417
0
done:
418
0
    FUNC_LEAVE_NOAPI(ret_value)
419
0
} /* end H5O__attr_encode() */
420
421
/*--------------------------------------------------------------------------
422
 NAME
423
    H5O__attr_copy
424
 PURPOSE
425
    Copies a message from MESG to DEST, allocating DEST if necessary.
426
 USAGE
427
    void *H5O__attr_copy(mesg, dest)
428
        const void *mesg;       IN: Pointer to the source attribute struct
429
        const void *dest;       IN: Pointer to the destination attribute struct
430
 RETURNS
431
    Pointer to DEST on success, NULL on failure
432
 DESCRIPTION
433
        This function copies a native (memory) attribute message,
434
    allocating the destination structure if necessary.
435
--------------------------------------------------------------------------*/
436
static void *
437
H5O__attr_copy(const void *_src, void *_dst)
438
0
{
439
0
    void *ret_value = NULL; /* Return value */
440
441
0
    FUNC_ENTER_PACKAGE
442
443
    /* check args */
444
0
    assert(_src);
445
446
    /* copy */
447
0
    if (NULL == (ret_value = (H5A_t *)H5A__copy((H5A_t *)_dst, (const H5A_t *)_src)))
448
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "can't copy attribute");
449
450
0
done:
451
0
    FUNC_LEAVE_NOAPI(ret_value)
452
0
} /* end H5O__attr_copy() */
453
454
/*--------------------------------------------------------------------------
455
 NAME
456
    H5O__attr_size
457
 PURPOSE
458
    Return the raw message size in bytes
459
 USAGE
460
    size_t H5O__attr_size(f, mesg)
461
        H5F_t *f;         IN: pointer to the HDF5 file struct
462
        const void *mesg;     IN: Pointer to the source attribute struct
463
 RETURNS
464
    Size of message on success, 0 on failure
465
 DESCRIPTION
466
        This function returns the size of the raw attribute message on
467
    success.  (Not counting the message type or size fields, only the data
468
    portion of the message).  It doesn't take into account alignment.
469
--------------------------------------------------------------------------*/
470
static size_t
471
H5O__attr_size(const H5F_t H5_ATTR_UNUSED *f, const void *_mesg)
472
0
{
473
0
    const H5A_t *attr = (const H5A_t *)_mesg;
474
0
    size_t       name_len;
475
0
    size_t       ret_value = 0;
476
477
0
    FUNC_ENTER_PACKAGE_NOERR
478
479
0
    assert(attr);
480
481
    /* Common size information */
482
0
    ret_value = 1 + /*version               */
483
0
                1 + /*reserved/flags  */
484
0
                2 + /*name size inc. null */
485
0
                2 + /*type size   */
486
0
                2;  /*space size    */
487
488
    /* Length of attribute name */
489
0
    name_len = strlen(attr->shared->name) + 1;
490
491
    /* Version-specific size information */
492
0
    if (attr->shared->version == H5O_ATTR_VERSION_1)
493
0
        ret_value += H5O_ALIGN_OLD(name_len) +              /*attribute name  */
494
0
                     H5O_ALIGN_OLD(attr->shared->dt_size) + /*datatype    */
495
0
                     H5O_ALIGN_OLD(attr->shared->ds_size) + /*dataspace   */
496
0
                     attr->shared->data_size;               /*the data itself */
497
0
    else if (attr->shared->version == H5O_ATTR_VERSION_2)
498
0
        ret_value += name_len +               /*attribute name  */
499
0
                     attr->shared->dt_size +  /*datatype    */
500
0
                     attr->shared->ds_size +  /*dataspace   */
501
0
                     attr->shared->data_size; /*the data itself */
502
0
    else if (attr->shared->version == H5O_ATTR_VERSION_3)
503
0
        ret_value += 1 +                      /*character encoding    */
504
0
                     name_len +               /*attribute name  */
505
0
                     attr->shared->dt_size +  /*datatype    */
506
0
                     attr->shared->ds_size +  /*dataspace   */
507
0
                     attr->shared->data_size; /*the data itself */
508
0
    else
509
0
        assert(0 && "Bad attribute version");
510
511
0
    FUNC_LEAVE_NOAPI(ret_value)
512
0
} /* end H5O__attr_size() */
513
514
/*-------------------------------------------------------------------------
515
 * Function:    H5O__attr_reset
516
 *
517
 * Purpose:     Frees resources within a attribute message, but doesn't free
518
 *              the message itself.
519
 *
520
 * Return:      SUCCEED/FAIL
521
 *
522
 *-------------------------------------------------------------------------
523
 */
524
herr_t
525
H5O__attr_reset(void H5_ATTR_UNUSED *_mesg)
526
0
{
527
0
    FUNC_ENTER_PACKAGE_NOERR
528
529
0
    FUNC_LEAVE_NOAPI(SUCCEED)
530
0
} /* end H5O__attr_reset() */
531
532
/*-------------------------------------------------------------------------
533
 * Function:    H5O__attr_free
534
 *
535
 * Purpose:     Frees the message
536
 *
537
 * Return:      SUCCEED/FAIL
538
 *
539
 *-------------------------------------------------------------------------
540
 */
541
static herr_t
542
H5O__attr_free(void *mesg)
543
0
{
544
0
    H5A_t *attr      = (H5A_t *)mesg;
545
0
    herr_t ret_value = SUCCEED; /* Return value */
546
547
0
    FUNC_ENTER_PACKAGE
548
549
0
    assert(mesg);
550
551
0
    if (H5A__close(attr) < 0)
552
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, FAIL, "unable to close attribute object");
553
554
0
done:
555
0
    FUNC_LEAVE_NOAPI(ret_value)
556
0
} /* end H5O__attr_free() */
557
558
/*-------------------------------------------------------------------------
559
 * Function:    H5O__attr_delete
560
 *
561
 * Purpose:     Free file space referenced by message
562
 *
563
 * Return:      SUCCEED/FAIL
564
 *
565
 *-------------------------------------------------------------------------
566
 */
567
herr_t
568
H5O__attr_delete(H5F_t *f, H5O_t *oh, void *_mesg)
569
0
{
570
0
    H5A_t *attr      = (H5A_t *)_mesg;
571
0
    herr_t ret_value = SUCCEED; /* Return value */
572
573
0
    FUNC_ENTER_PACKAGE
574
575
    /* check args */
576
0
    assert(f);
577
0
    assert(attr);
578
579
    /* Decrement reference count on datatype in file */
580
0
    if ((H5O_MSG_DTYPE->del)(f, oh, attr->shared->dt) < 0)
581
0
        HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust datatype link count");
582
583
    /* Decrement reference count on dataspace in file */
584
0
    if ((H5O_MSG_SDSPACE->del)(f, oh, attr->shared->ds) < 0)
585
0
        HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust dataspace link count");
586
587
0
done:
588
0
    FUNC_LEAVE_NOAPI(ret_value)
589
0
} /* end H5O__attr_delete() */
590
591
/*-------------------------------------------------------------------------
592
 * Function:    H5O__attr_link
593
 *
594
 * Purpose:     Increment reference count on any objects referenced by
595
 *              message
596
 *
597
 * Return:      SUCCEED/FAIL
598
 *
599
 *-------------------------------------------------------------------------
600
 */
601
herr_t
602
H5O__attr_link(H5F_t *f, H5O_t *oh, void *_mesg)
603
0
{
604
0
    H5A_t *attr      = (H5A_t *)_mesg;
605
0
    herr_t ret_value = SUCCEED; /* Return value */
606
607
0
    FUNC_ENTER_PACKAGE
608
609
    /* check args */
610
0
    assert(f);
611
0
    assert(attr);
612
613
    /* Re-share attribute's datatype and dataspace to increment their
614
     * reference count if they're shared.
615
     * Otherwise they may be deleted when the attribute
616
     * message is deleted.
617
     */
618
    /* Increment reference count on datatype & dataspace in file */
619
0
    if ((H5O_MSG_DTYPE->link)(f, oh, attr->shared->dt) < 0)
620
0
        HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust datatype link count");
621
0
    if ((H5O_MSG_SDSPACE->link)(f, oh, attr->shared->ds) < 0)
622
0
        HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust dataspace link count");
623
624
0
done:
625
0
    FUNC_LEAVE_NOAPI(ret_value)
626
0
} /* end H5O__attr_link() */
627
628
/*-------------------------------------------------------------------------
629
 * Function:    H5O__attr_pre_copy_file
630
 *
631
 * Purpose:     Perform any necessary actions before copying message between
632
 *              files for attribute messages.
633
 *
634
 * Return:      SUCCEED/FAIL
635
 *
636
 *-------------------------------------------------------------------------
637
 */
638
static herr_t
639
H5O__attr_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *native_src, bool *deleted,
640
                        const H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
641
0
{
642
0
    const H5A_t *attr_src  = (const H5A_t *)native_src; /* Source attribute */
643
0
    herr_t       ret_value = SUCCEED;                   /* Return value */
644
645
0
    FUNC_ENTER_PACKAGE
646
647
    /* check args */
648
0
    assert(deleted);
649
0
    assert(cpy_info);
650
0
    assert(cpy_info->file_dst);
651
652
    /* Check to ensure that the version of the message to be copied does not exceed
653
     * the message version allowed by the destination file's high bound.
654
     */
655
0
    if (attr_src->shared->version > H5O_attr_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)])
656
0
        HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "attribute message version out of bounds");
657
658
    /* If we are not copying attributes into the destination file, indicate
659
     *  that this message should be deleted.
660
     */
661
0
    if (cpy_info->copy_without_attr)
662
0
        *deleted = true;
663
664
0
done:
665
0
    FUNC_LEAVE_NOAPI(ret_value)
666
0
} /* end H5O__attr_pre_copy_file() */
667
668
/*-------------------------------------------------------------------------
669
 * Function:    H5O__attr_copy_file
670
 *
671
 * Purpose:     Copies a message from _MESG to _DEST in file
672
 *
673
 * Return:      Success:        Ptr to _DEST
674
 *              Failure:        NULL
675
 *
676
 *-------------------------------------------------------------------------
677
 */
678
static void *
679
H5O__attr_copy_file(H5F_t *file_src, const H5O_msg_class_t H5_ATTR_UNUSED *mesg_type, void *native_src,
680
                    H5F_t *file_dst, bool *recompute_size, H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
681
0
{
682
0
    void *ret_value = NULL; /* Return value */
683
684
0
    FUNC_ENTER_PACKAGE
685
686
    /* check args */
687
0
    assert(native_src);
688
0
    assert(file_dst);
689
0
    assert(cpy_info);
690
0
    assert(!cpy_info->copy_without_attr);
691
692
    /* Mark datatype as being on disk now.  This step used to be done in a lower level
693
     * by H5O_dtype_decode.  But it has been moved up.  Not an ideal place, but no better
694
     * place than here. */
695
0
    if (H5T_set_loc(((H5A_t *)native_src)->shared->dt, H5F_VOL_OBJ(file_src), H5T_LOC_DISK) < 0)
696
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "invalid datatype location");
697
698
0
    if (NULL == (ret_value = H5A__attr_copy_file((H5A_t *)native_src, file_dst, recompute_size, cpy_info)))
699
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy attribute");
700
701
0
done:
702
0
    FUNC_LEAVE_NOAPI(ret_value)
703
0
} /* H5O__attr_copy_file() */
704
705
/*-------------------------------------------------------------------------
706
 * Function:    H5O__attr_post_copy_file
707
 *
708
 * Purpose:     Finish copying a message from between files.
709
 *              We have to copy the values of a reference attribute in the
710
 *              post copy because H5O_post_copy_file() fails at the case that
711
 *              an object may have a reference attribute that points to the
712
 *              object itself.
713
 *
714
 * Return:      SUCCEED/FAIL
715
 *
716
 *-------------------------------------------------------------------------
717
 */
718
static herr_t
719
H5O__attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst,
720
                         H5O_copy_t *cpy_info)
721
0
{
722
0
    herr_t ret_value = SUCCEED; /* Return value */
723
724
0
    FUNC_ENTER_PACKAGE
725
726
0
    if (H5A__attr_post_copy_file(src_oloc, (const H5A_t *)mesg_src, dst_oloc, (H5A_t *)mesg_dst, cpy_info) <
727
0
        0)
728
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't copy attribute");
729
730
0
done:
731
0
    FUNC_LEAVE_NOAPI(ret_value)
732
0
} /* H5O__attr_post_copy_file() */
733
734
/*-------------------------------------------------------------------------
735
 * Function:    H5O__attr_get_crt_index
736
 *
737
 * Purpose:     Get creation index from the message
738
 *
739
 * Return:      SUCCEED/FAIL
740
 *
741
 *-------------------------------------------------------------------------
742
 */
743
static herr_t
744
H5O__attr_get_crt_index(const void *_mesg, H5O_msg_crt_idx_t *crt_idx /*out*/)
745
0
{
746
0
    const H5A_t *attr = (const H5A_t *)_mesg;
747
748
0
    FUNC_ENTER_PACKAGE_NOERR
749
750
0
    assert(attr);
751
0
    assert(crt_idx);
752
753
    /* Get the attribute's creation index */
754
0
    *crt_idx = attr->shared->crt_idx;
755
756
0
    FUNC_LEAVE_NOAPI(SUCCEED)
757
0
} /* end H5O__attr_get_crt_index() */
758
759
/*-------------------------------------------------------------------------
760
 * Function:    H5O__attr_set_crt_index
761
 *
762
 * Purpose:     Set creation index from the message
763
 *
764
 * Return:      SUCCEED/FAIL
765
 *
766
 *-------------------------------------------------------------------------
767
 */
768
static herr_t
769
H5O__attr_set_crt_index(void *_mesg, H5O_msg_crt_idx_t crt_idx)
770
0
{
771
0
    H5A_t *attr = (H5A_t *)_mesg;
772
773
0
    FUNC_ENTER_PACKAGE_NOERR
774
775
0
    assert(attr);
776
777
    /* Set the creation index */
778
0
    attr->shared->crt_idx = crt_idx;
779
780
0
    FUNC_LEAVE_NOAPI(SUCCEED)
781
0
} /* end H5O__attr_set_crt_index() */
782
783
/*--------------------------------------------------------------------------
784
 NAME
785
    H5O__attr_debug
786
 PURPOSE
787
    Prints debugging information for an attribute message
788
 USAGE
789
    void *H5O__attr_debug(f, mesg, stream, indent, fwidth)
790
        H5F_t *f;               IN: pointer to the HDF5 file struct
791
        const void *mesg;       IN: Pointer to the source attribute struct
792
        FILE *stream;           IN: Pointer to the stream for output data
793
        int indent;            IN: Amount to indent information by
794
        int fwidth;            IN: Field width (?)
795
 RETURNS
796
    Non-negative on success/Negative on failure
797
 DESCRIPTION
798
        This function prints debugging output to the stream passed as a
799
    parameter.
800
--------------------------------------------------------------------------*/
801
static herr_t
802
H5O__attr_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth)
803
0
{
804
0
    const H5A_t *mesg = (const H5A_t *)_mesg;
805
0
    const char  *s;                   /* Temporary string pointer */
806
0
    char         buf[128];            /* Temporary string buffer */
807
0
    herr_t       ret_value = SUCCEED; /* Return value */
808
809
0
    FUNC_ENTER_PACKAGE
810
811
    /* check args */
812
0
    assert(f);
813
0
    assert(stream);
814
0
    assert(indent >= 0);
815
0
    assert(fwidth >= 0);
816
817
0
    fprintf(stream, "%*s%-*s \"%s\"\n", indent, "", fwidth, "Name:", mesg->shared->name);
818
0
    switch (mesg->shared->encoding) {
819
0
        case H5T_CSET_ASCII:
820
0
            s = "ASCII";
821
0
            break;
822
823
0
        case H5T_CSET_UTF8:
824
0
            s = "UTF-8";
825
0
            break;
826
827
0
        case H5T_CSET_RESERVED_2:
828
0
        case H5T_CSET_RESERVED_3:
829
0
        case H5T_CSET_RESERVED_4:
830
0
        case H5T_CSET_RESERVED_5:
831
0
        case H5T_CSET_RESERVED_6:
832
0
        case H5T_CSET_RESERVED_7:
833
0
        case H5T_CSET_RESERVED_8:
834
0
        case H5T_CSET_RESERVED_9:
835
0
        case H5T_CSET_RESERVED_10:
836
0
        case H5T_CSET_RESERVED_11:
837
0
        case H5T_CSET_RESERVED_12:
838
0
        case H5T_CSET_RESERVED_13:
839
0
        case H5T_CSET_RESERVED_14:
840
0
        case H5T_CSET_RESERVED_15:
841
0
            snprintf(buf, sizeof(buf), "H5T_CSET_RESERVED_%d", (int)(mesg->shared->encoding));
842
0
            s = buf;
843
0
            break;
844
845
0
        case H5T_CSET_ERROR:
846
0
        default:
847
0
            snprintf(buf, sizeof(buf), "Unknown character set: %d", (int)(mesg->shared->encoding));
848
0
            s = buf;
849
0
            break;
850
0
    } /* end switch */
851
0
    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Character Set of Name:", s);
852
0
    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
853
0
            "Object opened:", mesg->obj_opened ? "TRUE" : "FALSE");
854
0
    fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, "Object:", mesg->oloc.addr);
855
856
    /* Check for attribute creation order index on the attribute */
857
0
    if (mesg->shared->crt_idx != H5O_MAX_CRT_ORDER_IDX)
858
0
        fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
859
0
                "Creation Index:", (unsigned)mesg->shared->crt_idx);
860
861
0
    fprintf(stream, "%*sDatatype...\n", indent, "");
862
0
    fprintf(stream, "%*s%-*s %lu\n", indent + 3, "", MAX(0, fwidth - 3),
863
0
            "Encoded Size:", (unsigned long)(mesg->shared->dt_size));
864
0
    if ((H5O_MSG_DTYPE->debug)(f, mesg->shared->dt, stream, indent + 3, MAX(0, fwidth - 3)) < 0)
865
0
        HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to display datatype message info");
866
867
0
    fprintf(stream, "%*sDataspace...\n", indent, "");
868
0
    fprintf(stream, "%*s%-*s %lu\n", indent + 3, "", MAX(0, fwidth - 3),
869
0
            "Encoded Size:", (unsigned long)(mesg->shared->ds_size));
870
0
    if (H5S_debug(f, mesg->shared->ds, stream, indent + 3, MAX(0, fwidth - 3)) < 0)
871
0
        HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to display dataspace message info");
872
873
0
done:
874
0
    FUNC_LEAVE_NOAPI(ret_value)
875
0
} /* end H5O__attr_debug() */