Coverage Report

Created: 2024-06-18 06:29

/src/hdf5/src/H5Aint.c
Line
Count
Source (jump to first uncovered line)
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the COPYING file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/*-------------------------------------------------------------------------
14
 *
15
 * Created:        H5Aint.c
16
 *
17
 * Purpose:        Internal routines for managing attributes.
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5Amodule.h" /* This source code file is part of the H5A module */
27
#define H5O_FRIEND     /*suppress error about including H5Opkg      */
28
29
/***********/
30
/* Headers */
31
/***********/
32
#include "H5private.h"   /* Generic Functions                        */
33
#include "H5Apkg.h"      /* Attributes                               */
34
#include "H5Eprivate.h"  /* Error handling                           */
35
#include "H5FLprivate.h" /* Free Lists                               */
36
#include "H5Iprivate.h"  /* IDs                                      */
37
#include "H5MMprivate.h" /* Memory management                        */
38
#include "H5Opkg.h"      /* Object headers                           */
39
#include "H5SMprivate.h" /* Shared Object Header Messages            */
40
#include "H5VLprivate.h" /* Virtual Object Layer                     */
41
42
/****************/
43
/* Local Macros */
44
/****************/
45
46
/******************/
47
/* Local Typedefs */
48
/******************/
49
50
/* Data exchange structure to use when building table of compact attributes for an object */
51
typedef struct {
52
    H5F_t            *f;             /* Pointer to file that fractal heap is in */
53
    H5A_attr_table_t *atable;        /* Pointer to attribute table to build */
54
    bool              bogus_crt_idx; /* Whether bogus creation index values need to be set */
55
} H5A_compact_bt_ud_t;
56
57
/* Data exchange structure to use when copying an attribute from _SRC to _DST */
58
typedef struct {
59
    const H5O_ainfo_t *ainfo;          /* dense information    */
60
    H5F_t             *file;           /* file                 */
61
    bool              *recompute_size; /* Flag to indicate if size changed */
62
    H5O_copy_t        *cpy_info;       /* Information on copying options   */
63
    const H5O_loc_t   *oloc_src;
64
    H5O_loc_t         *oloc_dst;
65
} H5A_dense_file_cp_ud_t;
66
67
/********************/
68
/* Package Typedefs */
69
/********************/
70
71
/********************/
72
/* Local Prototypes */
73
/********************/
74
75
static herr_t H5A__close_cb(H5VL_object_t *attr_vol_obj, void **request);
76
static herr_t H5A__compact_build_table_cb(H5O_t *oh, H5O_mesg_t *mesg /*in,out*/, unsigned sequence,
77
                                          unsigned *oh_flags_ptr, void *_udata /*in,out*/);
78
static herr_t H5A__dense_build_table_cb(const H5A_t *attr, void *_udata);
79
static int    H5A__attr_cmp_name_inc(const void *attr1, const void *attr2);
80
static int    H5A__attr_cmp_name_dec(const void *attr1, const void *attr2);
81
static int    H5A__attr_cmp_corder_inc(const void *attr1, const void *attr2);
82
static int    H5A__attr_cmp_corder_dec(const void *attr1, const void *attr2);
83
static herr_t H5A__attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type, H5_iter_order_t order);
84
static herr_t H5A__iterate_common(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx,
85
                                  H5A_attr_iter_op_t *attr_op, void *op_data);
86
87
/*********************/
88
/* Package Variables */
89
/*********************/
90
91
/* Format version bounds for attribute */
92
const unsigned H5O_attr_ver_bounds[] = {
93
    H5O_ATTR_VERSION_1,     /* H5F_LIBVER_EARLIEST */
94
    H5O_ATTR_VERSION_3,     /* H5F_LIBVER_V18 */
95
    H5O_ATTR_VERSION_3,     /* H5F_LIBVER_V110 */
96
    H5O_ATTR_VERSION_3,     /* H5F_LIBVER_V112 */
97
    H5O_ATTR_VERSION_LATEST /* H5F_LIBVER_LATEST */
98
};
99
100
/*****************************/
101
/* Library Private Variables */
102
/*****************************/
103
104
/*******************/
105
/* Local Variables */
106
/*******************/
107
108
/* Declare the free lists of H5A_t */
109
H5FL_DEFINE(H5A_t);
110
111
/* Declare the free lists for H5A_shared_t's */
112
H5FL_DEFINE(H5A_shared_t);
113
114
/* Declare a free list to manage blocks of type conversion data */
115
H5FL_BLK_DEFINE(attr_buf);
116
117
typedef H5A_t *H5A_t_ptr;
118
H5FL_SEQ_DEFINE_STATIC(H5A_t_ptr);
119
120
/* Attribute ID class */
121
static const H5I_class_t H5I_ATTR_CLS[1] = {{
122
    H5I_ATTR,                 /* ID class value */
123
    0,                        /* Class flags */
124
    0,                        /* # of reserved IDs for class */
125
    (H5I_free_t)H5A__close_cb /* Callback routine for closing objects of this class */
126
}};
127
128
/*-------------------------------------------------------------------------
129
 * Function: H5A_init
130
 *
131
 * Purpose:  Initialize the interface from some other layer.
132
 *
133
 * Return:   Success:    non-negative
134
 *
135
 *           Failure:    negative
136
 *-------------------------------------------------------------------------
137
 */
138
herr_t
139
H5A_init(void)
140
1
{
141
1
    herr_t ret_value = SUCCEED; /* Return value */
142
143
1
    FUNC_ENTER_NOAPI(FAIL)
144
145
    /*
146
     * Create attribute ID type.
147
     */
148
1
    if (H5I_register_type(H5I_ATTR_CLS) < 0)
149
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to initialize interface");
150
151
1
done:
152
1
    FUNC_LEAVE_NOAPI(ret_value)
153
1
} /* end H5A_init() */
154
155
/*--------------------------------------------------------------------------
156
 NAME
157
    H5A_top_term_package
158
 PURPOSE
159
    Terminate various H5A objects
160
 USAGE
161
    void H5A_top_term_package()
162
 RETURNS
163
 DESCRIPTION
164
    Release IDs for the atom group, deferring full interface shutdown
165
    until later (in H5A_term_package).
166
 GLOBAL VARIABLES
167
 COMMENTS, BUGS, ASSUMPTIONS
168
     Can't report errors...
169
 EXAMPLES
170
 REVISION LOG
171
--------------------------------------------------------------------------*/
172
int
173
H5A_top_term_package(void)
174
1
{
175
1
    int n = 0;
176
177
1
    FUNC_ENTER_NOAPI_NOINIT_NOERR
178
179
1
    if (H5I_nmembers(H5I_ATTR) > 0) {
180
0
        (void)H5I_clear_type(H5I_ATTR, false, false);
181
0
        n++; /*H5I*/
182
0
    }        /* end if */
183
184
1
    FUNC_LEAVE_NOAPI(n)
185
1
} /* H5A_top_term_package() */
186
187
/*--------------------------------------------------------------------------
188
 NAME
189
    H5A_term_package
190
 PURPOSE
191
    Terminate various H5A objects
192
 USAGE
193
    void H5A_term_package()
194
 RETURNS
195
 DESCRIPTION
196
    Release any other resources allocated.
197
 GLOBAL VARIABLES
198
 COMMENTS, BUGS, ASSUMPTIONS
199
     Can't report errors...
200
201
     Finishes shutting down the interface, after H5A_top_term_package()
202
     is called
203
 EXAMPLES
204
 REVISION LOG
205
--------------------------------------------------------------------------*/
206
int
207
H5A_term_package(void)
208
1
{
209
1
    int n = 0;
210
211
1
    FUNC_ENTER_NOAPI_NOINIT_NOERR
212
213
    /* Sanity checks */
214
1
    assert(0 == H5I_nmembers(H5I_ATTR));
215
216
    /* Destroy the attribute object id group */
217
1
    n += (H5I_dec_type_ref(H5I_ATTR) > 0);
218
219
1
    FUNC_LEAVE_NOAPI(n)
220
1
} /* H5A_term_package() */
221
222
/*-------------------------------------------------------------------------
223
 * Function:    H5A__create
224
 *
225
 * Purpose:     This is the guts of creating an attribute.
226
 *
227
 * Return:      Attribute structure on success, NULL on Failure.
228
 *
229
 *-------------------------------------------------------------------------
230
 */
231
H5A_t *
232
H5A__create(const H5G_loc_t *loc, const char *attr_name, const H5T_t *type, const H5S_t *space, hid_t acpl_id)
233
0
{
234
0
    H5A_t   *attr = NULL;      /* Attribute created */
235
0
    hssize_t snelmts;          /* elements in attribute */
236
0
    size_t   nelmts;           /* elements in attribute */
237
0
    bool     exists;           /* Whether attribute exists */
238
0
    H5A_t   *ret_value = NULL; /* Return value */
239
240
0
    FUNC_ENTER_PACKAGE_TAG(loc->oloc->addr)
241
242
    /* Check args */
243
0
    assert(loc);
244
0
    assert(attr_name);
245
0
    assert(type);
246
0
    assert(space);
247
248
    /* Check for existing attribute with same name */
249
    /* (technically, the "attribute create" operation will fail for a duplicated
250
     *  name, but it's going to be hard to unwind all the special cases on
251
     *  failure, so just check first, for now - QAK)
252
     */
253
0
    exists = false;
254
0
    if (H5O__attr_exists(loc->oloc, attr_name, &exists) < 0)
255
0
        HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "error checking attributes");
256
0
    if (exists)
257
0
        HGOTO_ERROR(H5E_ATTR, H5E_ALREADYEXISTS, NULL, "attribute already exists");
258
259
    /* Check if the dataspace has an extent set (or is NULL) */
260
0
    if (!(H5S_has_extent(space)))
261
0
        HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, NULL, "dataspace extent has not been set");
262
263
    /* Check if the datatype is "sensible" for use in a dataset */
264
0
    if (H5T_is_sensible(type) != true)
265
0
        HGOTO_ERROR(H5E_ATTR, H5E_BADTYPE, NULL, "datatype is not sensible");
266
267
    /* Build the attribute information */
268
0
    if (NULL == (attr = H5FL_CALLOC(H5A_t)))
269
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "memory allocation failed for attribute info");
270
271
0
    if (NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t)))
272
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "can't allocate shared attr structure");
273
274
    /* If the creation property list is H5P_ATTRIBUTE_CREATE_DEFAULT, use the default character encoding */
275
0
    assert(acpl_id != H5P_DEFAULT);
276
0
    if (acpl_id == H5P_ATTRIBUTE_CREATE_DEFAULT)
277
0
        attr->shared->encoding = H5F_DEFAULT_CSET;
278
0
    else {
279
0
        H5P_genplist_t *ac_plist; /* ACPL Property list */
280
281
        /* Get a local copy of the attribute creation property list */
282
0
        if (NULL == (ac_plist = (H5P_genplist_t *)H5I_object(acpl_id)))
283
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list");
284
285
0
        if (H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
286
0
            HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get character encoding flag");
287
0
    } /* end else */
288
289
    /* Copy the attribute name */
290
0
    attr->shared->name = H5MM_xstrdup(attr_name);
291
292
    /* Copy datatype */
293
0
    if (NULL == (attr->shared->dt = H5T_copy(type, H5T_COPY_ALL)))
294
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't get shared datatype info");
295
296
    /* Convert a datatype (if committed) to a transient type if the committed datatype's file
297
       location is different from the file location where the attribute will be created */
298
0
    if (H5T_convert_committed_datatype(attr->shared->dt, loc->oloc->file) < 0)
299
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't get shared datatype info");
300
301
    /* Mark datatype as being on disk now */
302
0
    if (H5T_set_loc(attr->shared->dt, H5F_VOL_OBJ(loc->oloc->file), H5T_LOC_DISK) < 0)
303
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location");
304
305
    /* Set the version for datatype */
306
0
    if (H5T_set_version(loc->oloc->file, attr->shared->dt) < 0)
307
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set version of datatype");
308
309
    /* Copy the dataspace for the attribute */
310
0
    attr->shared->ds = H5S_copy(space, false, true);
311
312
    /* Set the version for dataspace */
313
0
    if (H5S_set_version(loc->oloc->file, attr->shared->ds) < 0)
314
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set version of dataspace");
315
316
    /* Copy the object header information */
317
0
    if (H5O_loc_copy_deep(&(attr->oloc), loc->oloc) < 0)
318
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry");
319
320
    /* Deep copy of the group hierarchy path */
321
0
    if (H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
322
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path");
323
324
    /* Check if any of the pieces should be (or are already) shared in the
325
     * SOHM table
326
     */
327
0
    if (H5SM_try_share(attr->oloc.file, NULL, 0, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0)
328
0
        HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "trying to share datatype failed");
329
0
    if (H5SM_try_share(attr->oloc.file, NULL, 0, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0)
330
0
        HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "trying to share dataspace failed");
331
332
    /* Check whether datatype is committed & increment ref count
333
     * (to maintain ref. count incr/decr similarity with "shared message"
334
     *      type of datatype sharing)
335
     */
336
0
    if (H5T_is_named(attr->shared->dt))
337
        /* Increment the reference count on the shared datatype */
338
0
        if (H5T_link(attr->shared->dt, 1) < 0)
339
0
            HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, NULL, "unable to adjust shared datatype link count");
340
341
    /* Compute the size of pieces on disk.  This is either the size of the
342
     * datatype and dataspace messages themselves, or the size of the "shared"
343
     * messages if either or both of them are shared.
344
     */
345
0
    attr->shared->dt_size = H5O_msg_raw_size(attr->oloc.file, H5O_DTYPE_ID, false, attr->shared->dt);
346
0
    attr->shared->ds_size = H5O_msg_raw_size(attr->oloc.file, H5O_SDSPACE_ID, false, attr->shared->ds);
347
348
    /* Get # of elements for attribute's dataspace */
349
0
    if ((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
350
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, NULL, "dataspace is invalid");
351
0
    H5_CHECKED_ASSIGN(nelmts, size_t, snelmts, hssize_t);
352
353
0
    assert(attr->shared->dt_size > 0);
354
0
    assert(attr->shared->ds_size > 0);
355
0
    attr->shared->data_size = nelmts * H5T_GET_SIZE(attr->shared->dt);
356
357
    /* Hold the symbol table entry (and file) open */
358
0
    if (H5O_open(&(attr->oloc)) < 0)
359
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open");
360
0
    attr->obj_opened = true;
361
362
    /* Set the version to encode the attribute with */
363
0
    if (H5A__set_version(attr->oloc.file, attr) < 0)
364
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version");
365
366
    /* Insert the attribute into the object header */
367
0
    if (H5O__attr_create(&(attr->oloc), attr) < 0)
368
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, NULL, "unable to create attribute in object header");
369
370
    /* Set return value */
371
0
    ret_value = attr;
372
373
0
done:
374
    /* Cleanup on failure */
375
0
    if (NULL == ret_value && attr && H5A__close(attr))
376
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute");
377
378
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
379
0
} /* H5A__create() */
380
381
/*-------------------------------------------------------------------------
382
 * Function:    H5A__create_by_name
383
 *
384
 * Purpose:     Create an attribute on object, according to it's name
385
 *
386
 * Return:      SUCCEED/FAIL
387
 *
388
 *-------------------------------------------------------------------------
389
 */
