Coverage Report

Created: 2025-08-26 06:30

/src/hdf5/src/H5Gloc.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 LICENSE file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/*-------------------------------------------------------------------------
14
 *
15
 * Created:   H5Gloc.c
16
 *
17
 * Purpose:   Functions for working with group "locations"
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5Gmodule.h" /* This source code file is part of the H5G module */
27
28
/***********/
29
/* Headers */
30
/***********/
31
#include "H5private.h"  /* Generic Functions      */
32
#include "H5Aprivate.h" /* Attributes       */
33
#include "H5Dprivate.h" /* Datasets       */
34
#include "H5Eprivate.h" /* Error handling       */
35
#include "H5Gpkg.h"     /* Groups         */
36
#include "H5Iprivate.h" /* IDs            */
37
#include "H5Lprivate.h" /* Links        */
38
39
/****************/
40
/* Local Macros */
41
/****************/
42
43
/******************/
44
/* Local Typedefs */
45
/******************/
46
47
/* User data for looking up an object in a group */
48
typedef struct {
49
    /* upward */
50
    H5G_loc_t *loc; /* Group location to set */
51
} H5G_loc_fnd_t;
52
53
/* User data for looking up an object in a group by index */
54
typedef struct {
55
    /* downward */
56
    H5_index_t      idx_type; /* Index to use */
57
    H5_iter_order_t order;    /* Iteration order within index */
58
    hsize_t         n;        /* Offset within index */
59
60
    /* upward */
61
    H5G_loc_t *loc; /* Group location to set */
62
} H5G_loc_fbi_t;
63
64
/* User data for getting an object's data model info in a group */
65
typedef struct {
66
    /* downward */
67
    unsigned fields; /* which fields in H5O_info2_t struct to fill in */
68
69
    /* upward */
70
    H5O_info2_t *oinfo; /* Object information to retrieve */
71
} H5G_loc_info_t;
72
73
/* User data for getting an object's native info in a group */
74
typedef struct {
75
    /* downward */
76
    unsigned fields; /* which fields in H5O_native_info_t struct to fill in */
77
78
    /* upward */
79
    H5O_native_info_t *oinfo; /* Object information to retrieve */
80
} H5G_loc_native_info_t;
81
82
/* User data for setting an object's comment in a group */
83
typedef struct {
84
    /* downward */
85
    const char *comment; /* Object comment buffer */
86
87
    /* upward */
88
} H5G_loc_sc_t;
89
90
/* User data for getting an object's comment in a group */
91
typedef struct {
92
    /* downward */
93
    char  *comment; /* Object comment buffer */
94
    size_t bufsize; /* Size of object comment buffer */
95
96
    /* upward */
97
    size_t comment_size; /* Actual size of object comment */
98
} H5G_loc_gc_t;
99
100
/********************/
101
/* Local Prototypes */
102
/********************/
103
104
/* Group traversal callbacks */
105
static herr_t H5G__loc_find_cb(H5G_loc_t *grp_loc, const char *name, const H5O_link_t *lnk,
106
                               H5G_loc_t *obj_loc, void *_udata, H5G_own_loc_t *own_loc);
107
static herr_t H5G__loc_find_by_idx_cb(H5G_loc_t *grp_loc, const char *name, const H5O_link_t *lnk,
108
                                      H5G_loc_t *obj_loc, void *_udata, H5G_own_loc_t *own_loc);
109
static herr_t H5G__loc_addr_cb(H5G_loc_t *grp_loc, const char *name, const H5O_link_t *lnk,
110
                               H5G_loc_t *obj_loc, void *_udata, H5G_own_loc_t *own_loc);
111
static herr_t H5G__loc_info_cb(H5G_loc_t *grp_loc, const char *name, const H5O_link_t *lnk,
112
                               H5G_loc_t *obj_loc, void *_udata, H5G_own_loc_t *own_loc);
113
static herr_t H5G__loc_native_info_cb(H5G_loc_t *grp_loc, const char *name, const H5O_link_t *lnk,
114
                                      H5G_loc_t *obj_loc, void *_udata, H5G_own_loc_t *own_loc);
115
static herr_t H5G__loc_set_comment_cb(H5G_loc_t *grp_loc, const char *name, const H5O_link_t *lnk,
116
                                      H5G_loc_t *obj_loc, void *_udata, H5G_own_loc_t *own_loc);
117
static herr_t H5G__loc_get_comment_cb(H5G_loc_t *grp_loc, const char *name, const H5O_link_t *lnk,
118
                                      H5G_loc_t *obj_loc, void *_udata, H5G_own_loc_t *own_loc);
119
120
/*********************/
121
/* Package Variables */
122
/*********************/
123
124
/*****************************/
125
/* Library Private Variables */
126
/*****************************/
127
128
/*******************/
129
/* Local Variables */
130
/*******************/
131
132
/*-------------------------------------------------------------------------
133
 * Function:    H5G_loc_real
134
 *
135
 * Purpose:     Utility routine to get object location
136
 *
137
 * Returns:     SUCCEED/FAIL
138
 *
139
 *-------------------------------------------------------------------------
140
 */