390
H5A_t *
391
H5A__create_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name, const H5T_t *type,
392
                    const H5S_t *space, hid_t acpl_id)
393
0
{
394
0
    H5G_loc_t  obj_loc;           /* Location used to open group */
395
0
    H5G_name_t obj_path;          /* Opened object group hier. path */
396
0
    H5O_loc_t  obj_oloc;          /* Opened object object location */
397
0
    bool       loc_found = false; /* Entry at 'obj_name' found */
398
0
    H5A_t     *attr      = NULL;  /* Attribute from object header */
399
0
    H5A_t     *ret_value = NULL;  /* Return value */
400
401
0
    FUNC_ENTER_PACKAGE
402
403
    /* check args */
404
0
    assert(loc);
405
0
    assert(obj_name);
406
0
    assert(attr_name);
407
408
    /* Set up opened group location to fill in */
409
0
    obj_loc.oloc = &obj_oloc;
410
0
    obj_loc.path = &obj_path;
411
0
    H5G_loc_reset(&obj_loc);
412
413
    /* Find the object's location */
414
0
    if (H5G_loc_find(loc, obj_name, &obj_loc /*out*/) < 0)
415
0
        HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found");
416
0
    loc_found = true;
417
418
    /* Go do the real work for attaching the attribute to the object */
419
0
    if (NULL == (attr = H5A__create(&obj_loc, attr_name, type, space, acpl_id)))
420
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to create attribute");
421
422
    /* Set return value */
423
0
    ret_value = attr;
424
425
0
done:
426
    /* Release resources */
427
0
    if (loc_found && H5G_loc_free(&obj_loc) < 0)
428
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location");
429
430
    /* Cleanup on failure */
431
0
    if (ret_value == NULL)
432
0
        if (attr && H5A__close(attr) < 0)
433
0
            HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute");
434
435
0
    FUNC_LEAVE_NOAPI(ret_value)
436
0
} /* H5A__create_by_name() */
437
438
/*-------------------------------------------------------------------------
439
 * Function:    H5A__open_common
440
 *
441
 * Purpose:     Finishes initializing an attributes the open
442
 *
443
 * Usage:
444
 *  herr_t H5A__open_common(loc, name)
445
 *      const H5G_loc_t *loc;   IN: Pointer to group location for object
446
 *      H5A_t *attr;            IN/OUT: Pointer to attribute to initialize
447
 *
448
 * Return:      SUCCEED/FAIL
449
 *
450
 *-------------------------------------------------------------------------
451
 */
452
static herr_t
453
H5A__open_common(const H5G_loc_t *loc, H5A_t *attr)
454
64
{
455
64
    herr_t ret_value = SUCCEED; /* Return value */
456
457
64
    FUNC_ENTER_PACKAGE
458
459
    /* check args */
460
64
    assert(loc);
461
64
    assert(attr);
462
463
#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG)
464
    /* Clear object location */
465
    if (H5O_loc_reset(&(attr->oloc)) < 0)
466
        HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to reset location");
467
#endif /* H5_USING_MEMCHECKER */
468
469
    /* Free any previous group hier. path */
470
64
    if (H5G_name_free(&(attr->path)) < 0)
471
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path");
472
473
    /* Deep copy of the symbol table entry */
474
64
    if (H5O_loc_copy_deep(&(attr->oloc), loc->oloc) < 0)
475
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry");
476
477
    /* Deep copy of the group hier. path */
478
64
    if (H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
479
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy entry");
480
481
    /* Hold the symbol table entry (and file) open */
482
64
    if (H5O_open(&(attr->oloc)) < 0)
483
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open");
484
64
    attr->obj_opened = true;
485
486
64
done:
487
64
    FUNC_LEAVE_NOAPI(ret_value)
488
64
} /* H5A__open_common() */
489
490
/*-------------------------------------------------------------------------
491
 * Function:    H5A__open
492
 *
493
 * Purpose:     Open an attribute in an object header
494
 *
495
 * Return:      SUCCEED/FAIL
496
 *
497
 *-------------------------------------------------------------------------
498
 */
499
H5A_t *
500
H5A__open(const H5G_loc_t *loc, const char *attr_name)
501
0
{
502
0
    H5A_t *attr      = NULL; /* Attribute from object header */
503
0
    H5A_t *ret_value = NULL; /* Return value */
504
505
0
    FUNC_ENTER_PACKAGE
506
507
    /* check args */
508
0
    assert(loc);
509
0
    assert(attr_name);
510
511
    /* Read in attribute from object header */
512
0
    if (NULL == (attr = H5O__attr_open_by_name(loc->oloc, attr_name)))
513
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL,
514
0
                    "unable to load attribute info from object header for attribute: '%s'", attr_name);
515
516
    /* Finish initializing attribute */
517
0
    if (H5A__open_common(loc, attr) < 0)
518
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute");
519
520
    /* Set return value */
521
0
    ret_value = attr;
522
523
0
done:
524
    /* Cleanup on failure */
525
0
    if (ret_value == NULL)
526
0
        if (attr && H5A__close(attr) < 0)
527
0
            HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute");
528
529
0
    FUNC_LEAVE_NOAPI(ret_value)
530
0
} /* H5A__open() */
531
532
/*-------------------------------------------------------------------------
533
 * Function:    H5A__open_by_idx
534
 *
535
 * Purpose:     Open an attribute according to its index order
536
 *
537
 * Return:      SUCCEED/FAIL
538
 *
539
 *-------------------------------------------------------------------------
540
 */
541
H5A_t *
542
H5A__open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order,
543
                 hsize_t n)
544
0
{
545
0
    H5G_loc_t  obj_loc;           /* Location used to open group */
546
0
    H5G_name_t obj_path;          /* Opened object group hier. path */
547
0
    H5O_loc_t  obj_oloc;          /* Opened object object location */
548
0
    bool       loc_found = false; /* Entry at 'obj_name' found */
549
0
    H5A_t     *attr      = NULL;  /* Attribute from object header */
550
0
    H5A_t     *ret_value = NULL;  /* Return value */
551
552
0
    FUNC_ENTER_PACKAGE
553
554
    /* check args */
555
0
    assert(loc);
556
0
    assert(obj_name);
557
558
    /* Set up opened group location to fill in */
559
0
    obj_loc.oloc = &obj_oloc;
560
0
    obj_loc.path = &obj_path;
561
0
    H5G_loc_reset(&obj_loc);
562
563
    /* Find the object's location */
564
0
    if (H5G_loc_find(loc, obj_name, &obj_loc /*out*/) < 0)
565
0
        HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found");
566
0
    loc_found = true;
567
568
    /* Read in attribute from object header */
569
0
    if (NULL == (attr = H5O__attr_open_by_idx(obj_loc.oloc, idx_type, order, n)))
570
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header");
571
572
    /* Finish initializing attribute */
573
0
    if (H5A__open_common(&obj_loc, attr) < 0)
574
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute");
575
576
    /* Set return value */
577
0
    ret_value = attr;
578
579
0
done:
580
    /* Release resources */
581
0
    if (loc_found && H5G_loc_free(&obj_loc) < 0)
582
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location");
583
584
    /* Cleanup on failure */
585
0
    if (ret_value == NULL)
586
0
        if (attr && H5A__close(attr) < 0)
587
0
            HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute");
588
589
0
    FUNC_LEAVE_NOAPI(ret_value)
590
0
} /* H5A__open_by_idx() */
591
592
/*-------------------------------------------------------------------------
593
 * Function:    H5A__open_by_name
594
 *
595
 * Purpose:     Open an attribute in an object header, according to it's name
596
 *
597
 * Return:      SUCCEED/FAIL
598
 *
599
 *-------------------------------------------------------------------------
600
 */
601
H5A_t *
602
H5A__open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name)
603
78
{
604
78
    H5G_loc_t  obj_loc;           /* Location used to open group */
605
78
    H5G_name_t obj_path;          /* Opened object group hier. path */
606
78
    H5O_loc_t  obj_oloc;          /* Opened object object location */
607
78
    bool       loc_found = false; /* Entry at 'obj_name' found */
608
78
    H5A_t     *attr      = NULL;  /* Attribute from object header */
609
78
    H5A_t     *ret_value = NULL;  /* Return value */
610
611
78
    FUNC_ENTER_PACKAGE
612
613
    /* check args */
614
78
    assert(loc);
615
78
    assert(obj_name);
616
78
    assert(attr_name);
617
618
    /* Set up opened group location to fill in */
619
78
    obj_loc.oloc = &obj_oloc;
620
78
    obj_loc.path = &obj_path;
621
78
    H5G_loc_reset(&obj_loc);
622
623
    /* Find the object's location */
624
78
    if (H5G_loc_find(loc, obj_name, &obj_loc /*out*/) < 0)
625
0
        HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found");
626
78
    loc_found = true;
627
628
    /* Read in attribute from object header */
629
78
    if (NULL == (attr = H5O__attr_open_by_name(obj_loc.oloc, attr_name)))
630
14
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header");
631
632
    /* Finish initializing attribute */
633
64
    if (H5A__open_common(loc, attr) < 0)
634
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute");
635
636
    /* Set return value */
637
64
    ret_value = attr;
638
639
78
done:
640
    /* Release resources */
641
78
    if (loc_found && H5G_loc_free(&obj_loc) < 0)
642
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location");
643
644
    /* Cleanup on failure */
645
78
    if (ret_value == NULL)
646
14
        if (attr && H5A__close(attr) < 0)
647
0
            HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute");
648
649
78
    FUNC_LEAVE_NOAPI(ret_value)
650
64
} /* H5A__open_by_name() */
651
652
/*--------------------------------------------------------------------------
653
 NAME
654
    H5A__read
655
 PURPOSE
656
    Actually read in data from an attribute
657
 USAGE
658
    herr_t H5A__read (attr, mem_type, buf)
659
        H5A_t *attr;         IN: Attribute to read
660
        const H5T_t *mem_type;     IN: Memory datatype of buffer
661
        void *buf;           IN: Buffer for data to read
662
 RETURNS
663
    Non-negative on success/Negative on failure
664
665
 DESCRIPTION
666
    This function reads a complete attribute from disk.
667
--------------------------------------------------------------------------*/
668
herr_t
669
H5A__read(const H5A_t *attr, const H5T_t *mem_type, void *buf)
670
64
{
671
64
    uint8_t    *tconv_buf = NULL; /* datatype conv buffer*/
672
64
    uint8_t    *bkg_buf   = NULL; /* background buffer */
673
64
    hssize_t    snelmts;          /* elements in attribute */
674
64
    size_t      nelmts;           /* elements in attribute*/
675
64
    H5T_path_t *tpath = NULL;     /* type conversion info    */
676
64
    size_t      src_type_size;    /* size of source type     */
677
64
    size_t      dst_type_size;    /* size of destination type */
678
64
    size_t      buf_size;         /* desired buffer size    */
679
64
    herr_t      ret_value = SUCCEED;
680
681
64
    FUNC_ENTER_PACKAGE_TAG(attr->oloc.addr)
682
683
64
    assert(attr);
684
64
    assert(mem_type);
685
64
    assert(buf);
686
687
    /* Patch the top level file pointer in attr->shared->dt->shared->u.vlen.f if needed */
688
64
    if (H5T_patch_vlen_file(attr->shared->dt, H5F_VOL_OBJ(attr->oloc.file)) < 0)
689
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch VL datatype file pointer");
690
691
    /* Create buffer for data to store on disk */
692
64
    if ((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
693
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid");
694
64
    H5_CHECKED_ASSIGN(nelmts, size_t, snelmts, hssize_t);
695
696
64
    if (nelmts > 0) {
697
        /* Get the memory and file datatype sizes */
698
64
        src_type_size = H5T_GET_SIZE(attr->shared->dt);
699
64
        dst_type_size = H5T_GET_SIZE(mem_type);
700
701
        /* Check if the attribute has any data yet, if not, fill with zeroes */
702
64
        if (attr->obj_opened && !attr->shared->data)
703
0
            memset(buf, 0, (dst_type_size * nelmts));
704
64
        else { /* Attribute exists and has a value */
705
            /* Convert memory buffer into disk buffer */
706
            /* Set up type conversion function */
707
64
            if (NULL == (tpath = H5T_path_find(attr->shared->dt, mem_type)))
708
0
                HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL,
709
64
                            "unable to convert between src and dst datatypes");
710
711
            /* Check for type conversion required */
712
64
            if (!H5T_path_noop(tpath)) {
713
6
                H5T_bkg_t need_bkg; /* Background buffer type */
714
715
                /* Get the maximum buffer size needed and allocate it */
716
6
                buf_size = nelmts * MAX(src_type_size, dst_type_size);
717
6
                if (NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
718
0
                    HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed");
719
720
                /* Copy the attribute data into the buffer for conversion */
721
6
                H5MM_memcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts));
722
723
                /* Check if we need a background buffer */
724
6
                need_bkg = H5T_path_bkg(tpath);
725
726
6
                if (need_bkg) {
727
                    /* Allocate background buffer */
728
0
                    if (NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
729
0
                        HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed");
730
731
                    /* Copy the application buffer into the background buffer if necessary */
732
0
                    if (need_bkg == H5T_BKG_YES) {
733
0
                        assert(buf_size >= (dst_type_size * nelmts));
734
0
                        H5MM_memcpy(bkg_buf, buf, dst_type_size * nelmts);
735
0
                    }
736
0
                }
737
738
                /* Perform datatype conversion.  */
739
6
                if (H5T_convert(tpath, attr->shared->dt, mem_type, nelmts, (size_t)0, (size_t)0, tconv_buf,
740
6
                                bkg_buf) < 0)
741
3
                    HGOTO_ERROR(H5E_ATTR, H5E_CANTCONVERT, FAIL, "datatype conversion failed");
742
743
                /* Copy the converted data into the user's buffer */
744
3
                H5MM_memcpy(buf, tconv_buf, (dst_type_size * nelmts));
745
3
            } /* end if */
746
            /* No type conversion necessary */
747
58
            else {
748
58
                assert(dst_type_size == src_type_size);
749
750
                /* Copy the attribute data into the user's buffer */
751
58
                H5MM_memcpy(buf, attr->shared->data, (dst_type_size * nelmts));
752
58
            } /* end else */
753
64
        }     /* end else */
754
64
    }         /* end if */
755
756
64
done:
757
    /* Release resources */
758
64
    if (tconv_buf)
759
6
        tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf);
760
64
    if (bkg_buf)
761
0
        bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
762
763
64
    FUNC_LEAVE_NOAPI_TAG(ret_value)
764
64
} /* H5A__read() */
765
766
/*--------------------------------------------------------------------------
767
 NAME
768
    H5A__write
769
 PURPOSE
770
    Actually write out data to an attribute
771
 USAGE
772
    herr_t H5A__write (attr, mem_type, buf)
773
        H5A_t *attr;         IN: Attribute to write
774
        const H5T_t *mem_type;     IN: Memory datatype of buffer
775
        const void *buf;           IN: Buffer of data to write
776
 RETURNS
777
    Non-negative on success/Negative on failure
778
 DESCRIPTION
779
    This function writes a complete attribute to disk.
780
--------------------------------------------------------------------------*/
781
herr_t
782
H5A__write(H5A_t *attr, const H5T_t *mem_type, const void *buf)
783
0
{
784
0
    uint8_t    *tconv_buf = NULL; /* datatype conv buffer */
785
0
    uint8_t    *bkg_buf   = NULL; /* temp conversion buffer */
786
0
    hssize_t    snelmts;          /* elements in attribute */
787
0
    size_t      nelmts;           /* elements in attribute */
788
0
    H5T_path_t *tpath = NULL;     /* conversion information*/
789
0
    size_t      src_type_size;    /* size of source type    */
790
0
    size_t      dst_type_size;    /* size of destination type*/
791
0
    size_t      buf_size;         /* desired buffer size    */
792
0
    herr_t      ret_value = SUCCEED;
793
794
0
    FUNC_ENTER_PACKAGE_TAG(attr->oloc.addr)
795
796
0
    assert(attr);
797
0
    assert(mem_type);
798
0
    assert(buf);
799
800
    /* Patch the top level file pointer in attr->shared->dt->shared->u.vlen.f if needed */
801
0
    if (H5T_patch_vlen_file(attr->shared->dt, H5F_VOL_OBJ(attr->oloc.file)) < 0)
802
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't patch VL datatype file pointer");
803
804
    /* Get # of elements for attribute's dataspace */
805
0
    if ((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
806
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid");
807
0
    H5_CHECKED_ASSIGN(nelmts, size_t, snelmts, hssize_t);
808
809
    /* If there's actually data elements for the attribute, make a copy of the data passed in */
810
0
    if (nelmts > 0) {
811
        /* Get the memory and file datatype sizes */
812
0
        src_type_size = H5T_GET_SIZE(mem_type);
813
0
        dst_type_size = H5T_GET_SIZE(attr->shared->dt);
814
815
        /* Convert memory buffer into disk buffer */
816
        /* Set up type conversion function */
817
0
        if (NULL == (tpath = H5T_path_find(mem_type, attr->shared->dt)))
818
0
            HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes");
819
820
        /* Check for type conversion required */
821
0
        if (!H5T_path_noop(tpath)) {
822
0
            H5T_bkg_t need_bkg; /* Background buffer type */
823
824
            /* Get the maximum buffer size needed and allocate it */
825
0
            buf_size = nelmts * MAX(src_type_size, dst_type_size);
826
0
            if (NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
827
0
                HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed");
828
829
            /* Copy the user's data into the buffer for conversion */
830
0
            H5MM_memcpy(tconv_buf, buf, (src_type_size * nelmts));
831
832
            /* Check if we need a background buffer */
833
0
            if (H5T_detect_class(attr->shared->dt, H5T_VLEN, false))
834
0
                need_bkg = H5T_BKG_YES;
835
0
            else
836
0
                need_bkg = H5T_path_bkg(tpath);
837
838
0
            if (need_bkg) {
839
                /* Use the existing attribute data buffer, if present, as the background buffer,
840
                 * otherwise allocate one.  Note we don't need to track which one it is since both
841
                 * use the "attr_buf" free list block. */
842
0
                if (attr->shared->data) {
843
0
                    bkg_buf            = attr->shared->data;
844
0
                    attr->shared->data = NULL;
845
846
                    /* Clear background buffer if it's not supposed to be initialized with file
847
                     * contents */
848
0
                    if (need_bkg == H5T_BKG_TEMP)
849
0
                        memset(bkg_buf, 0, dst_type_size * nelmts);
850
0
                }
851
0
                else if (NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
852
0
                    HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed");
853
0
            }
854
855
            /* Perform datatype conversion */
856
0
            if (H5T_convert(tpath, mem_type, attr->shared->dt, nelmts, (size_t)0, (size_t)0, tconv_buf,
857
0
                            bkg_buf) < 0)
858
0
                HGOTO_ERROR(H5E_ATTR, H5E_CANTCONVERT, FAIL, "datatype conversion failed");
859
860
            /* Free the previous attribute data buffer, if there is one */
861
0
            if (attr->shared->data)
862
0
                attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
863
864
            /* Set the pointer to the attribute data to the converted information */
865
0
            attr->shared->data = tconv_buf;
866
0
            tconv_buf          = NULL;
867
0
        } /* end if */
868
        /* No type conversion necessary */
869
0
        else {
870
0
            assert(dst_type_size == src_type_size);
871
872
            /* Allocate the attribute buffer, if there isn't one */
873
0
            if (attr->shared->data == NULL)
874
0
                if (NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts)))
875
0
                    HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
876
877
            /* Copy the attribute data into the attribute data buffer */
878
0
            H5MM_memcpy(attr->shared->data, buf, (dst_type_size * nelmts));
879
0
        } /* end else */
880
881
        /* Modify the attribute in the object header */
882
0
        if (H5O__attr_write(&(attr->oloc), attr) < 0)
883
0
            HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to modify attribute");
884
0
    } /* end if */
885
886
0
done:
887
    /* Release resources */
888
0
    if (tconv_buf)
889
0
        tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf);
890
0
    if (bkg_buf)
891
0
        bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
892
893
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
894
0
} /* H5A__write() */
895
896
/*--------------------------------------------------------------------------
897
 NAME
898
    H5A__get_name
899
 PURPOSE
900
    Gets a copy of the name for an attribute
901
 RETURNS
902
    Non-negative on success/Negative on failure
903
 DESCRIPTION
904
        This function retrieves the name of an attribute for an attribute ID.
905
    Up to 'buf_size' characters are stored in 'buf' followed by a '\0' string
906
    terminator.  If the name of the attribute is longer than 'buf_size'-1,
907
    the string terminator is stored in the last position of the buffer to
908
    properly terminate the string.
909
        This function returns the length of the attribute's name (which may be
910
    longer than 'buf_size') in the 'attr_name_len' parameter.
911
--------------------------------------------------------------------------*/
912
herr_t
913
H5A__get_name(H5A_t *attr, size_t buf_size, char *buf, size_t *attr_name_len)
914
0
{
915
0
    size_t copy_len, nbytes;
916
917
0
    FUNC_ENTER_PACKAGE_NOERR
918
919
    /* Sanity checks */
920
0
    assert(attr);
921
0
    assert(attr_name_len);
922
923
    /* Get the real attribute length */
924
0
    nbytes = strlen(attr->shared->name);
925
926
    /* Compute the string length which will fit into the user's buffer */
927
0
    copy_len = MIN(buf_size - 1, nbytes);
928
929
    /* Copy all/some of the name */
930
0
    if (buf && copy_len > 0) {
931
0
        H5MM_memcpy(buf, attr->shared->name, copy_len);
932
933
        /* Terminate the string */
934
0
        buf[copy_len] = '\0';
935
0
    } /* end if */
936
937
    /* Set actual attribute name length */
938
0
    *attr_name_len = nbytes;
939
940
0
    FUNC_LEAVE_NOAPI(SUCCEED)
941
0
} /* H5A__get_name() */
942
943
/*-------------------------------------------------------------------------
944
 * Function:    H5A_get_space
945
 *
946
 * Purpose:     Returns dataspace of the attribute.
947
 *
948
 * Return:      Success:    A valid ID for the dataspace of an attribute
949
 *
950
 *              Failure:    H5I_INVALID_ID
951
 *
952
 *-------------------------------------------------------------------------
953
 */
954
hid_t
955
H5A_get_space(H5A_t *attr)
956
3
{
957
3
    H5S_t *ds        = NULL;
958
3
    hid_t  ret_value = H5I_INVALID_HID;
959
960
3
    FUNC_ENTER_NOAPI_NOINIT
961
962
3
    assert(attr);
963
964
    /* Copy the attribute's dataspace */
965
3
    if (NULL == (ds = H5S_copy(attr->shared->ds, false, true)))
966
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy dataspace");
967
968
    /* Register */
969
3
    if ((ret_value = H5I_register(H5I_DATASPACE, ds, true)) < 0)
970
0
        HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace ID");
971
972
3
done:
973
3
    if (H5I_INVALID_HID == ret_value && ds && H5S_close(ds) < 0)
974
0
        HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release dataspace");
975
976
3
    FUNC_LEAVE_NOAPI(ret_value)
977
3
} /* end H5A_get_space() */
978
979
/*-------------------------------------------------------------------------
980
 * Function:    H5A__get_type
981
 *
982
 * Purpose:     Returns an ID for the datatype of an attribute
983
 *
984
 * Return:      Success:    A valid ID for the datatype of an attribute
985
 *              Failure:    H5I_INVALID_HID
986
 *
987
 *-------------------------------------------------------------------------
988
 */
989
hid_t
990
H5A__get_type(H5A_t *attr)
991
58
{
992
58
    H5T_t *dt        = NULL;
993
58
    hid_t  ret_value = H5I_INVALID_HID;
994
995
58
    FUNC_ENTER_PACKAGE
996
997
58
    assert(attr);
998
999
    /* Patch the datatype's "top level" file pointer */
1000
58
    if (H5T_patch_file(attr->shared->dt, attr->oloc.file) < 0)
1001
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to patch datatype's file pointer");
1002
1003
    /* Copy the attribute's datatype.  If the type is a named type then
1004
     * reopen the type before returning it to the user. Make the type
1005
     * read-only.
1006
     */
1007
58
    if (NULL == (dt = H5T_copy_reopen(attr->shared->dt)))
1008
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy datatype");
1009
1010
    /* Mark any datatypes as being in memory now */
1011
58
    if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
1012
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "invalid datatype location");
1013
1014
    /* Lock copied type */
1015
58
    if (H5T_lock(dt, false) < 0)
1016
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to lock transient datatype");
1017
1018
    /* Register */
1019
58
    if (H5T_is_named(dt)) {
1020
        /* If this is a committed datatype, we need to recreate the
1021
         * two level IDs, where the VOL object is a copy of the
1022
         * returned datatype
1023
         */
1024
0
        if ((ret_value = H5VL_wrap_register(H5I_DATATYPE, dt, true)) < 0)
1025
0
            HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register file handle");
1026
0
    }
1027
58
    else {
1028
58
        if ((ret_value = H5I_register(H5I_DATATYPE, dt, true)) < 0)
1029
0
            HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype");
1030
58
    }
1031
1032
58
done:
1033
58
    if (H5I_INVALID_HID == ret_value)
1034
0
        if (dt && H5T_close(dt) < 0)
1035
0
            HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release datatype");
1036
1037
58
    FUNC_LEAVE_NOAPI(ret_value)
1038
58
} /* end H5A__get_type() */
1039
1040
/*--------------------------------------------------------------------------
1041
 NAME
1042
    H5A__get_create_plist
1043
 PURPOSE
1044
    Private version of H5Aget_create_plist
1045
 RETURNS
1046
    This function returns the ID of a copy of the attribute's creation
1047
    property list, or negative on failure.
1048
 DESCRIPTION
1049
        This function returns a copy of the creation property list for
1050
    an attribute.  The resulting ID must be closed with H5Pclose() or
1051
    resource leaks will occur.
1052
--------------------------------------------------------------------------*/
1053
hid_t
1054
H5A__get_create_plist(H5A_t *attr)
1055
0
{
1056
0
    H5P_genplist_t *plist;                       /* Default property list */
1057
0
    hid_t           new_plist_id;                /* ID of ACPL to return */
1058
0
    H5P_genplist_t *new_plist;                   /* ACPL to return */
1059
0
    hid_t           ret_value = H5I_INVALID_HID; /* Return value */
1060
1061
0
    FUNC_ENTER_PACKAGE
1062
1063
0
    if (NULL == (plist = (H5P_genplist_t *)H5I_object(H5P_LST_ATTRIBUTE_CREATE_ID_g)))
1064
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get default ACPL");
1065
1066
    /* Create the property list object to return */
1067
0
    if ((new_plist_id = H5P_copy_plist(plist, true)) < 0)
1068
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties");
1069
0
    if (NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_plist_id)))
1070
0
        HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list");
1071
1072
    /* Set the character encoding on the new property list */
1073
0
    if (H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
1074
0
        HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding");
1075
1076
0
    ret_value = new_plist_id;
1077
1078
0
done:
1079
0
    FUNC_LEAVE_NOAPI(ret_value)
1080
0
} /* end H5A__get_create_plist() */
1081
1082
/*-------------------------------------------------------------------------
1083
 * Function:    H5A__get_info
1084
 *
1085
 * Purpose:    Retrieve information about an attribute.
1086
 *
1087
 * Return:    Success:    Non-negative
1088
 *        Failure:    Negative
1089
 *
1090
 *-------------------------------------------------------------------------
1091
 */
1092
herr_t
1093
H5A__get_info(const H5A_t *attr, H5A_info_t *ainfo)
1094
0
{
1095
0
    herr_t ret_value = SUCCEED; /* Return value */
1096
1097
0
    FUNC_ENTER_NOAPI_NOERR
1098
1099
    /* Check args */
1100
0
    assert(attr);
1101
0
    assert(ainfo);
1102
1103
    /* Set info for attribute */
1104
0
    ainfo->cset      = attr->shared->encoding;
1105
0
    ainfo->data_size = attr->shared->data_size;
1106
0
    if (attr->shared->crt_idx == H5O_MAX_CRT_ORDER_IDX) {
1107
0
        ainfo->corder_valid = false;
1108
0
        ainfo->corder       = 0;
1109
0
    } /* end if */
1110
0
    else {
1111
0
        ainfo->corder_valid = true;
1112
0
        ainfo->corder       = attr->shared->crt_idx;
1113
0
    } /* end else */
1114
1115
0
    FUNC_LEAVE_NOAPI(ret_value)
1116
0
} /* end H5A__get_info() */
1117
1118
/*-------------------------------------------------------------------------
1119
 * Function:    H5A__copy
1120
 *
1121
 * Purpose:     Copies attribute OLD_ATTR.
1122
 *
1123
 * Return:      Success:    Pointer to a new copy of the OLD_ATTR argument.
1124
 *              Failure:    NULL
1125
 *
1126
 *-------------------------------------------------------------------------
1127
 */