141
herr_t
142
H5G_loc_real(void *obj, H5I_type_t type, H5G_loc_t *loc)
143
1.77k
{
144
1.77k
    herr_t ret_value = SUCCEED; /* Return value */
145
146
1.77k
    FUNC_ENTER_NOAPI(FAIL)
147
148
1.77k
    switch (type) {
149
1.71k
        case H5I_FILE: {
150
1.71k
            H5F_t *f = (H5F_t *)obj;
151
152
            /* Construct a group location for root group of the file */
153
1.71k
            if (H5G_root_loc(f, loc) < 0)
154
0
                HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unable to create location for file");
155
1.71k
            break;
156
1.71k
        }
157
158
1.71k
        case H5I_GROUP: {
159
0
            H5G_t *group = (H5G_t *)obj;
160
161
0
            if (NULL == (loc->oloc = H5G_oloc(group)))
162
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of group");
163
0
            if (NULL == (loc->path = H5G_nameof(group)))
164
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of group");
165
0
            break;
166
0
        }
167
168
0
        case H5I_DATATYPE: {
169
0
            H5T_t *dt = NULL;
170
171
            /* Get the actual datatype object if the VOL object is set */
172
0
            dt = H5T_get_actual_type((H5T_t *)obj);
173
174
0
            if (NULL == (loc->oloc = H5T_oloc(dt)))
175
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of datatype");
176
0
            if (NULL == (loc->path = H5T_nameof(dt)))
177
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of datatype");
178
0
            break;
179
0
        }
180
181
57
        case H5I_DATASET: {
182
57
            H5D_t *dset = (H5D_t *)obj;
183
184
57
            if (NULL == (loc->oloc = H5D_oloc(dset)))
185
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of dataset");
186
57
            if (NULL == (loc->path = H5D_nameof(dset)))
187
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of dataset");
188
57
            break;
189
57
        }
190
191
57
        case H5I_ATTR: {
192
0
            H5A_t *attr = (H5A_t *)obj;
193
194
0
            if (NULL == (loc->oloc = H5A_oloc(attr)))
195
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of attribute");
196
0
            if (NULL == (loc->path = H5A_nameof(attr)))
197
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of attribute");
198
0
            break;
199
0
        }
200
201
0
        case H5I_DATASPACE:
202
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of dataspace");
203
204
0
        case H5I_MAP:
205
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "maps not supported in native VOL connector");
206
207
0
        case H5I_GENPROP_CLS:
208
0
        case H5I_GENPROP_LST:
209
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of property list");
210
211
0
        case H5I_ERROR_CLASS:
212
0
        case H5I_ERROR_MSG:
213
0
        case H5I_ERROR_STACK:
214
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
215
0
                        "unable to get group location of error class, message or stack");
216
217
0
        case H5I_VFL:
218
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
219
0
                        "unable to get group location of a virtual file driver (VFD)");
220
221
0
        case H5I_VOL:
222
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
223
0
                        "unable to get group location of a virtual object layer (VOL) connector");
224
225
0
        case H5I_SPACE_SEL_ITER:
226
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
227
0
                        "unable to get group location of a dataspace selection iterator");
228
229
0
        case H5I_EVENTSET:
230
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of a event set");
231
232
0
        case H5I_UNINIT:
233
0
        case H5I_BADID:
234
0
        case H5I_NTYPES:
235
0
        default:
236
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid location type");
237
1.77k
    } /* end switch */
238
239
1.77k
done:
240
1.77k
    FUNC_LEAVE_NOAPI(ret_value)
241
1.77k
} /* end H5G_loc_real() */
242
243
/*-------------------------------------------------------------------------
244
 * Function:    H5G_loc
245
 *
246
 * Purpose:     Given an object ID return a location for the object.
247
 *
248
 * Return:      SUCCEED/FAIL
249
 *
250
 *-------------------------------------------------------------------------
251
 */
252
herr_t
253
H5G_loc(hid_t loc_id, H5G_loc_t *loc)
254
0
{
255
0
    void  *obj       = NULL;    /* VOL object   */
256
0
    herr_t ret_value = SUCCEED; /* Return value */
257
258
0
    FUNC_ENTER_NOAPI(FAIL)
259
260
    /* Get the object from the VOL */
261
0
    if (NULL == (obj = H5VL_object(loc_id)))
262
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
263
264
    /* Fill in the struct */
265
0
    if (H5G_loc_real(obj, H5I_get_type(loc_id), loc) < 0)
266
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unable to fill in location struct");
267
268
0
done:
269
0
    FUNC_LEAVE_NOAPI(ret_value)
270
0
} /* end H5G_loc() */
271
272
/*-------------------------------------------------------------------------
273
 * Function:  H5G_loc_copy
274
 *
275
 * Purpose: Copy over information for a location
276
 *
277
 * Return:  Non-negative on success/Negative on failure
278
 *
279
 *-------------------------------------------------------------------------
280
 */