1128
H5A_t *
1129
H5A__copy(H5A_t *_new_attr, const H5A_t *old_attr)
1130
64
{
1131
64
    H5A_t *new_attr       = NULL;
1132
64
    bool   allocated_attr = false; /* Whether the attribute was allocated */
1133
64
    H5A_t *ret_value      = NULL;  /* Return value */
1134
1135
64
    FUNC_ENTER_PACKAGE
1136
1137
    /* check args */
1138
64
    assert(old_attr);
1139
1140
    /* Allocate attribute structure */
1141
64
    if (_new_attr == NULL) {
1142
64
        if (NULL == (new_attr = H5FL_CALLOC(H5A_t)))
1143
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
1144
64
        allocated_attr = true;
1145
64
    } /* end if */
1146
0
    else
1147
0
        new_attr = _new_attr;
1148
1149
    /* Copy the top level of the attribute */
1150
64
    new_attr->sh_loc = old_attr->sh_loc;
1151
1152
    /* Deep copy of the group hierarchy path */
1153
64
    if (H5G_name_copy(&(new_attr->path), &(old_attr->path), H5_COPY_DEEP) < 0)
1154
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path");
1155
1156
    /* Share some attribute information */
1157
64
    new_attr->shared = old_attr->shared;
1158
1159
    /* Increment reference count for shared object */
1160
64
    new_attr->shared->nrefs++;
1161
1162
    /* Don't open the object header for a copy */
1163
64
    new_attr->obj_opened = false;
1164
1165
    /* Set the return value */
1166
64
    ret_value = new_attr;
1167
1168
64
done:
1169
64
    if (ret_value == NULL)
1170
0
        if (allocated_attr && new_attr && H5A__close(new_attr) < 0)
1171
0
            HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute");
1172
1173
64
    FUNC_LEAVE_NOAPI(ret_value)
1174
64
} /* end H5A__copy() */
1175
1176
/*-------------------------------------------------------------------------
1177
 * Function:    H5A__shared_free
1178
 *
1179
 * Purpose:     Cleans up the shared attribute data. This will free
1180
 *              the attribute's shared structure as well.
1181
 *
1182
 *              attr and attr->shared must not be NULL
1183
 *
1184
 * Return:      SUCCEED/FAIL
1185
 *
1186
 *-------------------------------------------------------------------------
1187
 */
1188
herr_t
1189
H5A__shared_free(H5A_t *attr)
1190
76
{
1191
76
    herr_t ret_value = SUCCEED; /* Return value */
1192
1193
76
    FUNC_ENTER_PACKAGE
1194
1195
76
    assert(attr);
1196
76
    assert(attr->shared);
1197
1198
    /* Free dynamically allocated items.
1199
     * When possible, keep trying to shut things down (via HDONE_ERROR).
1200
     */
1201
76
    if (attr->shared->name) {
1202
76
        H5MM_xfree(attr->shared->name);
1203
76
        attr->shared->name = NULL;
1204
76
    }
1205
76
    if (attr->shared->dt) {
1206
52
        if (H5T_close_real(attr->shared->dt) < 0)
1207
0
            HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info");
1208
52
        attr->shared->dt = NULL;
1209
52
    }
1210
76
    if (attr->shared->ds) {
1211
52
        if (H5S_close(attr->shared->ds) < 0)
1212
0
            HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info");
1213
52
        attr->shared->ds = NULL;
1214
52
    }
1215
76
    if (attr->shared->data)
1216
52
        attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
1217
1218
    /* Destroy shared attribute struct */
1219
76
    attr->shared = H5FL_FREE(H5A_shared_t, attr->shared);
1220
1221
76
    FUNC_LEAVE_NOAPI(ret_value)
1222
76
} /* end H5A__shared_free() */
1223
1224
/*-------------------------------------------------------------------------
1225
 * Function:    H5A__close_cb
1226
 *
1227
 * Purpose:     Called when the ref count reaches zero on the attribute's ID
1228
 *
1229
 * Return:      SUCCEED/FAIL
1230
 *
1231
 *-------------------------------------------------------------------------
1232
 */
1233
static herr_t
1234
H5A__close_cb(H5VL_object_t *attr_vol_obj, void **request)
1235
64
{
1236
64
    herr_t ret_value = SUCCEED; /* Return value */
1237
1238
64
    FUNC_ENTER_PACKAGE
1239
1240
    /* Sanity check */
1241
64
    assert(attr_vol_obj);
1242
1243
    /* Close the attribute */
1244
64
    if (H5VL_attr_close(attr_vol_obj, H5P_DATASET_XFER_DEFAULT, request) < 0)
1245
0
        HGOTO_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "problem closing attribute");
1246
1247
    /* Free the VOL object */
1248
64
    if (H5VL_free_object(attr_vol_obj) < 0)
1249
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to free VOL object");
1250
1251
64
done:
1252
64
    FUNC_LEAVE_NOAPI(ret_value)
1253
64
} /* end H5A__close_cb() */
1254
1255
/*-------------------------------------------------------------------------
1256
 * Function:    H5A__close
1257
 *
1258
 * Purpose:     Frees an attribute and all associated memory.
1259
 *
1260
 * Return:      SUCCEED/FAIL
1261
 *
1262
 *-------------------------------------------------------------------------
1263
 */
1264
herr_t
1265
H5A__close(H5A_t *attr)
1266
116
{
1267
116
    herr_t ret_value = SUCCEED; /* Return value */
1268
1269
116
    FUNC_ENTER_PACKAGE
1270
1271
116
    assert(attr);
1272
116
    assert(attr->shared);
1273
1274
    /* Close the object's symbol-table entry */
1275
116
    if (attr->obj_opened && (H5O_close(&(attr->oloc), NULL) < 0))
1276
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info");
1277
1278
    /* Reference count can be 0.  It only happens when H5A__create fails. */
1279
116
    if (attr->shared->nrefs <= 1) {
1280
        /* Free dynamically allocated items */
1281
52
        if (attr->shared)
1282
52
            if (H5A__shared_free(attr) < 0)
1283
0
                HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info");
1284
52
    } /* end if */
1285
64
    else {
1286
        /* There are other references to the shared part of the attribute.
1287
         * Only decrement the reference count. */
1288
64
        --attr->shared->nrefs;
1289
64
    } /* end else */
1290
1291
    /* Free group hierarchy path */
1292
116
    if (H5G_name_free(&(attr->path)) < 0)
1293
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path");
1294
1295
116
    attr->shared = NULL;
1296
116
    attr         = H5FL_FREE(H5A_t, attr);
1297
1298
116
done:
1299
116
    FUNC_LEAVE_NOAPI(ret_value)
1300
116
} /* end H5A__close() */
1301
1302
/*-------------------------------------------------------------------------
1303
 * Function:    H5A_oloc
1304
 *
1305
 * Purpose:    Return the object location for an attribute.  It's the
1306
 *        object location for the object to which the attribute
1307
 *        belongs, not the attribute itself.
1308
 *
1309
 * Return:    Success:    Ptr to entry
1310
 *        Failure:    NULL
1311
 *
1312
 *-------------------------------------------------------------------------
1313
 */
1314
H5O_loc_t *
1315
H5A_oloc(H5A_t *attr)
1316
24
{
1317
24
    H5O_loc_t *ret_value = NULL; /* Return value */
1318
1319
24
    FUNC_ENTER_NOAPI_NOERR
1320
1321
24
    assert(attr);
1322
1323
    /* Set return value */
1324
24
    ret_value = &(attr->oloc);
1325
1326
24
    FUNC_LEAVE_NOAPI(ret_value)
1327
24
} /* end H5A_oloc() */
1328
1329
/*-------------------------------------------------------------------------
1330
 * Function:    H5A_nameof
1331
 *
1332
 * Purpose:    Return the group hier. path for an attribute.  It's the
1333
 *        group hier. path for the object to which the attribute
1334
 *        belongs, not the attribute itself.
1335
 *
1336
 * Return:    Success:    Ptr to entry
1337
 *        Failure:    NULL
1338
 *
1339
 *-------------------------------------------------------------------------
1340
 */
1341
H5G_name_t *
1342
H5A_nameof(H5A_t *attr)
1343
0
{
1344
0
    H5G_name_t *ret_value = NULL; /* Return value */
1345
1346
0
    FUNC_ENTER_NOAPI_NOERR
1347
1348
0
    assert(attr);
1349
1350
    /* Set return value */
1351
0
    ret_value = &(attr->path);
1352
1353
0
    FUNC_LEAVE_NOAPI(ret_value)
1354
0
} /* end H5A_nameof() */
1355
1356
/*-------------------------------------------------------------------------
1357
 * Function:    H5A_type
1358
 *
1359
 * Purpose:     Return the datatype for an attribute.
1360
 *
1361
 * Return:      Success:        Ptr to entry
1362
 *              Failure:        NULL
1363
 *
1364
 *-------------------------------------------------------------------------
1365
 */
1366
H5T_t *
1367
H5A_type(const H5A_t *attr)
1368
0
{
1369
0
    H5T_t *ret_value = NULL; /* Return value */
1370
1371
0
    FUNC_ENTER_NOAPI_NOERR
1372
1373
0
    assert(attr);
1374
1375
    /* Set return value */
1376
0
    ret_value = attr->shared->dt;
1377
1378
0
    FUNC_LEAVE_NOAPI(ret_value)
1379
0
} /* end H5A_type() */
1380
1381
/*-------------------------------------------------------------------------
1382
 * Function:    H5A__exists_by_name
1383
 *
1384
 * Purpose:     Private version of H5Aexists_by_name
1385
 *
1386
 * Return:      true/false/FAIL
1387
 *
1388
 *-------------------------------------------------------------------------
1389
 */
1390
herr_t
1391
H5A__exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name, bool *attr_exists)
1392
107
{
1393
107
    H5G_loc_t  obj_loc;             /* Location used to open group */
1394
107
    H5G_name_t obj_path;            /* Opened object group hier. path */
1395
107
    H5O_loc_t  obj_oloc;            /* Opened object object location */
1396
107
    bool       loc_found = false;   /* Entry at 'obj_name' found */
1397
107
    herr_t     ret_value = SUCCEED; /* Return value */
1398
1399
107
    FUNC_ENTER_PACKAGE
1400
1401
    /* Sanity check */
1402
107
    assert(obj_name);
1403
107
    assert(attr_name);
1404
107
    assert(attr_exists);
1405
1406
    /* Set up opened group location to fill in */
1407
107
    obj_loc.oloc = &obj_oloc;
1408
107
    obj_loc.path = &obj_path;
1409
107
    H5G_loc_reset(&obj_loc);
1410
1411
    /* Find the object's location */
1412
107
    if (H5G_loc_find(&loc, obj_name, &obj_loc /*out*/) < 0)
1413
0
        HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found");
1414
107
    loc_found = true;
1415
1416
    /* Check if the attribute exists */
1417
107
    if (H5O__attr_exists(obj_loc.oloc, attr_name, attr_exists) < 0)
1418
12
        HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists");
1419
1420
107
done:
1421
    /* Release resources */
1422
107
    if (loc_found && H5G_loc_free(&obj_loc) < 0)
1423
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location");
1424
1425
107
    FUNC_LEAVE_NOAPI(ret_value)
1426
107
} /* H5A__exists_by_name() */
1427
1428
/*-------------------------------------------------------------------------
1429
 * Function:    H5A__compact_build_table_cb
1430
 *
1431
 * Purpose:    Object header iterator callback routine to copy attribute
1432
 *              into table.
1433
 *
1434
 * Return:    Non-negative on success/Negative on failure
1435
 *-------------------------------------------------------------------------
1436
 */
1437
static herr_t
1438
H5A__compact_build_table_cb(H5O_t H5_ATTR_UNUSED *oh, H5O_mesg_t *mesg /*in,out*/, unsigned sequence,
1439
                            unsigned H5_ATTR_UNUSED *oh_modified, void *_udata /*in,out*/)
1440
0
{
1441
0
    H5A_compact_bt_ud_t *udata     = (H5A_compact_bt_ud_t *)_udata; /* Operator user data */
1442
0
    herr_t               ret_value = H5_ITER_CONT;                  /* Return value */
1443
1444
0
    FUNC_ENTER_PACKAGE
1445
1446
    /* check args */
1447
0
    assert(mesg);
1448
1449
    /* Re-allocate the table if necessary */
1450
0
    if (udata->atable->num_attrs == udata->atable->max_attrs) {
1451
0
        H5A_t **new_table;      /* New table for attributes */
1452
0
        size_t  new_table_size; /* Number of attributes in new table */
1453
1454
        /* Allocate larger table */
1455
0
        new_table_size = MAX(1, 2 * udata->atable->max_attrs);
1456
0
        if (NULL == (new_table = (H5A_t **)H5FL_SEQ_REALLOC(H5A_t_ptr, udata->atable->attrs, new_table_size)))
1457
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "unable to extend attribute table");
1458
1459
        /* Update table information in user data */
1460
0
        udata->atable->attrs     = new_table;
1461
0
        udata->atable->max_attrs = new_table_size;
1462
0
    } /* end if */
1463
1464
    /* Copy attribute into table */
1465
0
    if (NULL ==
1466
0
        (udata->atable->attrs[udata->atable->num_attrs] = H5A__copy(NULL, (const H5A_t *)mesg->native)))
1467
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute");
1468
1469
    /* Assign [somewhat arbitrary] creation order value, if requested */
1470
0
    if (udata->bogus_crt_idx)
1471
0
        ((udata->atable->attrs[udata->atable->num_attrs])->shared)->crt_idx = sequence;
1472
1473
    /* Increment attribute count */
1474
0
    udata->atable->num_attrs++;
1475
1476
0
done:
1477
0
    FUNC_LEAVE_NOAPI(ret_value)
1478
0
} /* end H5A__compact_build_table_cb() */
1479
1480
/*-------------------------------------------------------------------------
1481
 * Function:    H5A__compact_build_table
1482
 *
1483
 * Purpose:     Builds a table containing a sorted list of attributes for
1484
 *              an object
1485
 *
1486
 * Note:        Used for building table of attributes in non-native iteration
1487
 *              order for an index
1488
 *
1489
 * Return:      SUCCEED/FAIL
1490
 *
1491
 *-------------------------------------------------------------------------
1492
 */