281
herr_t
282
H5G_loc_copy(H5G_loc_t *dst, const H5G_loc_t *src, H5_copy_depth_t depth)
283
2.32k
{
284
2.32k
    herr_t ret_value = SUCCEED; /* Return value */
285
286
2.32k
    FUNC_ENTER_NOAPI(FAIL)
287
288
    /* Check args. */
289
2.32k
    assert(dst);
290
2.32k
    assert(src);
291
292
    /* Copy components of the location */
293
2.32k
    if (H5O_loc_copy(dst->oloc, src->oloc, depth) < 0)
294
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to copy entry");
295
2.32k
    if (H5G_name_copy(dst->path, src->path, depth) < 0)
296
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to copy path");
297
298
2.32k
done:
299
2.32k
    FUNC_LEAVE_NOAPI(ret_value)
300
2.32k
} /* end H5G_loc_copy() */
301
302
/*-------------------------------------------------------------------------
303
 * Function:  H5G_loc_reset
304
 *
305
 * Purpose: Reset information for a location
306
 *
307
 * Return:  Non-negative on success/Negative on failure
308
 *
309
 *-------------------------------------------------------------------------
310
 */
311
herr_t
312
H5G_loc_reset(H5G_loc_t *loc)
313
5.32k
{
314
5.32k
    herr_t ret_value = SUCCEED; /* Return value */
315
316
5.32k
    FUNC_ENTER_NOAPI(FAIL)
317
318
    /* Check args. */
319
5.32k
    assert(loc);
320
321
    /* Reset components of the location */
322
5.32k
    if (H5O_loc_reset(loc->oloc) < 0)
323
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to reset entry");
324
5.32k
    if (H5G_name_reset(loc->path) < 0)
325
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to reset path");
326
327
5.32k
done:
328
5.32k
    FUNC_LEAVE_NOAPI(ret_value)
329
5.32k
} /* end H5G_loc_reset() */
330
331
/*-------------------------------------------------------------------------
332
 * Function:  H5G_loc_free
333
 *
334
 * Purpose: Free information for a location
335
 *
336
 * Return:  Non-negative on success/Negative on failure
337
 *
338
 *-------------------------------------------------------------------------
339
 */
340
herr_t
341
H5G_loc_free(H5G_loc_t *loc)
342
2.31k
{
343
2.31k
    herr_t ret_value = SUCCEED; /* Return value */
344
345
2.31k
    FUNC_ENTER_NOAPI(FAIL)
346
347
    /* Check args. */
348
2.31k
    assert(loc);
349
350
    /* Reset components of the location */
351
2.31k
    if (H5G_name_free(loc->path) < 0)
352
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to free path");
353
2.31k
    if (H5O_loc_free(loc->oloc) < 0)
354
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to free object header location");
355
356
2.31k
done:
357
2.31k
    FUNC_LEAVE_NOAPI(ret_value)
358
2.31k
} /* end H5G_loc_free() */
359
360
/*-------------------------------------------------------------------------
361
 * Function:  H5G__loc_find_cb
362
 *
363
 * Purpose: Callback for retrieving object location for an object in a group
364
 *
365
 * Return:  Non-negative on success/Negative on failure
366
 *
367
 *-------------------------------------------------------------------------
368
 */
369
static herr_t
370
H5G__loc_find_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc /*in*/, const char *name,
371
                 const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata /*in,out*/,
372
                 H5G_own_loc_t *own_loc /*out*/)
373
662
{
374
662
    H5G_loc_fnd_t *udata     = (H5G_loc_fnd_t *)_udata; /* User data passed in */
375
662
    herr_t         ret_value = SUCCEED;                 /* Return value */
376
377
662
    FUNC_ENTER_PACKAGE
378
379
    /* Check if the name in this group resolved to a valid object */
380
662
    if (obj_loc == NULL)
381
154
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object '%s' doesn't exist", name);
382
383
    /* Take ownership of the object's group location */
384
    /* (Group traversal callbacks are responsible for either taking ownership
385
     *  of the group location for the object, or freeing it. - QAK)
386
     */
387
508
    H5G_loc_copy(udata->loc, obj_loc, H5_COPY_SHALLOW);
388
508
    *own_loc = H5G_OWN_OBJ_LOC;
389
390
662
done:
391
662
    FUNC_LEAVE_NOAPI(ret_value)
392
662
} /* end H5G__loc_find_cb() */
393
394
/*-------------------------------------------------------------------------
395
 * Function:  H5G_loc_find
396
 *
397
 * Purpose: Find a symbol from a location
398
 *
399
 * Return:  Non-negative on success/Negative on failure
400
 *
401
 *-------------------------------------------------------------------------
402
 */
403
herr_t
404
H5G_loc_find(const H5G_loc_t *loc, const char *name, H5G_loc_t *obj_loc /*out*/)
405
1.71k
{
406
1.71k
    H5G_loc_fnd_t udata;               /* User data for traversal callback */
407
1.71k
    herr_t        ret_value = SUCCEED; /* Return value */
408
409
1.71k
    FUNC_ENTER_NOAPI(FAIL)
410
411
    /* Check args. */
412
1.71k
    assert(loc);
413
1.71k
    assert(name);
414
1.71k
    assert(obj_loc);
415
416
1.71k
    if (!*name)
417
0
        HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "invalid object name");
418
419
    /* Set up user data for locating object */
420
1.71k
    udata.loc = obj_loc;
421
422
    /* Traverse group hierarchy to locate object */
423
1.71k
    if (H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G__loc_find_cb, &udata) < 0)
424
1.20k
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object");
425
426
1.71k
done:
427
1.71k
    FUNC_LEAVE_NOAPI(ret_value)
428
1.71k
} /* end H5G_loc_find() */
429
430
/*-------------------------------------------------------------------------
431
 * Function:  H5G__loc_find_by_idx_cb
432
 *
433
 * Purpose: Callback for retrieving object location for an object in a group
434
 *              according to the order within an index
435
 *
436
 * Return:  Non-negative on success/Negative on failure
437
 *
438
 *-------------------------------------------------------------------------
439
 */
440
static herr_t
441
H5G__loc_find_by_idx_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc /*in*/, const char H5_ATTR_UNUSED *name,
442
                        const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata /*in,out*/,
443
                        H5G_own_loc_t *own_loc /*out*/)
444
0
{
445
0
    H5G_loc_fbi_t *udata = (H5G_loc_fbi_t *)_udata; /* User data passed in */
446
0
    H5O_link_t     fnd_lnk;                         /* Link within group */
447
0
    bool           lnk_copied    = false;           /* Whether the link was copied */
448
0
    bool           obj_loc_valid = false;           /* Flag to indicate that the object location is valid */
449
0
    bool           obj_exists    = false;           /* Whether the object exists (unused) */
450
0
    herr_t         ret_value     = SUCCEED;         /* Return value */
451
452
0
    FUNC_ENTER_PACKAGE
453
454
    /* Check if the name in this group resolved to a valid link */
455
0
    if (obj_loc == NULL)
456
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist");
457
458
    /* Query link */
459
0
    if (H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order, udata->n, &fnd_lnk) < 0)
460
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found");
461
0
    lnk_copied = true;
462
463
    /* Build the initial object location for the link */
464
0
    if (H5G__link_to_loc(obj_loc, &fnd_lnk, udata->loc) < 0)
465
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot initialize object location");
466
0
    obj_loc_valid = true;
467
468
    /* Perform any special traversals that the link needs */
469
    /* (soft links, user-defined links, file mounting, etc.) */
470
    /* (may modify the object location) */
471
0
    if (H5G__traverse_special(obj_loc, &fnd_lnk, H5G_TARGET_NORMAL, true, udata->loc, &obj_exists) < 0)
472
0
        HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "special link traversal failed");
473
474
0
done:
475
    /* Reset the link information, if we have a copy */
476
0
    if (lnk_copied)
477
0
        H5O_msg_reset(H5O_LINK_ID, &fnd_lnk);
478
479
    /* Release the object location if we failed after copying it */
480
0
    if (ret_value < 0 && obj_loc_valid)
481
0
        if (H5G_loc_free(udata->loc) < 0)
482
0
            HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location");
483
484
    /* Indicate that this callback didn't take ownership of the group *
485
     * location for the object */
486
0
    *own_loc = H5G_OWN_NONE;
487
488
0
    FUNC_LEAVE_NOAPI(ret_value)
489
0
} /* end H5G__loc_find_by_idx_cb() */
490
491
/*-------------------------------------------------------------------------
492
 * Function:  H5G_loc_find_by_idx
493
 *
494
 * Purpose: Find a symbol from a location, according to the order in an index
495
 *
496
 * Return:  Non-negative on success/Negative on failure
497
 *
498
 *-------------------------------------------------------------------------
499
 */
500
herr_t
501
H5G_loc_find_by_idx(const H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter_order_t order,
502
                    hsize_t n, H5G_loc_t *obj_loc /*out*/)