1493
herr_t
1494
H5A__compact_build_table(H5F_t *f, H5O_t *oh, H5_index_t idx_type, H5_iter_order_t order,
1495
                         H5A_attr_table_t *atable)
1496
0
{
1497
0
    H5A_compact_bt_ud_t udata;                 /* User data for iteration callback */
1498
0
    H5O_mesg_operator_t op;                    /* Wrapper for operator */
1499
0
    bool                iter_set_up = false;   /* Is everything set up for iteration */
1500
0
    herr_t              ret_value   = SUCCEED; /* Return value */
1501
1502
0
    FUNC_ENTER_PACKAGE
1503
1504
    /* Sanity check */
1505
0
    assert(f);
1506
0
    assert(oh);
1507
0
    assert(atable);
1508
1509
    /* Initialize table */
1510
0
    atable->attrs     = NULL;
1511
0
    atable->num_attrs = 0;
1512
0
    atable->max_attrs = 0;
1513
1514
    /* Set up user data for iteration */
1515
0
    udata.f      = f;
1516
0
    udata.atable = atable;
1517
0
    udata.bogus_crt_idx =
1518
0
        (bool)((oh->version == H5O_VERSION_1 || !(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)) ? true
1519
0
                                                                                               : false);
1520
1521
    /* Iterate over existing attributes, checking for attribute with same name */
1522
0
    op.op_type  = H5O_MESG_OP_LIB;
1523
0
    op.u.lib_op = H5A__compact_build_table_cb;
1524
0
    iter_set_up = true;
1525
0
    if (H5O__msg_iterate_real(f, oh, H5O_MSG_ATTR, &op, &udata) < 0)
1526
0
        HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error building attribute table");
1527
1528
    /* Don't sort an empty table. */
1529
0
    if (atable->num_attrs > 0)
1530
        /* Sort attribute table in correct iteration order */
1531
0
        if (H5A__attr_sort_table(atable, idx_type, order) < 0)
1532
0
            HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table");
1533
1534
0
done:
1535
0
    if (ret_value < 0)
1536
        /* Clean up partially built table on error */
1537
0
        if (iter_set_up)
1538
0
            if (atable->attrs && H5A__attr_release_table(atable) < 0)
1539
0
                HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table");
1540
1541
0
    FUNC_LEAVE_NOAPI(ret_value)
1542
0
} /* end H5A__compact_build_table() */
1543
1544
/*-------------------------------------------------------------------------
1545
 * Function:    H5A__dense_build_table_cb
1546
 *
1547
 * Purpose:    Callback routine for building table of attributes from dense
1548
 *              attribute storage.
1549
 *
1550
 * Return:      SUCCEED/FAIL
1551
 *
1552
 *-------------------------------------------------------------------------
1553
 */
1554
static herr_t
1555
H5A__dense_build_table_cb(const H5A_t *attr, void *_udata)
1556
0
{
1557
0
    H5A_attr_table_t *atable    = (H5A_attr_table_t *)_udata; /* 'User data' passed in */
1558
0
    herr_t            ret_value = H5_ITER_CONT;               /* Return value */
1559
1560
0
    FUNC_ENTER_PACKAGE
1561
1562
    /* check arguments */
1563
0
    assert(attr);
1564
0
    assert(atable);
1565
0
    assert(atable->num_attrs < atable->max_attrs);
1566
1567
    /* Allocate attribute for entry in the table */
1568
0
    if (NULL == (atable->attrs[atable->num_attrs] = H5FL_CALLOC(H5A_t)))
1569
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, H5_ITER_ERROR, "can't allocate attribute");
1570
1571
    /* Copy attribute information.  Share the attribute object in copying. */
1572
0
    if (NULL == H5A__copy(atable->attrs[atable->num_attrs], attr))
1573
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute");
1574
1575
    /* Increment number of attributes stored */
1576
0
    atable->num_attrs++;
1577
1578
0
done:
1579
0
    FUNC_LEAVE_NOAPI(ret_value)
1580
0
} /* end H5A__dense_build_table_cb() */
1581
1582
/*-------------------------------------------------------------------------
1583
 * Function:    H5A__dense_build_table
1584
 *
1585
 * Purpose:     Builds a table containing a sorted list of attributes for
1586
 *              an object
1587
 *
1588
 * Note:        Used for building table of attributes in non-native iteration
1589
 *              order for an index.  Uses the "name" index to retrieve records,
1590
 *              but the 'idx_type' index for sorting them.
1591
 *
1592
 * Return:      SUCCEED/FAIL
1593
 *
1594
 *-------------------------------------------------------------------------
1595
 */
1596
herr_t
1597
H5A__dense_build_table(H5F_t *f, const H5O_ainfo_t *ainfo, H5_index_t idx_type, H5_iter_order_t order,
1598
                       H5A_attr_table_t *atable)
1599
0
{
1600
0
    H5B2_t *bt2_name = NULL;     /* v2 B-tree handle for name index */
1601
0
    hsize_t nrec;                /* # of records in v2 B-tree */
1602
0
    herr_t  ret_value = SUCCEED; /* Return value */
1603
1604
0
    FUNC_ENTER_PACKAGE
1605
1606
    /* Sanity check */
1607
0
    assert(f);
1608
0
    assert(ainfo);
1609
0
    assert(H5_addr_defined(ainfo->fheap_addr));
1610
0
    assert(H5_addr_defined(ainfo->name_bt2_addr));
1611
0
    assert(atable);
1612
1613
    /* Open the name index v2 B-tree */
1614
0
    if (NULL == (bt2_name = H5B2_open(f, ainfo->name_bt2_addr, NULL)))
1615
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index");
1616
1617
    /* Retrieve # of records in "name" B-tree */
1618
    /* (should be same # of records in all indices) */
1619
0
    if (H5B2_get_nrec(bt2_name, &nrec) < 0)
1620
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index");
1621
1622
    /* Allocate space for the table entries */
1623
0
    if (nrec > 0) {
1624
0
        H5A_attr_iter_op_t attr_op; /* Attribute operator */
1625
1626
        /* Check for overflow on the downcast */
1627
0
        H5_CHECK_OVERFLOW(nrec, /* From: */ hsize_t, /* To: */ size_t);
1628
1629
        /* Allocate the table to store the attributes */
1630
0
        if (NULL == (atable->attrs = (H5A_t **)H5FL_SEQ_CALLOC(H5A_t_ptr, (size_t)nrec)))
1631
0
            HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed");
1632
0
        atable->num_attrs = 0;
1633
0
        atable->max_attrs = (size_t)nrec;
1634
1635
        /* Build iterator operator */
1636
0
        attr_op.op_type  = H5A_ATTR_OP_LIB;
1637
0
        attr_op.u.lib_op = H5A__dense_build_table_cb;
1638
1639
        /* Iterate over the links in the group, building a table of the link messages */
1640
0
        if (H5A__dense_iterate(f, (hid_t)0, ainfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, &attr_op,
1641
0
                               atable) < 0)
1642
0
            HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table");
1643
1644
        /* Sort attribute table in correct iteration order */
1645
0
        if (H5A__attr_sort_table(atable, idx_type, order) < 0)
1646
0
            HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table");
1647
0
    } /* end if */
1648
0
    else
1649
0
        atable->attrs = NULL;
1650
1651
0
done:
1652
    /* Release resources */
1653
0
    if (bt2_name && H5B2_close(bt2_name) < 0)
1654
0
        HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index");
1655
1656
0
    FUNC_LEAVE_NOAPI(ret_value)
1657
0
} /* end H5A__dense_build_table() */
1658
1659
/*-------------------------------------------------------------------------
1660
 * Function:    H5A__attr_cmp_name_inc
1661
 *
1662
 * Purpose:     Callback routine for comparing two attribute names, in
1663
 *              increasing alphabetic order
1664
 *
1665
 * Return:      An integer less than, equal to, or greater than zero if the
1666
 *              first argument is considered to be respectively less than,
1667
 *              equal to, or greater than the second.  If two members compare
1668
 *              as equal, their order in the sorted array is undefined.
1669
 *              (i.e. same as strcmp())
1670
 *
1671
 *-------------------------------------------------------------------------
1672
 */
1673
static int
1674
H5A__attr_cmp_name_inc(const void *attr1, const void *attr2)
1675
0
{
1676
0
    FUNC_ENTER_PACKAGE_NOERR
1677
1678
0
    FUNC_LEAVE_NOAPI(
1679
0
        strcmp((*(const H5A_t *const *)attr1)->shared->name, (*(const H5A_t *const *)attr2)->shared->name))
1680
0
} /* end H5A__attr_cmp_name_inc() */
1681
1682
/*-------------------------------------------------------------------------
1683
 * Function:    H5A__attr_cmp_name_dec
1684
 *
1685
 * Purpose:    Callback routine for comparing two attribute names, in
1686
 *              decreasing alphabetic order
1687
 *
1688
 * Return:    An integer less than, equal to, or greater than zero if the
1689
 *              second argument is considered to be respectively less than,
1690
 *              equal to, or greater than the first.  If two members compare
1691
 *              as equal, their order in the sorted array is undefined.
1692
 *              (i.e. opposite of strcmp())
1693
 *
1694
 *-------------------------------------------------------------------------
1695
 */
1696
static int
1697
H5A__attr_cmp_name_dec(const void *attr1, const void *attr2)
1698
0
{
1699
0
    FUNC_ENTER_PACKAGE_NOERR
1700
1701
0
    FUNC_LEAVE_NOAPI(
1702
0
        strcmp((*(const H5A_t *const *)attr2)->shared->name, (*(const H5A_t *const *)attr1)->shared->name))
1703
0
} /* end H5A__attr_cmp_name_dec() */
1704
1705
/*-------------------------------------------------------------------------
1706
 * Function:    H5A__attr_cmp_corder_inc
1707
 *
1708
 * Purpose:    Callback routine for comparing two attributes, in
1709
 *              increasing creation order
1710
 *
1711
 * Return:    An integer less than, equal to, or greater than zero if the
1712
 *              first argument is considered to be respectively less than,
1713
 *              equal to, or greater than the second.  If two members compare
1714
 *              as equal, their order in the sorted array is undefined.
1715
 *
1716
 *-------------------------------------------------------------------------
1717
 */
1718
static int
1719
H5A__attr_cmp_corder_inc(const void *attr1, const void *attr2)
1720
0
{
1721
0
    int ret_value = 0; /* Return value */
1722
1723
0
    FUNC_ENTER_PACKAGE_NOERR
1724
1725
0
    if ((*(const H5A_t *const *)attr1)->shared->crt_idx < (*(const H5A_t *const *)attr2)->shared->crt_idx)
1726
0
        ret_value = -1;
1727
0
    else if ((*(const H5A_t *const *)attr1)->shared->crt_idx >
1728
0
             (*(const H5A_t *const *)attr2)->shared->crt_idx)
1729
0
        ret_value = 1;
1730
0
    else
1731
0
        ret_value = 0;
1732
1733
0
    FUNC_LEAVE_NOAPI(ret_value)
1734
0
} /* end H5A__attr_cmp_corder_inc() */
1735
1736
/*-------------------------------------------------------------------------
1737
 * Function:    H5A__attr_cmp_corder_dec
1738
 *
1739
 * Purpose:     Callback routine for comparing two attributes, in
1740
 *              decreasing creation order
1741
 *
1742
 * Return:      An integer less than, equal to, or greater than zero if the
1743
 *              second argument is considered to be respectively less than,
1744
 *              equal to, or greater than the first.  If two members compare
1745
 *              as equal, their order in the sorted array is undefined.
1746
 *
1747
 *-------------------------------------------------------------------------
1748
 */
1749
static int
1750
H5A__attr_cmp_corder_dec(const void *attr1, const void *attr2)
1751
0
{
1752
0
    int ret_value = 0; /* Return value */
1753
1754
0
    FUNC_ENTER_PACKAGE_NOERR
1755
1756
0
    if ((*(const H5A_t *const *)attr1)->shared->crt_idx < (*(const H5A_t *const *)attr2)->shared->crt_idx)
1757
0
        ret_value = 1;
1758
0
    else if ((*(const H5A_t *const *)attr1)->shared->crt_idx >
1759
0
             (*(const H5A_t *const *)attr2)->shared->crt_idx)
1760
0
        ret_value = -1;
1761
0
    else
1762
0
        ret_value = 0;
1763
1764
0
    FUNC_LEAVE_NOAPI(ret_value)
1765
0
} /* end H5A__attr_cmp_corder_dec() */
1766
1767
/*-------------------------------------------------------------------------
1768
 * Function:    H5A__attr_sort_table
1769
 *
1770
 * Purpose:     Sort table containing a list of attributes for an object
1771
 *
1772
 * Return:      SUCCEED/FAIL
1773
 *
1774
 *-------------------------------------------------------------------------
1775
 */
1776
static herr_t
1777
H5A__attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type, H5_iter_order_t order)
1778
0
{
1779
0
    FUNC_ENTER_PACKAGE_NOERR
1780
1781
    /* Sanity check */
1782
0
    assert(atable);
1783
1784
    /* Pick appropriate comparison routine */
1785
0
    if (idx_type == H5_INDEX_NAME) {
1786
0
        if (order == H5_ITER_INC)
1787
0
            qsort(atable->attrs, atable->num_attrs, sizeof(H5A_t *), H5A__attr_cmp_name_inc);
1788
0
        else if (order == H5_ITER_DEC)
1789
0
            qsort(atable->attrs, atable->num_attrs, sizeof(H5A_t *), H5A__attr_cmp_name_dec);
1790
0
        else
1791
0
            assert(order == H5_ITER_NATIVE);
1792
0
    } /* end if */
1793
0
    else {
1794
0
        assert(idx_type == H5_INDEX_CRT_ORDER);
1795
0
        if (order == H5_ITER_INC)
1796
0
            qsort(atable->attrs, atable->num_attrs, sizeof(H5A_t *), H5A__attr_cmp_corder_inc);
1797
0
        else if (order == H5_ITER_DEC)
1798
0
            qsort(atable->attrs, atable->num_attrs, sizeof(H5A_t *), H5A__attr_cmp_corder_dec);
1799
0
        else
1800
0
            assert(order == H5_ITER_NATIVE);
1801
0
    } /* end else */
1802
1803
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1804
0
} /* end H5A__attr_sort_table() */
1805
1806
/*-------------------------------------------------------------------------
1807
 * Function:    H5A__attr_iterate_table
1808
 *
1809
 * Purpose:     Iterate over table containing a list of attributes for an object,
1810
 *              making appropriate callbacks
1811
 *
1812
 * Return:      SUCCEED/FAIL
1813
 *
1814
 *-------------------------------------------------------------------------
1815
 */
1816
herr_t
1817
H5A__attr_iterate_table(const H5A_attr_table_t *atable, hsize_t skip, hsize_t *last_attr, hid_t loc_id,
1818
                        const H5A_attr_iter_op_t *attr_op, void *op_data)
1819
0
{
1820
0
    size_t u;                        /* Local index variable */
1821
0
    herr_t ret_value = H5_ITER_CONT; /* Return value */
1822
1823
0
    FUNC_ENTER_PACKAGE
1824
1825
    /* Sanity check */
1826
0
    assert(atable);
1827
0
    assert(attr_op);
1828
1829
    /* Skip over attributes, if requested */
1830
0
    if (last_attr)
1831
0
        *last_attr = skip;
1832
1833
    /* Iterate over attribute messages */
1834
0
    H5_CHECKED_ASSIGN(u, size_t, skip, hsize_t);
1835
0
    for (; u < atable->num_attrs && !ret_value; u++) {
1836
        /* Check which type of callback to make */
1837
0
        switch (attr_op->op_type) {
1838
0
            case H5A_ATTR_OP_APP2: {
1839
0
                H5A_info_t ainfo; /* Info for attribute */
1840
1841
                /* Get the attribute information */
1842
0
                if (H5A__get_info(atable->attrs[u], &ainfo) < 0)
1843
0
                    HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, H5_ITER_ERROR, "unable to get attribute info");
1844
1845
                /* Make the application callback */
1846
0
                ret_value = (attr_op->u.app_op2)(loc_id, ((atable->attrs[u])->shared)->name, &ainfo, op_data);
1847
0
                break;
1848
0
            }
1849
1850
#ifndef H5_NO_DEPRECATED_SYMBOLS
1851
            case H5A_ATTR_OP_APP:
1852
                /* Make the application callback */
1853
                ret_value = (attr_op->u.app_op)(loc_id, ((atable->attrs[u])->shared)->name, op_data);
1854
                break;
1855
#endif /* H5_NO_DEPRECATED_SYMBOLS */
1856
1857
0
            case H5A_ATTR_OP_LIB:
1858
                /* Call the library's callback */
1859
0
                ret_value = (attr_op->u.lib_op)((atable->attrs[u]), op_data);
1860
0
                break;
1861
1862
0
            default:
1863
0
                assert("unknown attribute op type" && 0);
1864
0
#ifdef NDEBUG
1865
0
                HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unsupported attribute op type");
1866
0
#endif    /* NDEBUG */
1867
0
        } /* end switch */
1868
1869
        /* Increment the number of entries passed through */
1870
0
        if (last_attr)
1871
0
            (*last_attr)++;
1872
0
    } /* end for */
1873
1874
    /* Check for callback failure and pass along return value */
1875
0
    if (ret_value < 0)
1876
0
        HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
1877
1878
0
done:
1879
0
    FUNC_LEAVE_NOAPI(ret_value)
1880
0
} /* end H5A__attr_iterate_table() */
1881
1882
/*-------------------------------------------------------------------------
1883
 * Function:    H5A__attr_release_table
1884
 *
1885
 * Purpose:     Release table containing a list of attributes for an object
1886
 *
1887
 * Return:      SUCCEED/FAIL
1888
 *
1889
 *-------------------------------------------------------------------------
1890
 */
1891
herr_t
1892
H5A__attr_release_table(H5A_attr_table_t *atable)
1893
0
{
1894
0
    herr_t ret_value = SUCCEED; /* Return value */
1895
1896
0
    FUNC_ENTER_PACKAGE
1897
1898
    /* Sanity check */
1899
0
    assert(atable);
1900
1901
    /* Release attribute info, if any. */
1902
0
    if (atable->num_attrs > 0) {
1903
0
        size_t u; /* Local index variable */
1904
1905
        /* Free attribute message information */
1906
0
        for (u = 0; u < atable->num_attrs; u++)
1907
0
            if (atable->attrs[u] && H5A__close(atable->attrs[u]) < 0)
1908
0
                HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute");
1909
1910
        /* Release array */
1911
0
        atable->attrs = (H5A_t **)H5FL_SEQ_FREE(H5A_t_ptr, atable->attrs);
1912
0
    } /* end if */
1913
0
    else
1914
0
        assert(atable->attrs == NULL);
1915
1916
0
done:
1917
0
    FUNC_LEAVE_NOAPI(ret_value)
1918
0
} /* end H5A__attr_release_table() */
1919
1920
/*-------------------------------------------------------------------------
1921
 * Function:    H5A__get_ainfo
1922
 *
1923
 * Purpose:     Retrieves the "attribute info" message for an object.  Also
1924
 *              sets the number of attributes correctly, if it isn't set up yet.
1925
 *
1926
 * Return:      true/false/FAIL
1927
 *
1928
 *-------------------------------------------------------------------------
1929
 */
1930
htri_t
1931
H5A__get_ainfo(H5F_t *f, H5O_t *oh, H5O_ainfo_t *ainfo)
1932
0
{
1933
0
    H5B2_t *bt2_name  = NULL; /* v2 B-tree handle for name index */
1934
0
    htri_t  ret_value = FAIL; /* Return value */
1935
1936
0
    FUNC_ENTER_NOAPI_TAG(oh->cache_info.addr, FAIL)
1937
1938
    /* check arguments */
1939
0
    assert(f);
1940
0
    assert(oh);
1941
0
    assert(ainfo);
1942
1943
    /* Check if the "attribute info" message exists */
1944
0
    if ((ret_value = H5O_msg_exists_oh(oh, H5O_AINFO_ID)) < 0)
1945
0
        HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "unable to check object header");
1946
0
    if (ret_value > 0) {
1947
        /* Retrieve the "attribute info" structure */
1948
0
        if (NULL == H5O_msg_read_oh(f, oh, H5O_AINFO_ID, ainfo))
1949
0
            HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't read AINFO message");
1950
1951
        /* Check if we don't know how many attributes there are */
1952
0
        if (ainfo->nattrs == HSIZET_MAX) {
1953
            /* Check if we are using "dense" attribute storage */
1954
0
            if (H5_addr_defined(ainfo->fheap_addr)) {
1955
                /* Open the name index v2 B-tree */
1956
0
                if (NULL == (bt2_name = H5B2_open(f, ainfo->name_bt2_addr, NULL)))
1957
0
                    HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index");
1958
1959
                /* Retrieve # of records in "name" B-tree */
1960
                /* (should be same # of records in all indices) */
1961
0
                if (H5B2_get_nrec(bt2_name, &ainfo->nattrs) < 0)
1962
0
                    HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index");
1963
0
            } /* end if */
1964
0
            else
1965
                /* Retrieve # of attributes from object header */
1966
0
                ainfo->nattrs = oh->attr_msgs_seen;
1967
0
        } /* end if */
1968
0
    }     /* end if */
1969
1970
0
done:
1971
    /* Release resources */
1972
0
    if (bt2_name && H5B2_close(bt2_name) < 0)
1973
0
        HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index");
1974
1975
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
1976
0
} /* end H5A__get_ainfo() */
1977
1978
/*-------------------------------------------------------------------------
1979
 * Function:    H5A__set_version
1980
 *
1981
 * Purpose:     Sets the correct version to encode attribute with.
1982
 *              Chooses the oldest version possible, unless the
1983
 *              file's low bound indicates otherwise.
1984
 *
1985
 * Return:      SUCCEED/FAIL
1986
 *
1987
 *-------------------------------------------------------------------------
1988
 */
1989
herr_t
1990
H5A__set_version(const H5F_t *f, H5A_t *attr)
1991
0
{
1992
0
    bool type_shared, space_shared; /* Flags to indicate that shared messages are used for this attribute */
1993
0
    uint8_t version;                /* Message version */
1994
0
    herr_t  ret_value = SUCCEED;    /* Return value */
1995
1996
0
    FUNC_ENTER_PACKAGE
1997
1998
    /* check arguments */
1999
0
    assert(f);
2000
0
    assert(attr);
2001
2002
    /* Check whether datatype and dataspace are shared */
2003
0
    if (H5O_msg_is_shared(H5O_DTYPE_ID, attr->shared->dt) > 0)
2004
0
        type_shared = true;
2005
0
    else
2006
0
        type_shared = false;
2007
2008
0
    if (H5O_msg_is_shared(H5O_SDSPACE_ID, attr->shared->ds) > 0)
2009
0
        space_shared = true;
2010
0
    else
2011
0
        space_shared = false;
2012
2013
    /* Check which version to encode attribute with */
2014
0
    if (attr->shared->encoding != H5T_CSET_ASCII)
2015
0
        version = H5O_ATTR_VERSION_3; /* Write version which includes the character encoding */
2016
0
    else if (type_shared || space_shared)
2017
0
        version =
2018
0
            H5O_ATTR_VERSION_2; /* Write out version with flag for indicating shared datatype or dataspace */
2019
0
    else
2020
0
        version = H5O_ATTR_VERSION_1; /* Write out basic version */
2021
2022
    /* Upgrade to the version indicated by the file's low bound if higher */
2023
0
    version = (uint8_t)MAX(version, (uint8_t)H5O_attr_ver_bounds[H5F_LOW_BOUND(f)]);
2024
2025
    /* Version bounds check */
2026
0
    if (version > H5O_attr_ver_bounds[H5F_HIGH_BOUND(f)])
2027
0
        HGOTO_ERROR(H5E_ATTR, H5E_BADRANGE, FAIL, "attribute version out of bounds");
2028
2029
    /* Set the message version */
2030
0
    attr->shared->version = version;
2031
2032
0
done:
2033
0
    FUNC_LEAVE_NOAPI(ret_value)
2034
0
} /* end H5A__set_version() */
2035
2036
/*-------------------------------------------------------------------------
2037
 * Function:    H5A__attr_copy_file
2038
 *
2039
 * Purpose:     Copies a message from _MESG to _DEST in file
2040
 *
2041
 *              Note that this function assumes that it is copying *all*
2042
 *              the attributes in the object, specifically when it copies
2043
 *              the creation order from source to destination.  If this is
2044
 *              to be used to copy only a single attribute, then the
2045
 *              creation order must be handled differently.  -NAF
2046
 *
2047
 * Return:      Success:        Ptr to _DEST
2048
 *
2049
 *              Failure:        NULL
2050
 *
2051
 *-------------------------------------------------------------------------
2052
 */
2053
H5A_t *
2054
H5A__attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, bool *recompute_size,
2055
                    H5O_copy_t H5_ATTR_NDEBUG_UNUSED *cpy_info)
2056
0
{
2057
0
    H5A_t   *attr_dst    = NULL; /* Destination attribute */
2058
0
    H5T_t   *dt_mem      = NULL; /* Memory datatype */
2059
0
    H5S_t   *buf_space   = NULL; /* Dataspace describing buffer */
2060
0
    void    *buf         = NULL; /* Buffer for copying data */
2061
0
    void    *reclaim_buf = NULL; /* Buffer for reclaiming data */
2062
0
    void    *bkg_buf     = NULL; /* Background buffer */
2063
0
    hssize_t sdst_nelmts;        /* # of elements in destination attribute (signed) */
2064
0
    size_t   dst_nelmts;         /* # of elements in destination attribute */
2065
0
    size_t   dst_dt_size;        /* Size of destination attribute datatype */
2066
0
    H5A_t   *ret_value = NULL;   /* Return value */
2067
2068
0
    FUNC_ENTER_PACKAGE
2069
2070
    /* check args */
2071
0
    assert(attr_src);
2072
0
    assert(file_dst);
2073
0
    assert(cpy_info);
2074
0
    assert(!cpy_info->copy_without_attr);
2075
2076
    /* Allocate space for the destination message */
2077
0
    if (NULL == (attr_dst = H5FL_CALLOC(H5A_t)))
2078
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
2079
2080
    /* Copy the top level of the attribute */
2081
0
    *attr_dst = *attr_src;
2082
2083
0
    if (NULL == (attr_dst->shared = H5FL_CALLOC(H5A_shared_t)))
2084
0
        HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared attr structure");
2085
2086
    /* Don't have an opened group location for copy */
2087
0
    H5O_loc_reset(&(attr_dst->oloc));
2088
0
    H5G_name_reset(&(attr_dst->path));
2089
0
    attr_dst->obj_opened = false;
2090
2091
    /* Reference count for the header message in the cache */
2092
0
    attr_dst->shared->nrefs = 1;
2093
2094
    /* Copy attribute's name */
2095
0
    attr_dst->shared->name = H5MM_strdup(attr_src->shared->name);
2096
0
    assert(attr_dst->shared->name);
2097
0
    attr_dst->shared->encoding = attr_src->shared->encoding;
2098
2099
    /* Copy attribute's datatype */
2100
    /* If source is named, we will keep dst as named, but we will not actually
2101
     * copy the target and update the message until post copy */
2102
0
    if (NULL == (attr_dst->shared->dt = H5T_copy(attr_src->shared->dt, H5T_COPY_ALL)))
2103
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "cannot copy datatype");
2104
2105
    /* Set the location of the destination datatype */
2106
0
    if (H5T_set_loc(attr_dst->shared->dt, H5F_VOL_OBJ(file_dst), H5T_LOC_DISK) < 0)
2107
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "cannot mark datatype on disk");
2108
2109
0
    if (!H5T_is_named(attr_src->shared->dt)) {
2110
        /* If the datatype is not named, it may have been shared in the
2111
         * source file's heap.  Un-share it for now. We'll try to shared
2112
         * it in the destination file below.
2113
         */
2114
0
        if (H5O_msg_reset_share(H5O_DTYPE_ID, attr_dst->shared->dt) < 0)
2115
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset datatype sharing");
2116
0
    }
2117
2118
    /* Copy the dataspace for the attribute. Make sure the maximal dimension is also copied.
2119
     * Otherwise the comparison in the test may complain about it. SLU 2011/4/12 */
2120
0
    attr_dst->shared->ds = H5S_copy(attr_src->shared->ds, false, true);
2121
0
    assert(attr_dst->shared->ds);
2122
2123
    /* Reset the dataspace's sharing in the source file before trying to share
2124
     * it in the destination.
2125
     */
2126
0
    if (H5O_msg_reset_share(H5O_SDSPACE_ID, attr_dst->shared->ds) < 0)
2127
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset dataspace sharing");
2128
2129
    /* Simulate trying to share both the datatype and dataset, to determine the
2130
     * final size of the messages.  This does nothing if the datatype is
2131
     * committed or sharing is disabled.
2132
     */