503
0
{
504
0
    H5G_loc_fbi_t udata;               /* User data for traversal callback */
505
0
    herr_t        ret_value = SUCCEED; /* Return value */
506
507
0
    FUNC_ENTER_NOAPI(FAIL)
508
509
    /* Check args. */
510
0
    assert(loc);
511
0
    assert(group_name && *group_name);
512
0
    assert(obj_loc);
513
514
    /* Set up user data for locating object */
515
0
    udata.idx_type = idx_type;
516
0
    udata.order    = order;
517
0
    udata.n        = n;
518
0
    udata.loc      = obj_loc;
519
520
    /* Traverse group hierarchy to locate object */
521
0
    if (H5G_traverse(loc, group_name, H5G_TARGET_NORMAL, H5G__loc_find_by_idx_cb, &udata) < 0)
522
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object");
523
524
0
done:
525
0
    FUNC_LEAVE_NOAPI(ret_value)
526
0
} /* end H5G_loc_find_by_idx() */
527
528
/*-------------------------------------------------------------------------
529
 * Function:  H5G__loc_insert
530
 *
531
 * Purpose: Insert an object at a location
532
 *
533
 * Return:  Non-negative on success/Negative on failure
534
 *
535
 *-------------------------------------------------------------------------
536
 */
537
herr_t
538
H5G__loc_insert(H5G_loc_t *grp_loc, char *name, H5G_loc_t *obj_loc, H5O_type_t obj_type, const void *crt_info)
539
0
{
540
0
    H5O_link_t lnk;                 /* Link for object to insert */
541
0
    herr_t     ret_value = SUCCEED; /* Return value */
542
543
0
    FUNC_ENTER_PACKAGE
544
545
    /* Check args. */
546
0
    assert(grp_loc);
547
0
    assert(name && *name);
548
0
    assert(obj_loc);
549
550
    /* Create link object for the object location */
551
0
    lnk.type         = H5L_TYPE_HARD;
552
0
    lnk.cset         = H5F_DEFAULT_CSET;
553
0
    lnk.corder       = 0;     /* Will be reset if the group is tracking creation order */
554
0
    lnk.corder_valid = false; /* Indicate that the creation order isn't valid (yet) */
555
0
    lnk.name         = name;
556
0
    lnk.u.hard.addr  = obj_loc->oloc->addr;
557
558
    /* Insert new group into current group's symbol table */
559
0
    if (H5G_obj_insert(grp_loc->oloc, &lnk, true, obj_type, crt_info) < 0)
560
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert object");
561
562
    /* Set the name of the object location */
563
0
    if (H5G_name_set(grp_loc->path, obj_loc->path, name) < 0)
564
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name");
565
566
0
done:
567
0
    FUNC_LEAVE_NOAPI(ret_value)
568
0
} /* end H5G__loc_insert() */
569
570
/*-------------------------------------------------------------------------
571
 * Function:  H5G__loc_exists_cb
572
 *
573
 * Purpose: Callback for checking if an object exists
574
 *
575
 * Return:  Non-negative on success/Negative on failure
576
 *
577
 *-------------------------------------------------------------------------
578
 */
579
static herr_t
580
H5G__loc_exists_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc /*in*/, const char H5_ATTR_UNUSED *name,
581
                   const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata /*in,out*/,
582
                   H5G_own_loc_t *own_loc /*out*/)
583
0
{
584
0
    bool *exists = (bool *)_udata; /* User data passed in */
585
586
0
    FUNC_ENTER_PACKAGE_NOERR
587
588
    /* Check if the name in this group resolved to a valid object */
589
0
    if (obj_loc == NULL)
590
0
        *exists = false;
591
0
    else
592
0
        *exists = true;
593
594
    /* Indicate that this callback didn't take ownership of the group *
595
     * location for the object */
596
0
    *own_loc = H5G_OWN_NONE;
597
598
0
    FUNC_LEAVE_NOAPI(SUCCEED)
599
0
} /* end H5G__loc_exists_cb() */
600
601
/*-------------------------------------------------------------------------
602
 * Function:  H5G_loc_exists
603
 *
604
 * Purpose: Check if an object actually exists at a location
605
 *
606
 * Return:  Non-negative on success/Negative on failure
607
 *
608
 *-------------------------------------------------------------------------
609
 */
610
herr_t
611
H5G_loc_exists(const H5G_loc_t *loc, const char *name, bool *exists)
612
0
{
613
0
    herr_t ret_value = SUCCEED; /* Return value */
614
615
0
    FUNC_ENTER_NOAPI(FAIL)
616
617
    /* Check args. */
618
0
    assert(loc);
619
0
    assert(name && *name);
620
0
    assert(exists);
621
622
    /* Traverse group hierarchy to locate object */
623
0
    if (H5G_traverse(loc, name, H5G_TARGET_EXISTS, H5G__loc_exists_cb, exists) < 0)
624
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't check if object exists");
625
626
0
done:
627
0
    FUNC_LEAVE_NOAPI(ret_value)
628
0
} /* end H5G_loc_exists() */
629
630
/*-------------------------------------------------------------------------
631
 * Function:  H5G__loc_addr_cb
632
 *
633
 * Purpose: Callback for retrieving the address for an object in a group
634
 *
635
 * Return:  Non-negative on success/Negative on failure
636
 *
637
 *-------------------------------------------------------------------------
638
 */