2133
0
    if (H5SM_try_share(file_dst, NULL, H5SM_DEFER, H5O_DTYPE_ID, attr_dst->shared->dt, NULL) < 0)
2134
0
        HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute datatype");
2135
0
    if (H5SM_try_share(file_dst, NULL, H5SM_DEFER, H5O_SDSPACE_ID, attr_dst->shared->ds, NULL) < 0)
2136
0
        HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute dataspace");
2137
2138
    /* Compute the sizes of the datatype and dataspace. This is their raw
2139
     * size unless they're shared.
2140
     */
2141
0
    attr_dst->shared->dt_size = H5O_msg_raw_size(file_dst, H5O_DTYPE_ID, false, attr_dst->shared->dt);
2142
0
    assert(attr_dst->shared->dt_size > 0);
2143
0
    attr_dst->shared->ds_size = H5O_msg_raw_size(file_dst, H5O_SDSPACE_ID, false, attr_dst->shared->ds);
2144
0
    assert(attr_dst->shared->ds_size > 0);
2145
2146
    /* Check whether to recompute the size of the attribute */
2147
    /* (happens when the datatype or dataspace changes sharing status) */
2148
0
    if (attr_dst->shared->dt_size != attr_src->shared->dt_size ||
2149
0
        attr_dst->shared->ds_size != attr_src->shared->ds_size)
2150
0
        *recompute_size = true;
2151
2152
    /* Get # of elements for destination attribute's dataspace */
2153
0
    if ((sdst_nelmts = H5S_GET_EXTENT_NPOINTS(attr_dst->shared->ds)) < 0)
2154
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, NULL, "dataspace is invalid");
2155
0
    H5_CHECKED_ASSIGN(dst_nelmts, size_t, sdst_nelmts, hssize_t);
2156
2157
    /* Get size of destination attribute's datatype */
2158
0
    if (0 == (dst_dt_size = H5T_get_size(attr_dst->shared->dt)))
2159
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size");
2160
2161
    /* Compute the size of the data */
2162
0
    attr_dst->shared->data_size = dst_nelmts * dst_dt_size;
2163
2164
    /* Copy (& convert) the data, if necessary */
2165
0
    if (attr_src->shared->data) {
2166
0
        if (NULL == (attr_dst->shared->data = H5FL_BLK_MALLOC(attr_buf, attr_dst->shared->data_size)))
2167
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
2168
2169
        /* Check if we need to convert data */
2170
0
        if (H5T_detect_class(attr_src->shared->dt, H5T_VLEN, false) > 0) {
2171
0
            H5T_path_t *tpath_src_mem, *tpath_mem_dst; /* Datatype conversion paths */
2172
0
            size_t      src_dt_size;                   /* Source datatype size */
2173
0
            size_t      tmp_dt_size;                   /* Temp. datatype size */
2174
0
            size_t      max_dt_size;                   /* Max atatype size */
2175
0
            hsize_t     buf_dim;                       /* Dimension for buffer */
2176
0
            size_t      nelmts;                        /* Number of elements in buffer */
2177
0
            size_t      buf_size;                      /* Size of copy buffer */
2178
2179
            /* create a memory copy of the variable-length datatype */
2180
0
            if (NULL == (dt_mem = H5T_copy(attr_src->shared->dt, H5T_COPY_TRANSIENT)))
2181
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy");
2182
2183
            /* Set up the conversion functions */
2184
0
            if (NULL == (tpath_src_mem = H5T_path_find(attr_src->shared->dt, dt_mem)))
2185
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL,
2186
0
                            "unable to convert between src and mem datatypes");
2187
0
            if (NULL == (tpath_mem_dst = H5T_path_find(dt_mem, attr_dst->shared->dt)))
2188
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL,
2189
0
                            "unable to convert between mem and dst datatypes");
2190
2191
            /* Determine largest datatype size */
2192
0
            if (0 == (src_dt_size = H5T_get_size(attr_src->shared->dt)))
2193
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size");
2194
0
            if (0 == (tmp_dt_size = H5T_get_size(dt_mem)))
2195
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size");
2196
0
            max_dt_size = MAX(src_dt_size, tmp_dt_size);
2197
0
            if (0 == (tmp_dt_size = H5T_get_size(attr_dst->shared->dt)))
2198
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size");
2199
0
            max_dt_size = MAX(max_dt_size, tmp_dt_size);
2200
2201
            /* Set number of whole elements that fit in buffer */
2202
0
            if (0 == (nelmts = attr_src->shared->data_size / src_dt_size))
2203
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "element size too large");
2204
2205
            /* Set up number of bytes to copy, and initial buffer size */
2206
0
            buf_size = nelmts * max_dt_size;
2207
2208
            /* Create dataspace for number of elements in buffer */
2209
0
            buf_dim = nelmts;
2210
2211
            /* Create the space and set the initial extent */
2212
0
            if (NULL == (buf_space = H5S_create_simple((unsigned)1, &buf_dim, NULL)))
2213
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace");
2214
2215
            /* Allocate memory for recclaim buf */
2216
0
            if (NULL == (reclaim_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
2217
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk");
2218
2219
            /* Allocate memory for copying the chunk */
2220
0
            if (NULL == (buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
2221
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk");
2222
2223
0
            H5MM_memcpy(buf, attr_src->shared->data, attr_src->shared->data_size);
2224
2225
            /* Allocate background memory */
2226
0
            if (H5T_path_bkg(tpath_src_mem) || H5T_path_bkg(tpath_mem_dst))
2227
0
                if (NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
2228
0
                    HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "memory allocation failed");
2229
2230
            /* Convert from source file to memory */
2231
0
            if (H5T_convert(tpath_src_mem, attr_src->shared->dt, dt_mem, nelmts, (size_t)0, (size_t)0, buf,
2232
0
                            bkg_buf) < 0)
2233
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed");
2234
2235
0
            H5MM_memcpy(reclaim_buf, buf, buf_size);
2236
2237
            /* Set background buffer to all zeros */
2238
0
            if (bkg_buf)
2239
0
                memset(bkg_buf, 0, buf_size);
2240
2241
            /* Convert from memory to destination file */
2242
0
            if (H5T_convert(tpath_mem_dst, dt_mem, attr_dst->shared->dt, nelmts, (size_t)0, (size_t)0, buf,
2243
0
                            bkg_buf) < 0)
2244
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed");
2245
2246
0
            H5MM_memcpy(attr_dst->shared->data, buf, attr_dst->shared->data_size);
2247
2248
0
            if (H5T_reclaim(dt_mem, buf_space, reclaim_buf) < 0)
2249
0
                HGOTO_ERROR(H5E_DATASET, H5E_BADITER, NULL, "unable to reclaim variable-length data");
2250
0
        } /* end if */
2251
0
        else {
2252
0
            assert(attr_dst->shared->data_size == attr_src->shared->data_size);
2253
0
            H5MM_memcpy(attr_dst->shared->data, attr_src->shared->data, attr_src->shared->data_size);
2254
0
        } /* end else */
2255
0
    }     /* end if(attr_src->shared->data) */
2256
2257
    /* Copy the creation order */
2258
0
    attr_dst->shared->crt_idx = attr_src->shared->crt_idx;
2259
2260
    /* Recompute the version to encode the destination attribute */
2261
0
    if (H5A__set_version(file_dst, attr_dst) < 0)
2262
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version");
2263
2264
    /* Recompute the destination attribute's size, if it's a different version */
2265
0
    if (attr_src->shared->version != attr_dst->shared->version)
2266
0
        *recompute_size = true;
2267
2268
    /* Set return value */
2269
0
    ret_value = attr_dst;
2270
2271
0
done:
2272
0
    if (dt_mem && (H5T_close(dt_mem) < 0))
2273
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, NULL, "can't close temporary datatype");
2274
0
    if (buf_space && H5S_close(buf_space) < 0)
2275
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, NULL, "can't close temporary dataspace");
2276
0
    if (buf)
2277
0
        buf = H5FL_BLK_FREE(attr_buf, buf);
2278
0
    if (reclaim_buf)
2279
0
        reclaim_buf = H5FL_BLK_FREE(attr_buf, reclaim_buf);
2280
0
    if (bkg_buf)
2281
0
        bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
2282
2283
    /* Release destination attribute information on failure */
2284
0
    if (!ret_value && attr_dst && H5A__close(attr_dst) < 0)
2285
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute");
2286
2287
0
    FUNC_LEAVE_NOAPI(ret_value)
2288
0
} /* H5A__attr_copy_file() */
2289
2290
/*-------------------------------------------------------------------------
2291
 * Function:    H5A__attr_post_copy_file
2292
 *
2293
 * Purpose:     Finish copying a message from between files.
2294
 *              We have to copy the values of a reference attribute in the
2295
 *              post copy because H5O_post_copy_file() fails at the case that
2296
 *              an object may have a reference attribute that points to the
2297
 *              object itself.
2298
 *
2299
 * Return:      SUCCEED/FAIL
2300
 *
2301
 *-------------------------------------------------------------------------
2302
 */
2303
herr_t
2304
H5A__attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t *attr_src, H5O_loc_t *dst_oloc,
2305
                         const H5A_t *attr_dst, H5O_copy_t *cpy_info)
2306
0
{
2307
0
    H5F_t *file_src, *file_dst;
2308
0
    herr_t ret_value = SUCCEED; /* Return value */
2309
2310
0
    FUNC_ENTER_PACKAGE
2311
2312
    /* check args */
2313
0
    assert(src_oloc);
2314
0
    assert(dst_oloc);
2315
0
    assert(attr_dst);
2316
0
    assert(attr_src);
2317
2318
0
    file_src = src_oloc->file;
2319
0
    file_dst = dst_oloc->file;
2320
2321
0
    assert(file_src);
2322
0
    assert(file_dst);
2323
2324
0
    if (H5T_is_named(attr_src->shared->dt)) {
2325
0
        H5O_loc_t *src_oloc_dt; /* Pointer to source datatype's object location */
2326
0
        H5O_loc_t *dst_oloc_dt; /* Pointer to dest. datatype's object location */
2327
2328
        /* Get group entries for source & destination */
2329
0
        src_oloc_dt = H5T_oloc(attr_src->shared->dt);
2330
0
        assert(src_oloc_dt);
2331
0
        dst_oloc_dt = H5T_oloc(attr_dst->shared->dt);
2332
0
        assert(dst_oloc_dt);
2333
2334
        /* Reset object location for new object */
2335
0
        H5O_loc_reset(dst_oloc_dt);
2336
0
        dst_oloc_dt->file = file_dst;
2337
2338
        /* Copy the shared object from source to destination */
2339
0
        if (H5O_copy_header_map(src_oloc_dt, dst_oloc_dt, cpy_info, false, NULL, NULL) < 0)
2340
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object");
2341
2342
        /* Update shared message info from named datatype info */
2343
0
        H5T_update_shared(attr_dst->shared->dt);
2344
0
    }
2345
2346
    /* Try to share both the datatype and dataset.  This does nothing if the
2347
     * datatype is committed or sharing is disabled.
2348
     */
2349
0
    if (H5SM_try_share(file_dst, NULL, H5SM_WAS_DEFERRED, H5O_DTYPE_ID, attr_dst->shared->dt, NULL) < 0)
2350
0
        HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "can't share attribute datatype");
2351
0
    if (H5SM_try_share(file_dst, NULL, H5SM_WAS_DEFERRED, H5O_SDSPACE_ID, attr_dst->shared->ds, NULL) < 0)
2352
0
        HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "can't share attribute dataspace");
2353
2354
    /* Only need to fix reference attribute with real data being copied to
2355
     *  another file.
2356
     */
2357
0
    if ((NULL != attr_dst->shared->data) && (H5T_get_class(attr_dst->shared->dt, false) == H5T_REFERENCE)) {
2358
2359
        /* copy object pointed by reference. The current implementation does not
2360
         *  deal with nested reference such as reference in a compound structure
2361
         */
2362
2363
        /* Check for expanding references */
2364
0
        if (cpy_info->expand_ref) {
2365
            /* Copy objects referenced in source buffer to destination file and set destination elements */
2366
0
            if (H5O_copy_expand_ref(file_src, attr_src->shared->dt, attr_src->shared->data,
2367
0
                                    attr_src->shared->data_size, file_dst, attr_dst->shared->data,
2368
0
                                    cpy_info) < 0)
2369
0
                HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy reference attribute");
2370
0
        } /* end if */
2371
0
        else
2372
            /* Reset value to zero */
2373
0
            memset(attr_dst->shared->data, 0, attr_dst->shared->data_size);
2374
0
    } /* end if */
2375
2376
0
done:
2377
0
    FUNC_LEAVE_NOAPI(ret_value)
2378
0
} /* H5A__attr_post_copy_file() */
2379
2380
/*-------------------------------------------------------------------------
2381
 * Function:    H5A__dense_post_copy_file_cb
2382
 *
2383
 * Purpose:     Callback routine for copying a dense attribute from SRC to DST.
2384
 *
2385
 * Return:      Success:        Non-negative
2386
 *              Failure:        Negative
2387
 *
2388
 *-------------------------------------------------------------------------
2389
 */
2390
static herr_t
2391
H5A__dense_post_copy_file_cb(const H5A_t *attr_src, void *_udata)
2392
0
{
2393
0
    H5A_dense_file_cp_ud_t *udata     = (H5A_dense_file_cp_ud_t *)_udata;
2394
0
    H5A_t                  *attr_dst  = NULL;
2395
0
    herr_t                  ret_value = H5_ITER_CONT; /* Return value */
2396
2397
0
    FUNC_ENTER_PACKAGE
2398
2399
    /* check arguments */
2400
0
    assert(attr_src);
2401
0
    assert(udata);
2402
0
    assert(udata->ainfo);
2403
0
    assert(udata->file);
2404
0
    assert(udata->cpy_info);
2405
2406
    /* Set the location of the src datatype */
2407
0
    if (H5T_set_loc(attr_src->shared->dt, H5F_VOL_OBJ(udata->oloc_src->file), H5T_LOC_DISK) < 0)
2408
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "cannot mark datatype on disk");
2409
2410
0
    if (NULL ==
2411
0
        (attr_dst = H5A__attr_copy_file(attr_src, udata->file, udata->recompute_size, udata->cpy_info)))
2412
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute");
2413
2414
0
    if (H5A__attr_post_copy_file(udata->oloc_src, attr_src, udata->oloc_dst, attr_dst, udata->cpy_info) < 0)
2415
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute");
2416
2417
    /* Reset shared location information */