639
static herr_t
640
H5G__loc_addr_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc /*in*/, const char H5_ATTR_UNUSED *name,
641
                 const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata /*in,out*/,
642
                 H5G_own_loc_t *own_loc /*out*/)
643
0
{
644
0
    haddr_t *udata = (haddr_t *)_udata; /* User data passed in */
645
646
0
    FUNC_ENTER_PACKAGE_NOERR
647
648
    /* Check if the name in this group resolved to a valid link */
649
0
    if (obj_loc == NULL)
650
0
        *udata = HADDR_UNDEF; /* No object found */
651
0
    else
652
0
        *udata = obj_loc->oloc->addr; /* Set address of object */
653
654
    /* Indicate that this callback didn't take ownership of the group *
655
     * location for the object */
656
0
    *own_loc = H5G_OWN_NONE;
657
658
0
    FUNC_LEAVE_NOAPI(SUCCEED)
659
0
} /* end H5G__loc_addr_cb() */
660
661
/*-------------------------------------------------------------------------
662
 * Function:  H5G__loc_addr
663
 *
664
 * Purpose: Retrieve the information for an object from a group location
665
 *              and path to that object
666
 *
667
 * Return:  Non-negative on success/Negative on failure
668
 *
669
 *-------------------------------------------------------------------------
670
 */
671
herr_t
672
H5G__loc_addr(const H5G_loc_t *loc, const char *name, haddr_t *addr /*out*/)
673
0
{
674
0
    herr_t ret_value = SUCCEED; /* Return value */
675
676
0
    FUNC_ENTER_PACKAGE
677
678
    /* Check args. */
679
0
    assert(loc);
680
0
    assert(name && *name);
681
0
    assert(addr);
682
683
    /* Traverse group hierarchy to locate object */
684
0
    if (H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G__loc_addr_cb, addr) < 0)
685
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object");
686
687
0
done:
688
0
    FUNC_LEAVE_NOAPI(ret_value)
689
0
} /* end H5G__loc_addr() */
690
691
/*-------------------------------------------------------------------------
692
 * Function:  H5G__loc_info_cb
693
 *
694
 * Purpose: Callback for retrieving data model info for an object in a group
695
 *
696
 * Return:  Non-negative on success/Negative on failure
697
 *
698
 *-------------------------------------------------------------------------
699
 */
700
static herr_t
701
H5G__loc_info_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc /*in*/, const char H5_ATTR_UNUSED *name,
702
                 const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata /*in,out*/,
703
                 H5G_own_loc_t *own_loc /*out*/)
704
0
{
705
0
    H5G_loc_info_t *udata     = (H5G_loc_info_t *)_udata; /* User data passed in */
706
0
    herr_t          ret_value = SUCCEED;                  /* Return value */
707
708
0
    FUNC_ENTER_PACKAGE
709
710
    /* Check if the name in this group resolved to a valid link */
711
0
    if (obj_loc == NULL)
712
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist");
713
714
    /* Query object information */
715
0
    if (H5O_get_info(obj_loc->oloc, udata->oinfo, udata->fields) < 0)
716
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get object info");
717
718
0
done:
719
    /* Indicate that this callback didn't take ownership of the group *
720
     * location for the object */
721
0
    *own_loc = H5G_OWN_NONE;
722
723
0
    FUNC_LEAVE_NOAPI(ret_value)
724
0
} /* end H5G__loc_info_cb() */
725
726
/*-------------------------------------------------------------------------
727
 * Function:    H5G_loc_info
728
 *
729
 * Purpose:     Retrieve the data model information for an object from a group location
730
 *              and path to that object
731
 *
732
 * Return:  Non-negative on success/Negative on failure
733
 *
734
 *-------------------------------------------------------------------------
735
 */
736
herr_t
737
H5G_loc_info(const H5G_loc_t *loc, const char *name, H5O_info2_t *oinfo /*out*/, unsigned fields)
738
0
{
739
0
    H5G_loc_info_t udata;               /* User data for traversal callback */
740
0
    herr_t         ret_value = SUCCEED; /* Return value */
741
742
0
    FUNC_ENTER_NOAPI(FAIL)
743
744
    /* Check args. */
745
0
    assert(loc);
746
0
    assert(name && *name);
747
0
    assert(oinfo);
748
749
    /* Set up user data for locating object */
750
0
    udata.fields = fields;
751
0
    udata.oinfo  = oinfo;
752
753
    /* Traverse group hierarchy to locate object */
754
0
    if (H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G__loc_info_cb, &udata) < 0)
755
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object");
756
757
0
done:
758
0
    FUNC_LEAVE_NOAPI(ret_value)