2418
0
    if (H5O_msg_reset_share(H5O_ATTR_ID, attr_dst) < 0)
2419
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, H5_ITER_ERROR, "unable to reset attribute sharing");
2420
2421
    /* Set COPIED tag for destination object's metadata */
2422
0
    H5_BEGIN_TAG(H5AC__COPIED_TAG)
2423
2424
    /* Insert attribute into dense storage */
2425
0
    if (H5A__dense_insert(udata->file, udata->ainfo, attr_dst) < 0)
2426
0
        HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage");
2427
2428
    /* Reset metadata tag */
2429
0
    H5_END_TAG
2430
2431
0
done:
2432
0
    if (attr_dst && H5A__close(attr_dst) < 0)
2433
0
        HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5_ITER_ERROR, "can't close destination attribute");
2434
2435
0
    FUNC_LEAVE_NOAPI(ret_value)
2436
0
} /* end H5A__dense_post_copy_file_cb() */
2437
2438
/*-------------------------------------------------------------------------
2439
 * Function:    H5A__dense_post_copy_file_all
2440
 *
2441
 * Purpose:     Copy all dense attributes from SRC to DST.
2442
 *
2443
 * Return:      SUCCEED/FAIL
2444
 *
2445
 *-------------------------------------------------------------------------
2446
 */
2447
herr_t
2448
H5A__dense_post_copy_file_all(const H5O_loc_t *src_oloc, const H5O_ainfo_t *ainfo_src, H5O_loc_t *dst_oloc,
2449
                              H5O_ainfo_t *ainfo_dst, H5O_copy_t *cpy_info)
2450
0
{
2451
0
    H5A_dense_file_cp_ud_t udata;                    /* User data for iteration callback */
2452
0
    H5A_attr_iter_op_t     attr_op;                  /* Attribute operator */
2453
0
    bool                   recompute_size = false;   /* recompute the size */
2454
0
    herr_t                 ret_value      = SUCCEED; /* Return value */
2455
2456
0
    FUNC_ENTER_PACKAGE
2457
2458
    /* check arguments */
2459
0
    assert(ainfo_src);
2460
0
    assert(ainfo_dst);
2461
2462
0
    udata.ainfo          = ainfo_dst;       /* Destination dense information    */
2463
0
    udata.file           = dst_oloc->file;  /* Destination file                 */
2464
0
    udata.recompute_size = &recompute_size; /* Flag to indicate if size changed */
2465
0
    udata.cpy_info       = cpy_info;        /* Information on copying options   */
2466
0
    udata.oloc_src       = src_oloc;
2467
0
    udata.oloc_dst       = dst_oloc;
2468
2469
0
    attr_op.op_type  = H5A_ATTR_OP_LIB;
2470
0
    attr_op.u.lib_op = H5A__dense_post_copy_file_cb;
2471
2472
0
    if (H5A__dense_iterate(src_oloc->file, (hid_t)0, ainfo_src, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0,
2473
0
                           NULL, &attr_op, &udata) < 0)
2474
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table");
2475
2476
0
done:
2477
0
    FUNC_LEAVE_NOAPI(ret_value)
2478
0
} /* end H5A__dense_post_copy_file_all */
2479
2480
/*-------------------------------------------------------------------------
2481
 * Function:    H5A__rename_by_name
2482
 *
2483
 * Purpose:     Private version of H5Arename_by_name
2484
 *
2485
 * Return:      SUCCEED/FAIL
2486
 *
2487
 *-------------------------------------------------------------------------
2488
 */
2489
herr_t
2490
H5A__rename_by_name(H5G_loc_t loc, const char *obj_name, const char *old_attr_name, const char *new_attr_name)
2491
0
{
2492
0
    H5G_loc_t  obj_loc;             /* Location used to open group */
2493
0
    H5G_name_t obj_path;            /* Opened object group hier. path */
2494
0
    H5O_loc_t  obj_oloc;            /* Opened object object location */
2495
0
    bool       loc_found = false;   /* Entry at 'obj_name' found */
2496
0
    herr_t     ret_value = SUCCEED; /* Return value */
2497
2498
0
    FUNC_ENTER_PACKAGE
2499
2500
    /* Avoid thrashing things if the names are the same */
2501
0
    if (strcmp(old_attr_name, new_attr_name) != 0) {
2502
        /* Set up opened group location to fill in */
2503
0
        obj_loc.oloc = &obj_oloc;
2504
0
        obj_loc.path = &obj_path;
2505
0
        H5G_loc_reset(&obj_loc);
2506
2507
        /* Find the object's location */
2508
0
        if (H5G_loc_find(&loc, obj_name, &obj_loc /*out*/) < 0)
2509
0
            HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found");
2510
0
        loc_found = true;
2511
2512
        /* Call attribute rename routine */
2513
0
        if (H5O__attr_rename(obj_loc.oloc, old_attr_name, new_attr_name) < 0)
2514
0
            HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute");
2515
0
    } /* end if */
2516
2517
0
done:
2518
    /* Release resources */
2519
0
    if (loc_found && H5G_loc_free(&obj_loc) < 0)
2520
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location");
2521
2522
0
    FUNC_LEAVE_NOAPI(ret_value)
2523
0
} /* H5A__rename_by_name() */
2524
2525
/*-------------------------------------------------------------------------
2526
 * Function:    H5A__iterate_common
2527
 *
2528
 * Purpose:     Internal common version of H5Aiterate
2529
 *
2530
 * Return:      SUCCEED/FAIL
2531
 *
2532
 *-------------------------------------------------------------------------
2533
 */
2534
static herr_t
2535
H5A__iterate_common(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx,
2536
                    H5A_attr_iter_op_t *attr_op, void *op_data)
2537
0
{
2538
0
    hsize_t start_idx;           /* Index of attribute to start iterating at */
2539
0
    hsize_t last_attr;           /* Index of last attribute examined */
2540
0
    herr_t  ret_value = SUCCEED; /* Return value */
2541
2542
0
    FUNC_ENTER_PACKAGE_NOERR
2543
2544
    /* Call attribute iteration routine */
2545
0
    last_attr = start_idx = (idx ? *idx : 0);
2546
0
    if ((ret_value = H5O__attr_iterate(loc_id, idx_type, order, start_idx, &last_attr, attr_op, op_data)) < 0)
2547
0
        HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
2548
2549
    /* Set the last attribute information */
2550
0
    if (idx)
2551
0
        *idx = last_attr;
2552
2553
0
    FUNC_LEAVE_NOAPI(ret_value)
2554
0
} /* H5A__iterate_common() */
2555
2556
/*-------------------------------------------------------------------------
2557
 * Function:    H5A__iterate
2558
 *
2559
 * Purpose:     Private version of H5Aiterate2
2560
 *
2561
 * Return:      SUCCEED/FAIL
2562
 *
2563
 *-------------------------------------------------------------------------
2564
 */
2565
herr_t
2566
H5A__iterate(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order,
2567
             hsize_t *idx, H5A_operator2_t op, void *op_data)
2568
0
{
2569
0
    H5G_loc_t          obj_loc;                      /* Location used to open group */
2570
0
    H5G_name_t         obj_path;                     /* Opened object group hier. path */
2571
0
    H5O_loc_t          obj_oloc;                     /* Opened object object location */
2572
0
    bool               loc_found  = false;           /* Entry at 'obj_name' found */
2573
0
    hid_t              obj_loc_id = H5I_INVALID_HID; /* ID for object located */
2574
0
    H5A_attr_iter_op_t attr_op;                      /* Attribute operator */
2575
0
    void              *temp_obj = NULL;
2576
0
    H5I_type_t         obj_type;
2577
0
    herr_t             ret_value = SUCCEED; /* Return value */
2578
2579
0
    FUNC_ENTER_PACKAGE
2580
2581
    /* Build attribute operator info */
2582
0
    attr_op.op_type   = H5A_ATTR_OP_APP2;
2583
0
    attr_op.u.app_op2 = op;
2584
2585
    /* Set up opened group location to fill in */
2586
0
    obj_loc.oloc = &obj_oloc;
2587
0
    obj_loc.path = &obj_path;
2588
0
    H5G_loc_reset(&obj_loc);
2589
2590
    /* Find the object's location */
2591
0
    if (H5G_loc_find(loc, obj_name, &obj_loc) < 0)
2592
0
        HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found");
2593
0
    loc_found = true;
2594
2595
    /* Open the object */
2596
0
    if (NULL == (temp_obj = H5O_open_by_loc(&obj_loc, &obj_type)))
2597
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open object");
2598
2599
    /* Get an ID for the object */
2600
0
    if ((obj_loc_id = H5VL_wrap_register(obj_type, temp_obj, true)) < 0)
2601
0
        HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, FAIL, "unable to register datatype");
2602
2603
    /* Call internal attribute iteration routine */
2604
0
    if ((ret_value = H5A__iterate_common(obj_loc_id, idx_type, order, idx, &attr_op, op_data)) < 0)
2605
0
        HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
2606
2607
0
done:
2608
    /* Release resources */
2609
0
    if (obj_loc_id != H5I_INVALID_HID) {
2610
0
        if (H5I_dec_app_ref(obj_loc_id) < 0)
2611
0
            HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object");
2612
0
    } /* end if */
2613
0
    else if (loc_found && H5G_loc_free(&obj_loc) < 0)
2614
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location");
2615
2616
0
    FUNC_LEAVE_NOAPI(ret_value)
2617
0
} /* end H5A__iterate() */
2618
2619
#ifndef H5_NO_DEPRECATED_SYMBOLS
2620
2621
/*-------------------------------------------------------------------------
2622
 * Function:    H5A__iterate_old
2623
 *
2624
 * Purpose:     Private version of H5Aiterate1
2625
 *
2626
 * Return:      SUCCEED/FAIL
2627
 *
2628
 *-------------------------------------------------------------------------
2629
 */
2630
herr_t
2631
H5A__iterate_old(hid_t loc_id, unsigned *attr_num, H5A_operator1_t op, void *op_data)
2632
{
2633
    H5A_attr_iter_op_t attr_op;             /* Attribute operator */
2634
    hsize_t            idx;                 /* Index of attribute to start iterating at */
2635
    herr_t             ret_value = SUCCEED; /* Return value */
2636
2637
    FUNC_ENTER_PACKAGE_NOERR
2638
2639
    /* Build attribute operator info */
2640
    attr_op.op_type  = H5A_ATTR_OP_APP;
2641
    attr_op.u.app_op = op;
2642
2643
    /* Set up index */
2644
    idx = (hsize_t)(attr_num ? *attr_num : 0);
2645
2646
    /* Call internal attribute iteration routine */
2647
    if ((ret_value = H5A__iterate_common(loc_id, H5_INDEX_CRT_ORDER, H5_ITER_INC, &idx, &attr_op, op_data)) <
2648
        0)
2649
        HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
2650
2651
    /* Translate hsize_t index value to legacy unsigned index value*/
2652
    if (attr_num)
2653
        *attr_num = (unsigned)idx;
2654
2655
    FUNC_LEAVE_NOAPI(ret_value)
2656
} /* H5A__iterate_old() */
2657
#endif /* H5_NO_DEPRECATED_SYMBOLS */
2658
2659
/*-------------------------------------------------------------------------
2660
 * Function:    H5A__delete_by_name
2661
 *
2662
 * Purpose:     Private version of H5Adelete_by_name
2663
 *
2664
 * Return:      SUCCEED/FAIL
2665
 *
2666
 *-------------------------------------------------------------------------
2667
 */
2668
herr_t
2669
H5A__delete_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name)
2670
0
{
2671
0
    H5G_loc_t  obj_loc;             /* Location used to open group */
2672
0
    H5G_name_t obj_path;            /* Opened object group hier. path */
2673
0
    H5O_loc_t  obj_oloc;            /* Opened object object location */
2674
0
    bool       loc_found = false;   /* Entry at 'obj_name' found */
2675
0
    herr_t     ret_value = SUCCEED; /* Return value */
2676
2677
0
    FUNC_ENTER_PACKAGE
2678
2679
    /* Set up opened group location to fill in */
2680
0
    obj_loc.oloc = &obj_oloc;
2681
0
    obj_loc.path = &obj_path;
2682
0
    H5G_loc_reset(&obj_loc);
2683
2684
    /* Find the object's location */
2685
0
    if (H5G_loc_find(loc, obj_name, &obj_loc /*out*/) < 0)
2686
0
        HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found");
2687
0
    loc_found = true;
2688
2689
    /* Delete the attribute from the location */
2690
0
    if (H5O__attr_remove(obj_loc.oloc, attr_name) < 0)
2691
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute");
2692
2693
0
done:
2694
    /* Release resources */
2695
0
    if (loc_found && H5G_loc_free(&obj_loc) < 0)
2696
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location");
2697
2698
0
    FUNC_LEAVE_NOAPI(ret_value)
2699
0
} /* H5A__delete_by_name() */
2700
2701
/*-------------------------------------------------------------------------
2702
 * Function:    H5A__delete_by_idx
2703
 *
2704
 * Purpose:     Private version of H5Adelete_by_idx
2705
 *
2706
 * Return:      SUCCEED/FAIL
2707
 *
2708
 *-------------------------------------------------------------------------
2709
 */
2710
herr_t
2711
H5A__delete_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order,
2712
                   hsize_t n)
2713
0
{
2714
0
    H5G_loc_t  obj_loc;             /* Location used to open group */
2715
0
    H5G_name_t obj_path;            /* Opened object group hier. path */
2716
0
    H5O_loc_t  obj_oloc;            /* Opened object object location */
2717
0
    bool       loc_found = false;   /* Entry at 'obj_name' found */
2718
0
    herr_t     ret_value = SUCCEED; /* Return value */
2719
2720
0
    FUNC_ENTER_PACKAGE
2721
2722
    /* Set up opened group location to fill in */
2723
0
    obj_loc.oloc = &obj_oloc;
2724
0
    obj_loc.path = &obj_path;
2725
0
    H5G_loc_reset(&obj_loc);
2726
2727
    /* Find the object's location */
2728
0
    if (H5G_loc_find(loc, obj_name, &obj_loc /*out*/) < 0)
2729
0
        HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found");
2730
0
    loc_found = true;
2731
2732
    /* Delete the attribute from the location */
2733
0
    if (H5O__attr_remove_by_idx(obj_loc.oloc, idx_type, order, n) < 0)
2734
0
        HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute");
2735
2736
0
done:
2737
    /* Release resources */
2738
0
    if (loc_found && H5G_loc_free(&obj_loc) < 0)
2739
0
        HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location");
2740
2741
0
    FUNC_LEAVE_NOAPI(ret_value)
2742
0
} /* H5A__delete_by_idx() */