759
0
} /* end H5G_loc_info() */
760
761
/*-------------------------------------------------------------------------
762
 * Function:  H5G__loc_native_info_cb
763
 *
764
 * Purpose: Callback for retrieving native info for an object in a group
765
 *
766
 * Return:  Non-negative on success/Negative on failure
767
 *
768
 *-------------------------------------------------------------------------
769
 */
770
static herr_t
771
H5G__loc_native_info_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc /*in*/, const char H5_ATTR_UNUSED *name,
772
                        const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata /*in,out*/,
773
                        H5G_own_loc_t *own_loc /*out*/)
774
0
{
775
0
    H5G_loc_native_info_t *udata     = (H5G_loc_native_info_t *)_udata; /* User data passed in */
776
0
    herr_t                 ret_value = SUCCEED;                         /* Return value */
777
778
0
    FUNC_ENTER_PACKAGE
779
780
    /* Check if the name in this group resolved to a valid link */
781
0
    if (obj_loc == NULL)
782
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist");
783
784
    /* Query object information */
785
0
    if (H5O_get_native_info(obj_loc->oloc, udata->oinfo, udata->fields) < 0)
786
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get object info");
787
788
0
done:
789
    /* Indicate that this callback didn't take ownership of the group *
790
     * location for the object */
791
0
    *own_loc = H5G_OWN_NONE;
792
793
0
    FUNC_LEAVE_NOAPI(ret_value)
794
0
} /* end H5G__loc_native_info_cb() */
795
796
/*-------------------------------------------------------------------------
797
 * Function:  H5G_loc_native_info
798
 *
799
 * Purpose: Retrieve the native information for an object from a group location
800
 *              and path to that object
801
 *
802
 * Return:  Non-negative on success/Negative on failure
803
 *
804
 *-------------------------------------------------------------------------
805
 */
806
herr_t
807
H5G_loc_native_info(const H5G_loc_t *loc, const char *name, H5O_native_info_t *oinfo /*out*/, unsigned fields)
808
0
{
809
0
    H5G_loc_native_info_t udata;               /* User data for traversal callback */
810
0
    herr_t                ret_value = SUCCEED; /* Return value */
811
812
0
    FUNC_ENTER_NOAPI(FAIL)
813
814
    /* Check args. */
815
0
    assert(loc);
816
0
    assert(name && *name);
817
0
    assert(oinfo);
818
819
    /* Set up user data for locating object */
820
0
    udata.fields = fields;
821
0
    udata.oinfo  = oinfo;
822
823
    /* Traverse group hierarchy to locate object */
824
0
    if (H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G__loc_native_info_cb, &udata) < 0)
825
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object");
826
827
0
done:
828
0
    FUNC_LEAVE_NOAPI(ret_value)
829
0
} /* end H5G_loc_native_info() */
830
831
/*-------------------------------------------------------------------------
832
 * Function:  H5G__loc_set_comment_cb
833
 *
834
 * Purpose: Callback for (re)setting object comment for an object in a group
835
 *
836
 * Return:  Non-negative on success/Negative on failure
837
 *
838
 *-------------------------------------------------------------------------
839
 */
840
static herr_t
841
H5G__loc_set_comment_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc /*in*/, const char H5_ATTR_UNUSED *name,
842
                        const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata /*in,out*/,
843
                        H5G_own_loc_t *own_loc /*out*/)
844
0
{
845
0
    H5G_loc_sc_t *udata   = (H5G_loc_sc_t *)_udata; /* User data passed in */
846
0
    H5O_name_t    comment = {0};                    /* Object header "comment" message */
847
0
    htri_t        exists;                           /* Whether a "comment" message already exists */
848
0
    herr_t        ret_value = SUCCEED;              /* Return value */
849
850
0
    FUNC_ENTER_PACKAGE
851
852
    /* Check if the name in this group resolved to a valid link */
853
0
    if (obj_loc == NULL)
854
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist");
855
856
    /* Check for existing comment message */
857
0
    if ((exists = H5O_msg_exists(obj_loc->oloc, H5O_NAME_ID)) < 0)
858
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read object header");
859
860
    /* Remove the previous comment message if any */
861
0
    if (exists)
862
0
        if (H5O_msg_remove(obj_loc->oloc, H5O_NAME_ID, 0, true) < 0)
863
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL,
864
0
                        "unable to delete existing comment object header message");
865
866
    /* Add the new message */
867
0
    if (udata->comment && *udata->comment) {
868
0
        if (NULL == (comment.s = strdup(udata->comment)))
869
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't copy group comment");
870
0
        if (H5O_msg_create(obj_loc->oloc, H5O_NAME_ID, 0, H5O_UPDATE_TIME, &comment) < 0)
871
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to set comment object header message");
872
0
    } /* end if */
873
874
0
done:
875
0
    free(comment.s);
876
877
    /* Indicate that this callback didn't take ownership of the group *
878
     * location for the object */
879
0
    *own_loc = H5G_OWN_NONE;
880
881
0
    FUNC_LEAVE_NOAPI(ret_value)
882
0
} /* end H5G__loc_set_comment_cb() */
883
884
/*-------------------------------------------------------------------------
885
 * Function:  H5G_loc_set_comment
886
 *
887
 * Purpose: (Re)set the information for an object from a group location
888
 *              and path to that object
889
 *
890
 * Return:  Non-negative on success/Negative on failure
891
 *
892
 *-------------------------------------------------------------------------
893
 */
894
herr_t
895
H5G_loc_set_comment(const H5G_loc_t *loc, const char *name, const char *comment)
896
0
{
897
0
    H5G_loc_sc_t udata;               /* User data for traversal callback */
898
0
    herr_t       ret_value = SUCCEED; /* Return value */
899
900
0
    FUNC_ENTER_NOAPI(FAIL)
901
902
    /* Check args. */
903
0
    assert(loc);
904
0
    assert(name && *name);
905
906
    /* Set up user data for locating object */
907
0
    udata.comment = comment;
908
909
    /* Traverse group hierarchy to locate object */
910
0
    if (H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G__loc_set_comment_cb, &udata) < 0)
911
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object");
912
913
0
done:
914
0
    FUNC_LEAVE_NOAPI(ret_value)
915
0
} /* end H5G_loc_set_comment() */
916
917
/*-------------------------------------------------------------------------
918
 * Function:  H5G__loc_get_comment_cb
919
 *
920
 * Purpose: Callback for retrieving object comment for an object in a group
921
 *
922
 * Return:  Non-negative on success/Negative on failure
923
 *
924
 *-------------------------------------------------------------------------
925
 */
926
static herr_t
927
H5G__loc_get_comment_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc /*in*/, const char H5_ATTR_UNUSED *name,
928
                        const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata /*in,out*/,
929
                        H5G_own_loc_t *own_loc /*out*/)
930
0
{
931
0
    H5G_loc_gc_t *udata = (H5G_loc_gc_t *)_udata; /* User data passed in */
932
0
    H5O_name_t    comment;                        /* Object header "comment" message */
933
0
    herr_t        ret_value = SUCCEED;            /* Return value */
934
935
0
    FUNC_ENTER_PACKAGE
936
937
    /* Check if the name in this group resolved to a valid link */
938
0
    if (obj_loc == NULL)
939
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist");
940
941
    /* Query object comment */
942
0
    comment.s = NULL;
943
0
    if (NULL == H5O_msg_read(obj_loc->oloc, H5O_NAME_ID, &comment)) {
944
0
        if (udata->comment && udata->bufsize > 0)
945
0
            udata->comment[0] = '\0';
946
0
        udata->comment_size = 0;
947
0
    }
948
0
    else {
949
0
        if (udata->comment && udata->bufsize)
950
0
            strncpy(udata->comment, comment.s, udata->bufsize);
951
0
        udata->comment_size = strlen(comment.s);
952
0
        H5O_msg_reset(H5O_NAME_ID, &comment);
953
0
    }
954
955
0
done:
956
    /* Indicate that this callback didn't take ownership of the group *
957
     * location for the object.
958
     */
959
0
    *own_loc = H5G_OWN_NONE;
960
961
0
    FUNC_LEAVE_NOAPI(ret_value)
962
0
} /* end H5G__loc_get_comment_cb() */
963
964
/*-------------------------------------------------------------------------
965
 * Function:  H5G_loc_get_comment
966
 *
967
 * Purpose: Retrieve the information for an object from a group location
968
 *              and path to that object
969
 *
970
 * Return:  Non-negative on success/Negative on failure
971
 *
972
 *-------------------------------------------------------------------------
973
 */
974
herr_t
975
H5G_loc_get_comment(const H5G_loc_t *loc, const char *name, char *comment /*out*/, size_t bufsize,
976
                    size_t *comment_len)
977
0
{
978
0
    H5G_loc_gc_t udata;               /* User data for traversal callback */
979
0
    herr_t       ret_value = SUCCEED; /* Return value */
980
981
0
    FUNC_ENTER_NOAPI(FAIL)
982
983
    /* Check args. */
984
0
    assert(loc);
985
0
    assert(name && *name);
986
987
    /* Set up user data for locating object */
988
0
    udata.comment      = comment;
989
0
    udata.bufsize      = bufsize;
990
0
    udata.comment_size = 0;
991
992
    /* Traverse group hierarchy to locate object */
993
0
    if (H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G__loc_get_comment_cb, &udata) < 0)
994
0
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object");
995
996
    /* Set value to return */
997
0
    if (comment_len)
998
0
        *comment_len = udata.comment_size;
999
1000
0
done:
1001
0
    FUNC_LEAVE_NOAPI(ret_value)
1002
0
} /* end H5G_loc_get_comment() */