Coverage Report

Created: 2026-03-04 00:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5L.c
Line
Count
Source
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the LICENSE file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/****************/
14
/* Module Setup */
15
/****************/
16
17
#include "H5Lmodule.h" /* This source code file is part of the H5L module */
18
19
/***********/
20
/* Headers */
21
/***********/
22
#include "H5private.h"          /* Generic Functions                        */
23
#include "H5CXprivate.h"        /* API Contexts                             */
24
#include "H5Eprivate.h"         /* Error handling                           */
25
#include "H5ESprivate.h"        /* Event Sets                               */
26
#include "H5Gprivate.h"         /* Groups                                   */
27
#include "H5Iprivate.h"         /* IDs                                      */
28
#include "H5Lpkg.h"             /* Links                                    */
29
#include "H5MMprivate.h"        /* Memory management                        */
30
#include "H5Pprivate.h"         /* Property lists                           */
31
#include "H5VLprivate.h"        /* Virtual Object Layer                     */
32
#include "H5VLnative_private.h" /* Native VOL                               */
33
34
/****************/
35
/* Local Macros */
36
/****************/
37
38
/******************/
39
/* Local Typedefs */
40
/******************/
41
42
/********************/
43
/* Local Prototypes */
44
/********************/
45
46
static herr_t H5L__create_soft_api_common(const char *link_target, hid_t link_loc_id, const char *link_name,
47
                                          hid_t lcpl_id, hid_t lapl_id, void **token_ptr,
48
                                          H5VL_object_t **_vol_obj_ptr);
49
static herr_t H5L__create_hard_api_common(hid_t cur_loc_id, const char *cur_name, hid_t new_loc_id,
50
                                          const char *new_name, hid_t lcpl_id, hid_t lapl_id,
51
                                          void **token_ptr, H5VL_connector_t **conn);
52
static herr_t H5L__delete_api_common(hid_t loc_id, const char *name, hid_t lapl_id, void **token_ptr,
53
                                     H5VL_object_t **_vol_obj_ptr);
54
static herr_t H5L__delete_by_idx_api_common(hid_t loc_id, const char *group_name, H5_index_t idx_type,
55
                                            H5_iter_order_t order, hsize_t n, hid_t lapl_id, void **token_ptr,
56
                                            H5VL_object_t **_vol_obj_ptr);
57
static herr_t H5L__exists_api_common(hid_t loc_id, const char *name, bool *exists, hid_t lapl_id,
58
                                     void **token_ptr, H5VL_object_t **_vol_obj_ptr);
59
static herr_t H5L__iterate_api_common(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order,
60
                                      hsize_t *idx_p, H5L_iterate2_t op, void *op_data, void **token_ptr,
61
                                      H5VL_object_t **_vol_obj_ptr);
62
63
/*********************/
64
/* Package Variables */
65
/*********************/
66
67
/*****************************/
68
/* Library Private Variables */
69
/*****************************/
70
71
/*******************/
72
/* Local Variables */
73
/*******************/
74
75
/*-------------------------------------------------------------------------
76
 * Function:    H5Lmove
77
 *
78
 * Purpose:     Renames an object within an HDF5 file and moves it to a new
79
 *              group.  The original name SRC is unlinked from the group graph
80
 *              and then inserted with the new name DST (which can specify a
81
 *              new path for the object) as an atomic operation. The names
82
 *              are interpreted relative to SRC_LOC_ID and DST_LOC_ID,
83
 *              which are either file IDs or group ID.
84
 *
85
 * Return:      Non-negative on success/Negative on failure
86
 *
87
 *-------------------------------------------------------------------------
88
 */
89
herr_t
90
H5Lmove(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, const char *dst_name, hid_t lcpl_id,
91
        hid_t lapl_id)
92
0
{
93
0
    H5VL_object_t    *vol_obj1 = NULL; /* Object of src_id */
94
0
    H5VL_object_t    *vol_obj2 = NULL; /* Object of dst_id */
95
0
    H5VL_loc_params_t loc_params1;
96
0
    H5VL_loc_params_t loc_params2;
97
0
    H5I_type_t        src_id_type = H5I_BADID, dst_id_type = H5I_BADID;
98
0
    herr_t            ret_value = SUCCEED; /* Return value */
99
100
0
    FUNC_ENTER_API(FAIL)
101
102
    /* Check arguments */
103
0
    if (src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC)
104
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC");
105
0
    if (!src_name || !*src_name)
106
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified");
107
0
    if (!dst_name || !*dst_name)
108
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination name specified");
109
110
    /* reset an ID in the case of H5L_SAME_LOC */
111
0
    if (src_loc_id == H5L_SAME_LOC)
112
0
        src_loc_id = dst_loc_id;
113
0
    else if (dst_loc_id == H5L_SAME_LOC)
114
0
        dst_loc_id = src_loc_id;
115
116
    /* verify that src and dst IDs are either a file or a group ID */
117
0
    src_id_type = H5I_get_type(src_loc_id);
118
0
    if (!(H5I_GROUP == src_id_type || H5I_FILE == src_id_type))
119
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group (or file) ID, src_loc_id");
120
0
    dst_id_type = H5I_get_type(dst_loc_id);
121
0
    if (!(H5I_GROUP == dst_id_type || H5I_FILE == dst_id_type))
122
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group (or file) ID, dst_loc_id");
123
124
0
    if (lcpl_id != H5P_DEFAULT && (true != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
125
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list");
126
127
    /* Check the link create property list */
128
0
    if (H5P_DEFAULT == lcpl_id)
129
0
        lcpl_id = H5P_LINK_CREATE_DEFAULT;
130
131
    /* Set the LCPL for the API context */
132
0
    H5CX_set_lcpl(lcpl_id);
133
134
    /* Verify access property list and set up collective metadata if appropriate */
135
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, dst_loc_id, true) < 0)
136
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
137
138
    /* Set location parameter for source object */
139
0
    loc_params1.type                         = H5VL_OBJECT_BY_NAME;
140
0
    loc_params1.loc_data.loc_by_name.name    = src_name;
141
0
    loc_params1.loc_data.loc_by_name.lapl_id = lapl_id;
142
0
    loc_params1.obj_type                     = src_id_type;
143
144
    /* Set location parameter for destination object */
145
0
    loc_params2.type                         = H5VL_OBJECT_BY_NAME;
146
0
    loc_params2.loc_data.loc_by_name.name    = dst_name;
147
0
    loc_params2.loc_data.loc_by_name.lapl_id = lapl_id;
148
0
    loc_params2.obj_type                     = dst_id_type;
149
150
    /* Get the location object */
151
0
    if (NULL == (vol_obj1 = H5VL_vol_object(src_loc_id)))
152
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
153
    /* Get the location object */
154
0
    if (NULL == (vol_obj2 = H5VL_vol_object(dst_loc_id)))
155
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
156
157
    /* Make sure that the VOL connectors are the same */
158
0
    if (vol_obj1 && vol_obj2) {
159
0
        htri_t same_connector;
160
161
        /* Check if both objects are associated with the same VOL connector */
162
0
        if ((same_connector =
163
0
                 H5VL_conn_same_class(H5VL_OBJ_CONNECTOR(vol_obj1), H5VL_OBJ_CONNECTOR(vol_obj2))) < 0)
164
0
            HGOTO_ERROR(H5E_LINK, H5E_CANTCOMPARE, FAIL, "can't compare connector classes");
165
0
        if (!same_connector)
166
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
167
0
                        "Objects are accessed through different VOL connectors and can't be linked");
168
0
    }
169
170
    /* Move the link */
171
0
    if (H5VL_link_move(vol_obj1, &loc_params1, vol_obj2, &loc_params2, lcpl_id, lapl_id,
172
0
                       H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
173
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTMOVE, FAIL, "unable to move link");
174
175
0
done:
176
0
    FUNC_LEAVE_API(ret_value)
177
0
} /* end H5Lmove() */
178
179
/*-------------------------------------------------------------------------
180
 * Function:    H5Lcopy
181
 *
182
 * Purpose:     Creates an identical copy of a link with the same creation
183
 *              time and target.  The new link can have a different name
184
 *              and be in a different location than the original.
185
 *
186
 * Return:      Non-negative on success/Negative on failure
187
 *
188
 *-------------------------------------------------------------------------
189
 */
190
herr_t
191
H5Lcopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, const char *dst_name, hid_t lcpl_id,
192
        hid_t lapl_id)
193
0
{
194
0
    H5VL_object_t    *vol_obj1 = NULL; /* Object of src_id */
195
0
    H5VL_loc_params_t loc_params1;
196
0
    H5VL_object_t    *vol_obj2 = NULL; /* Object of dst_id */
197
0
    H5VL_loc_params_t loc_params2;
198
0
    H5I_type_t        src_id_type = H5I_BADID, dst_id_type = H5I_BADID;
199
0
    herr_t            ret_value = SUCCEED; /* Return value */
200
201
0
    FUNC_ENTER_API(FAIL)
202
203
    /* Check arguments */
204
0
    if (src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC)
205
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC");
206
0
    if (!src_name || !*src_name)
207
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified");
208
0
    if (!dst_name || !*dst_name)
209
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination name specified");
210
0
    if (lcpl_id != H5P_DEFAULT && (true != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
211
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list");
212
213
    /* reset an ID in the case of H5L_SAME_LOC */
214
0
    if (src_loc_id == H5L_SAME_LOC)
215
0
        src_loc_id = dst_loc_id;
216
0
    else if (dst_loc_id == H5L_SAME_LOC)
217
0
        dst_loc_id = src_loc_id;
218
219
    /* verify that src and dst IDs are either a file or a group ID */
220
0
    src_id_type = H5I_get_type(src_loc_id);
221
0
    if (!(H5I_GROUP == src_id_type || H5I_FILE == src_id_type) && src_loc_id != H5L_SAME_LOC)
222
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group (or file) ID, src_loc_id");
223
0
    dst_id_type = H5I_get_type(dst_loc_id);
224
0
    if (!(H5I_GROUP == dst_id_type || H5I_FILE == dst_id_type) && dst_loc_id != H5L_SAME_LOC)
225
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group (or file) ID, dst_loc_id");
226
227
    /* Check the link create property list */
228
0
    if (H5P_DEFAULT == lcpl_id)
229
0
        lcpl_id = H5P_LINK_CREATE_DEFAULT;
230
231
    /* Set the LCPL for the API context */
232
0
    H5CX_set_lcpl(lcpl_id);
233
234
    /* Verify access property list and set up collective metadata if appropriate */
235
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, ((src_loc_id != H5L_SAME_LOC) ? src_loc_id : dst_loc_id), true) <
236
0
        0)
237
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
238
239
    /* Set location parameter for source object */
240
0
    loc_params1.type                         = H5VL_OBJECT_BY_NAME;
241
0
    loc_params1.loc_data.loc_by_name.name    = src_name;
242
0
    loc_params1.loc_data.loc_by_name.lapl_id = lapl_id;
243
0
    loc_params1.obj_type                     = src_id_type;
244
245
    /* Set location parameter for destination object */
246
0
    loc_params2.type                         = H5VL_OBJECT_BY_NAME;
247
0
    loc_params2.loc_data.loc_by_name.name    = dst_name;
248
0
    loc_params2.loc_data.loc_by_name.lapl_id = lapl_id;
249
0
    loc_params2.obj_type                     = dst_id_type;
250
251
    /* Get the location object */
252
0
    if (NULL == (vol_obj1 = H5VL_vol_object(src_loc_id)))
253
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
254
    /* Get the location object */
255
0
    if (NULL == (vol_obj2 = H5VL_vol_object(dst_loc_id)))
256
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
257
258
    /* Make sure that the VOL connectors are the same */
259
0
    if (vol_obj1 && vol_obj2) {
260
0
        htri_t same_connector;
261
262
        /* Check if both objects are associated with the same VOL connector */
263
0
        if ((same_connector =
264
0
                 H5VL_conn_same_class(H5VL_OBJ_CONNECTOR(vol_obj1), H5VL_OBJ_CONNECTOR(vol_obj2))) < 0)
265
0
            HGOTO_ERROR(H5E_LINK, H5E_CANTCOMPARE, FAIL, "can't compare connector classes");
266
0
        if (!same_connector)
267
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
268
0
                        "Objects are accessed through different VOL connectors and can't be linked");
269
0
    } /* end if */
270
271
    /* Copy the link */
272
0
    if (H5VL_link_copy(vol_obj1, &loc_params1, vol_obj2, &loc_params2, lcpl_id, lapl_id,
273
0
                       H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
274
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTMOVE, FAIL, "unable to copy link");
275
276
0
done:
277
0
    FUNC_LEAVE_API(ret_value)
278
0
} /* end H5Lcopy() */
279
280
/*-------------------------------------------------------------------------
281
 * Function:    H5L__create_soft_api_common
282
 *
283
 * Purpose:     This is the common function for creating a soft link
284
 *
285
 * Return:      Non-negative on success/Negative on failure
286
 *
287
 *-------------------------------------------------------------------------
288
 */
289
static herr_t
290
H5L__create_soft_api_common(const char *link_target, hid_t link_loc_id, const char *link_name, hid_t lcpl_id,
291
                            hid_t lapl_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr)
292
0
{
293
0
    H5VL_object_t  *tmp_vol_obj = NULL; /* Object for loc_id */
294
0
    H5VL_object_t **vol_obj_ptr =
295
0
        (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */
296
0
    H5VL_link_create_args_t vol_cb_args;              /* Arguments to VOL callback */
297
0
    H5VL_loc_params_t       loc_params;               /* Location parameters for object access */
298
0
    herr_t                  ret_value = SUCCEED;      /* Return value */
299
300
0
    FUNC_ENTER_PACKAGE
301
302
    /* Check arguments */
303
0
    if (link_loc_id == H5L_SAME_LOC)
304
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link location id should not be H5L_SAME_LOC");
305
0
    if (!link_target)
306
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link_target parameter cannot be NULL");
307
0
    if (!*link_target)
308
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link_target parameter cannot be an empty string");
309
0
    if (lcpl_id != H5P_DEFAULT && (true != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
310
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list");
311
    /* link_name is verified in H5VL_setup_name_args() */
312
313
    /* Get the link creation property list */
314
0
    if (H5P_DEFAULT == lcpl_id)
315
0
        lcpl_id = H5P_LINK_CREATE_DEFAULT;
316
317
    /* Set the LCPL for the API context */
318
0
    H5CX_set_lcpl(lcpl_id);
319
320
    /* Verify access property list and set up collective metadata if appropriate */
321
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, link_loc_id, true) < 0)
322
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
323
324
    /* Set up object access arguments */
325
0
    if (H5VL_setup_name_args(link_loc_id, link_name, true, lapl_id, vol_obj_ptr, &loc_params) < 0)
326
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set object access arguments");
327
328
    /* Set up VOL callback arguments */
329
0
    vol_cb_args.op_type          = H5VL_LINK_CREATE_SOFT;
330
0
    vol_cb_args.args.soft.target = link_target;
331
332
    /* Create the link */
333
0
    if (H5VL_link_create(&vol_cb_args, *vol_obj_ptr, &loc_params, lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT,
334
0
                         token_ptr) < 0)
335
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to create soft link");
336
337
0
done:
338
0
    FUNC_LEAVE_NOAPI(ret_value)
339
0
} /* H5L__create_soft_api_common() */
340
341
/*-------------------------------------------------------------------------
342
 * Function:    H5Lcreate_soft
343
 *
344
 * Purpose:     Creates a soft link from LINK_NAME to LINK_TARGET.
345
 *
346
 *              LINK_TARGET can be anything and is interpreted at lookup
347
 *              time relative to the group which contains the final component
348
 *              of LINK_NAME.  For instance, if LINK_TARGET is `./foo' and
349
 *              LINK_NAME is `./x/y/bar' and a request is made for `./x/y/bar'
350
 *              then the actual object looked up is `./x/y/./foo'.
351
 *
352
 * Return:      Non-negative on success/Negative on failure
353
 *
354
 *-------------------------------------------------------------------------
355
 */
356
herr_t
357
H5Lcreate_soft(const char *link_target, hid_t link_loc_id, const char *link_name, hid_t lcpl_id,
358
               hid_t lapl_id)
359
0
{
360
0
    herr_t ret_value = SUCCEED; /* Return value */
361
362
0
    FUNC_ENTER_API(FAIL)
363
364
    /* Creates a soft link synchronously */
365
0
    if (H5L__create_soft_api_common(link_target, link_loc_id, link_name, lcpl_id, lapl_id, NULL, NULL) < 0)
366
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to synchronously create soft link");
367
368
0
done:
369
0
    FUNC_LEAVE_API(ret_value)
370
0
} /* end H5Lcreate_soft() */
371
372
/*-------------------------------------------------------------------------
373
 * Function:    H5Lcreate_soft_async
374
 *
375
 * Purpose:     Asynchronous version of H5Lcreate_soft
376
 *
377
 * Return:      Non-negative on success/Negative on failure
378
 *
379
 *-------------------------------------------------------------------------
380
 */
381
herr_t
382
H5Lcreate_soft_async(const char *app_file, const char *app_func, unsigned app_line, const char *link_target,
383
                     hid_t link_loc_id, const char *link_name, hid_t lcpl_id, hid_t lapl_id, hid_t es_id)
384
0
{
385
0
    H5VL_object_t *vol_obj   = NULL;            /* Object for loc_id */
386
0
    void          *token     = NULL;            /* Request token for async operation        */
387
0
    void         **token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation        */
388
0
    herr_t         ret_value = SUCCEED;         /* Return value */
389
390
0
    FUNC_ENTER_API(FAIL)
391
392
    /* Set up request token pointer for asynchronous operation */
393
0
    if (H5ES_NONE != es_id)
394
0
        token_ptr = &token; /* Point at token for VOL connector to set up */
395
396
    /* Creates a soft link asynchronously */
397
0
    if (H5L__create_soft_api_common(link_target, link_loc_id, link_name, lcpl_id, lapl_id, token_ptr,
398
0
                                    &vol_obj) < 0)
399
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to asynchronously create soft link");
400
401
    /* If a token was created, add the token to the event set */
402
0
    if (NULL != token)
403
        /* clang-format off */
404
0
        if (H5ES_insert(es_id, H5VL_OBJ_CONNECTOR(vol_obj), token,
405
0
                        H5ARG_TRACE9(__func__, "*s*sIu*si*siii", app_file, app_func, app_line, link_target, link_loc_id, link_name, lcpl_id, lapl_id, es_id)) < 0)
406
            /* clang-format on */
407
0
            HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set");
408
409
0
done:
410
0
    FUNC_LEAVE_API(ret_value)
411
0
} /* H5Lcreate_soft_async() */
412
413
/*-------------------------------------------------------------------------
414
 * Function:    H5L__create_hard_api_common
415
 *
416
 * Purpose:     This is the common function for creating a hard link
417
 *
418
 * Return:      Non-negative on success/Negative on failure
419
 *
420
 *-------------------------------------------------------------------------
421
 */
422
static herr_t
423
H5L__create_hard_api_common(hid_t cur_loc_id, const char *cur_name, hid_t link_loc_id, const char *link_name,
424
                            hid_t lcpl_id, hid_t lapl_id, void **token_ptr, H5VL_connector_t **connector)
425
0
{
426
0
    H5VL_object_t          *curr_vol_obj = NULL; /* Object of cur_loc_id */
427
0
    H5VL_object_t          *link_vol_obj = NULL; /* Object of link_loc_id */
428
0
    H5VL_link_create_args_t vol_cb_args;         /* Arguments to VOL callback */
429
0
    H5VL_loc_params_t       link_loc_params;     /* Location parameters for link_loc_id object access */
430
0
    herr_t                  ret_value = SUCCEED; /* Return value */
431
432
0
    FUNC_ENTER_PACKAGE
433
434
    /* Check arguments */
435
0
    if (cur_loc_id == H5L_SAME_LOC && link_loc_id == H5L_SAME_LOC)
436
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not be both H5L_SAME_LOC");
437
0
    if (!cur_name)
438
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cur_name parameter cannot be NULL");
439
0
    if (!*cur_name)
440
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cur_name parameter cannot be an empty string");
441
0
    if (!link_name)
442
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "new_name parameter cannot be NULL");
443
0
    if (!*link_name)
444
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "new_name parameter cannot be an empty string");
445
0
    if (lcpl_id != H5P_DEFAULT && (true != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
446
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list");
447
448
    /* Check the link create property list */
449
0
    if (H5P_DEFAULT == lcpl_id)
450
0
        lcpl_id = H5P_LINK_CREATE_DEFAULT;
451
452
    /* Set the LCPL for the API context */
453
0
    H5CX_set_lcpl(lcpl_id);
454
455
    /* Verify access property list and set up collective metadata if appropriate */
456
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, cur_loc_id, true) < 0)
457
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
458
459
0
    if (H5L_SAME_LOC != cur_loc_id)
460
        /* Get the current location object */
461
0
        if (NULL == (curr_vol_obj = H5VL_vol_object(cur_loc_id)))
462
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
463
0
    if (H5L_SAME_LOC != link_loc_id)
464
        /* Get the new location object */
465
0
        if (NULL == (link_vol_obj = H5VL_vol_object(link_loc_id)))
466
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
467
468
    /* Make sure that the VOL connectors are the same */
469
0
    if (curr_vol_obj && link_vol_obj) {
470
0
        htri_t same_connector;
471
472
        /* Check if both objects are associated with the same VOL connector */
473
0
        if ((same_connector = H5VL_conn_same_class(H5VL_OBJ_CONNECTOR(curr_vol_obj),
474
0
                                                   H5VL_OBJ_CONNECTOR(link_vol_obj))) < 0)
475
0
            HGOTO_ERROR(H5E_LINK, H5E_CANTCOMPARE, FAIL, "can't compare connector classes");
476
0
        if (!same_connector)
477
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
478
0
                        "Objects are accessed through different VOL connectors and can't be linked");
479
0
    } /* end if */
480
481
    /* Set up new location struct */
482
0
    link_loc_params.type     = H5VL_OBJECT_BY_NAME;
483
0
    link_loc_params.obj_type = (link_vol_obj ? H5I_get_type(link_loc_id) : H5I_get_type(cur_loc_id));
484
0
    link_loc_params.loc_data.loc_by_name.name    = link_name;
485
0
    link_loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
486
487
    /* Set up VOL callback arguments */
488
0
    vol_cb_args.op_type                        = H5VL_LINK_CREATE_HARD;
489
0
    vol_cb_args.args.hard.curr_obj             = (curr_vol_obj ? H5VL_OBJ_DATA(curr_vol_obj) : NULL);
490
0
    vol_cb_args.args.hard.curr_loc_params.type = H5VL_OBJECT_BY_NAME;
491
0
    vol_cb_args.args.hard.curr_loc_params.obj_type =
492
0
        (H5L_SAME_LOC != cur_loc_id ? H5I_get_type(cur_loc_id) : H5I_BADID);
493
0
    vol_cb_args.args.hard.curr_loc_params.loc_data.loc_by_name.name    = cur_name;
494
0
    vol_cb_args.args.hard.curr_loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
495
496
    /* Create the link */
497
0
    if (H5VL_link_create(&vol_cb_args, (link_vol_obj ? link_vol_obj : curr_vol_obj), &link_loc_params,
498
0
                         lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT, token_ptr) < 0)
499
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to create hard link");
500
501
    /* Set the connector to use for async operations */
502
0
    if (connector)
503
0
        *connector = (link_vol_obj ? H5VL_OBJ_CONNECTOR(link_vol_obj) : H5VL_OBJ_CONNECTOR(curr_vol_obj));
504
505
0
done:
506
0
    FUNC_LEAVE_NOAPI(ret_value)
507
0
} /* H5L__create_hard_api_common() */
508
509
/*-------------------------------------------------------------------------
510
 * Function:    H5Lcreate_hard
511
 *
512
 * Purpose:     Creates a hard link from NEW_NAME to CUR_NAME.
513
 *
514
 *              CUR_NAME must name an existing object.  CUR_NAME and
515
 *              NEW_NAME are interpreted relative to CUR_LOC_ID and
516
 *              NEW_LOC_ID, which are either file IDs or group IDs.
517
 *
518
 * Return:      Non-negative on success/Negative on failure
519
 *
520
 *-------------------------------------------------------------------------
521
 */
522
herr_t
523
H5Lcreate_hard(hid_t cur_loc_id, const char *cur_name, hid_t new_loc_id, const char *new_name, hid_t lcpl_id,
524
               hid_t lapl_id)
525
0
{
526
0
    herr_t ret_value = SUCCEED; /* Return value */
527
528
0
    FUNC_ENTER_API(FAIL)
529
530
    /* Creates a hard link synchronously */
531
0
    if (H5L__create_hard_api_common(cur_loc_id, cur_name, new_loc_id, new_name, lcpl_id, lapl_id, NULL,
532
0
                                    NULL) < 0)
533
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to synchronously create hard link");
534
535
0
done:
536
0
    FUNC_LEAVE_API(ret_value)
537
0
} /* end H5Lcreate_hard() */
538
539
/*-------------------------------------------------------------------------
540
 * Function:    H5Lcreate_hard_async
541
 *
542
 * Purpose:     Asynchronous version of H5Lcreate_hard
543
 *
544
 * Note:        The implementation for this routine is different from other
545
 *              _async operations, as the 'api_common' routine needs a "real"
546
 *              H5VL_object_t to point at, which is usually provided by the
547
 *              loc_id, but isn't here.
548
 *
549
 * Return:      Non-negative on success/Negative on failure
550
 *
551
 *-------------------------------------------------------------------------
552
 */
553
herr_t
554
H5Lcreate_hard_async(const char *app_file, const char *app_func, unsigned app_line, hid_t cur_loc_id,
555
                     const char *cur_name, hid_t new_loc_id, const char *new_name, hid_t lcpl_id,
556
                     hid_t lapl_id, hid_t es_id)
557
0
{
558
0
    H5VL_connector_t *connector = NULL;            /* Connector for operation */
559
0
    void             *token     = NULL;            /* Request token for async operation        */
560
0
    void            **token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation        */
561
0
    herr_t            ret_value = SUCCEED;         /* Return value */
562
563
0
    FUNC_ENTER_API(FAIL)
564
565
    /* Set up request token pointer for asynchronous operation */
566
0
    if (H5ES_NONE != es_id)
567
0
        token_ptr = &token; /* Point at token for VOL connector to set up */
568
569
    /* Creates a hard link asynchronously */
570
0
    if (H5L__create_hard_api_common(cur_loc_id, cur_name, new_loc_id, new_name, lcpl_id, lapl_id, token_ptr,
571
0
                                    &connector) < 0)
572
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTCREATE, FAIL, "unable to asynchronously create hard link");
573
0
    assert(connector);
574
575
    /* If a token was created, add the token to the event set */
576
0
    if (NULL != token)
577
        /* clang-format off */
578
0
        if (H5ES_insert(es_id, connector, token,
579
0
                        H5ARG_TRACE10(__func__, "*s*sIui*si*siii", app_file, app_func, app_line, cur_loc_id, cur_name, new_loc_id, new_name, lcpl_id, lapl_id, es_id)) < 0)
580
            /* clang-format on */
581
0
            HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set");
582
583
0
done:
584
0
    FUNC_LEAVE_API(ret_value)
585
0
} /* H5Lcreate_hard_async() */
586
587
/*-------------------------------------------------------------------------
588
 * Function:    H5Lcreate_external
589
 *
590
 * Purpose:     Creates an external link from LINK_NAME to OBJ_NAME.
591
 *
592
 *              External links are links to objects in other HDF5 files.  They
593
 *              are allowed to "dangle" like soft links internal to a file.
594
 *              FILE_NAME is the name of the file that OBJ_NAME is contained
595
 *              within.  If OBJ_NAME is given as a relative path name, the
596
 *              path will be relative to the root group of FILE_NAME.
597
 *              LINK_NAME is interpreted relative to LINK_LOC_ID, which is
598
 *              either a file ID or a group ID.
599
 *
600
 * Return:      Non-negative on success/Negative on failure
601
 *
602
 *-------------------------------------------------------------------------
603
 */
604
herr_t
605
H5Lcreate_external(const char *file_name, const char *obj_name, hid_t link_loc_id, const char *link_name,
606
                   hid_t lcpl_id, hid_t lapl_id)
607
0
{
608
0
    H5VL_object_t          *vol_obj = NULL;       /* Object of loc_id */
609
0
    H5VL_link_create_args_t vol_cb_args;          /* Arguments to VOL callback */
610
0
    H5VL_loc_params_t       loc_params;           /* Location parameters for object access */
611
0
    char                   *norm_obj_name = NULL; /* Pointer to normalized current name */
612
0
    void                   *ext_link_buf  = NULL; /* Buffer to contain external link */
613
0
    size_t                  buf_size;             /* Size of buffer to hold external link */
614
0
    size_t                  file_name_len;        /* Length of file name string */
615
0
    size_t                  norm_obj_name_len;    /* Length of normalized object name string */
616
0
    uint8_t                *p;                    /* Pointer into external link buffer */
617
0
    herr_t                  ret_value = SUCCEED;  /* Return value */
618
619
0
    FUNC_ENTER_API(FAIL)
620
621
    /* Check arguments */
622
0
    if (!file_name || !*file_name)
623
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no file name specified");
624
0
    if (!obj_name || !*obj_name)
625
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name specified");
626
0
    if (!link_name || !*link_name)
627
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no link name specified");
628
629
    /* Get the link creation property list */
630
0
    if (H5P_DEFAULT == lcpl_id)
631
0
        lcpl_id = H5P_LINK_CREATE_DEFAULT;
632
633
    /* Set the LCPL for the API context */
634
0
    H5CX_set_lcpl(lcpl_id);
635
636
    /* Verify access property list and set up collective metadata if appropriate */
637
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, link_loc_id, true) < 0)
638
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
639
640
    /* Get normalized copy of the link target */
641
0
    if (NULL == (norm_obj_name = H5G_normalize(obj_name)))
642
0
        HGOTO_ERROR(H5E_LINK, H5E_BADVALUE, FAIL, "can't normalize object name");
643
644
    /* Combine the filename and link name into a single buffer to give to the UD link */
645
0
    file_name_len     = strlen(file_name) + 1;
646
0
    norm_obj_name_len = strlen(norm_obj_name) + 1;
647
0
    buf_size          = 1 + file_name_len + norm_obj_name_len;
648
0
    if (NULL == (ext_link_buf = H5MM_malloc(buf_size)))
649
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate udata buffer");
650
651
    /* Encode the external link information */
652
0
    p    = (uint8_t *)ext_link_buf;
653
0
    *p++ = (H5L_EXT_VERSION << 4) | H5L_EXT_FLAGS_ALL; /* External link version & flags */
654
0
    strncpy((char *)p, file_name, buf_size - 1);       /* Name of file containing external link's object */
655
0
    p += file_name_len;
656
0
    strncpy((char *)p, norm_obj_name, buf_size - (file_name_len + 1)); /* External link's object */
657
658
0
    loc_params.type                         = H5VL_OBJECT_BY_NAME;
659
0
    loc_params.loc_data.loc_by_name.name    = link_name;
660
0
    loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
661
0
    loc_params.obj_type                     = H5I_get_type(link_loc_id);
662
663
    /* get the location object */
664
0
    if (NULL == (vol_obj = H5VL_vol_object(link_loc_id)))
665
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier");
666
667
    /* Set up VOL callback arguments */
668
0
    vol_cb_args.op_type          = H5VL_LINK_CREATE_UD;
669
0
    vol_cb_args.args.ud.type     = H5L_TYPE_EXTERNAL;
670
0
    vol_cb_args.args.ud.buf      = ext_link_buf;
671
0
    vol_cb_args.args.ud.buf_size = buf_size;
672
673
    /* Create an external link */
674
0
    if (H5VL_link_create(&vol_cb_args, vol_obj, &loc_params, lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT,
675
0
                         H5_REQUEST_NULL) < 0)
676
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create external link");
677
678
0
done:
679
0
    H5MM_xfree(ext_link_buf);
680
0
    H5MM_xfree(norm_obj_name);
681
682
0
    FUNC_LEAVE_API(ret_value)
683
0
} /* end H5Lcreate_external() */
684
685
/*-------------------------------------------------------------------------
686
 * Function:    H5Lcreate_ud
687
 *
688
 * Purpose:     Creates a user-defined link of type LINK_TYPE named LINK_NAME
689
 *              with user-specified data UDATA.
690
 *
691
 *              The format of the information pointed to by UDATA is
692
 *              defined by the user. UDATA_SIZE holds the size of this buffer.
693
 *
694
 *              LINK_NAME is interpreted relative to LINK_LOC_ID.
695
 *
696
 *              The property list specified by LCPL_ID holds properties used
697
 *              to create the link.
698
 *
699
 *              The link class of the new link must already be registered
700
 *              with the library.
701
 *
702
 * Return:      Non-negative on success/Negative on failure
703
 *
704
 *-------------------------------------------------------------------------
705
 */
706
herr_t
707
H5Lcreate_ud(hid_t link_loc_id, const char *link_name, H5L_type_t link_type, const void *udata,
708
             size_t udata_size, hid_t lcpl_id, hid_t lapl_id)
709
0
{
710
0
    H5VL_object_t          *vol_obj = NULL;      /* Object of loc_id */
711
0
    H5VL_link_create_args_t vol_cb_args;         /* Arguments to VOL callback */
712
0
    H5VL_loc_params_t       loc_params;          /* Location parameters for object access */
713
0
    herr_t                  ret_value = SUCCEED; /* Return value */
714
715
0
    FUNC_ENTER_API(FAIL)
716
717
    /* Check arguments */
718
0
    if (!link_name || !*link_name)
719
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no link name specified");
720
0
    if (link_type < H5L_TYPE_UD_MIN || link_type > H5L_TYPE_MAX)
721
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link class");
722
0
    if (!udata && udata_size)
723
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "udata cannot be NULL if udata_size is non-zero");
724
725
    /* Get the link creation property list */
726
0
    if (H5P_DEFAULT == lcpl_id)
727
0
        lcpl_id = H5P_LINK_CREATE_DEFAULT;
728
729
    /* Set the LCPL for the API context */
730
0
    H5CX_set_lcpl(lcpl_id);
731
732
    /* Verify access property list and set up collective metadata if appropriate */
733
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, link_loc_id, true) < 0)
734
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
735
736
0
    loc_params.type                         = H5VL_OBJECT_BY_NAME;
737
0
    loc_params.loc_data.loc_by_name.name    = link_name;
738
0
    loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
739
0
    loc_params.obj_type                     = H5I_get_type(link_loc_id);
740
741
    /* get the location object */
742
0
    if (NULL == (vol_obj = H5VL_vol_object(link_loc_id)))
743
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
744
745
    /* Set up VOL callback arguments */
746
0
    vol_cb_args.op_type          = H5VL_LINK_CREATE_UD;
747
0
    vol_cb_args.args.ud.type     = link_type;
748
0
    vol_cb_args.args.ud.buf      = udata;
749
0
    vol_cb_args.args.ud.buf_size = udata_size;
750
751
    /* Create user-defined link */
752
0
    if (H5VL_link_create(&vol_cb_args, vol_obj, &loc_params, lcpl_id, lapl_id, H5P_DATASET_XFER_DEFAULT,
753
0
                         H5_REQUEST_NULL) < 0)
754
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link");
755
756
0
done:
757
0
    FUNC_LEAVE_API(ret_value)
758
0
} /* end H5Lcreate_ud() */
759
760
/*-------------------------------------------------------------------------
761
 * Function:    H5L__delete_api_common
762
 *
763
 * Purpose:     This is the common function for deleting a link
764
 *
765
 * Return:      Non-negative on success/Negative on failure
766
 *
767
 *-------------------------------------------------------------------------
768
 */
769
static herr_t
770
H5L__delete_api_common(hid_t loc_id, const char *name, hid_t lapl_id, void **token_ptr,
771
                       H5VL_object_t **_vol_obj_ptr)
772
0
{
773
0
    H5VL_object_t  *tmp_vol_obj = NULL; /* Object for loc_id */
774
0
    H5VL_object_t **vol_obj_ptr =
775
0
        (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */
776
0
    H5VL_link_specific_args_t vol_cb_args;            /* Arguments to VOL callback */
777
0
    H5VL_loc_params_t         loc_params;             /* Location parameters for object access */
778
0
    herr_t                    ret_value = SUCCEED;    /* Return value */
779
780
0
    FUNC_ENTER_PACKAGE
781
782
    /* Check arguments */
783
    /* name is verified in H5VL_setup_name_args() */
784
785
    /* Set up object access arguments */
786
0
    if (H5VL_setup_name_args(loc_id, name, true, lapl_id, vol_obj_ptr, &loc_params) < 0)
787
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set object access arguments");
788
789
    /* Set up VOL callback arguments */
790
0
    vol_cb_args.op_type = H5VL_LINK_DELETE;
791
792
    /* Delete link */
793
0
    if (H5VL_link_specific(*vol_obj_ptr, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, token_ptr) < 0)
794
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link");
795
796
0
done:
797
0
    FUNC_LEAVE_NOAPI(ret_value)
798
0
} /* H5L__delete_api_common() */
799
800
/*-------------------------------------------------------------------------
801
 * Function:    H5Ldelete
802
 *
803
 * Purpose:     Removes the specified NAME from the group graph and
804
 *              decrements the link count for the object to which NAME
805
 *              points. If the link count reaches zero then all file-space
806
 *              associated with the object will be reclaimed (but if the
807
 *              object is open, then the reclamation of the file space is
808
 *              delayed until all handles to the object are closed).
809
 *
810
 * Return:      Non-negative on success/Negative on failure
811
 *
812
 *-------------------------------------------------------------------------
813
 */
814
herr_t
815
H5Ldelete(hid_t loc_id, const char *name, hid_t lapl_id)
816
0
{
817
0
    herr_t ret_value = SUCCEED; /* Return value */
818
819
0
    FUNC_ENTER_API(FAIL)
820
821
    /* Delete a link synchronously */
822
0
    if (H5L__delete_api_common(loc_id, name, lapl_id, NULL, NULL) < 0)
823
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to synchronously delete link");
824
825
0
done:
826
0
    FUNC_LEAVE_API(ret_value)
827
0
} /* end H5Ldelete() */
828
829
/*-------------------------------------------------------------------------
830
 * Function:    H5Ldelete_async
831
 *
832
 * Purpose:     Asynchronous version of H5Ldelete
833
 *
834
 * Return:      Non-negative on success/Negative on failure
835
 *
836
 *-------------------------------------------------------------------------
837
 */
838
herr_t
839
H5Ldelete_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name,
840
                hid_t lapl_id, hid_t es_id)
841
0
{
842
0
    H5VL_object_t *vol_obj   = NULL;            /* Object for loc_id */
843
0
    void          *token     = NULL;            /* Request token for async operation        */
844
0
    void         **token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation        */
845
0
    herr_t         ret_value = SUCCEED;         /* Return value */
846
847
0
    FUNC_ENTER_API(FAIL)
848
849
    /* Set up request token pointer for asynchronous operation */
850
0
    if (H5ES_NONE != es_id)
851
0
        token_ptr = &token; /* Point at token for VOL connector to set up */
852
853
    /* Delete a link asynchronously */
854
0
    if (H5L__delete_api_common(loc_id, name, lapl_id, token_ptr, &vol_obj) < 0)
855
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to asynchronously delete link");
856
857
    /* If a token was created, add the token to the event set */
858
0
    if (NULL != token)
859
        /* clang-format off */
860
0
        if (H5ES_insert(es_id, H5VL_OBJ_CONNECTOR(vol_obj), token,
861
0
                        H5ARG_TRACE7(__func__, "*s*sIui*sii", app_file, app_func, app_line, loc_id, name, lapl_id, es_id)) < 0)
862
            /* clang-format on */
863
0
            HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set");
864
865
0
done:
866
0
    FUNC_LEAVE_API(ret_value)
867
0
} /* H5Ldelete_async() */
868
869
/*-------------------------------------------------------------------------
870
 * Function:    H5L__delete_by_idx_api_common
871
 *
872
 * Purpose:     This is the common function for deleting a link
873
 *            according to the order within an index.
874
 *
875
 * Return:      Non-negative on success/Negative on failure
876
 *
877
 *-------------------------------------------------------------------------
878
 */
879
static herr_t
880
H5L__delete_by_idx_api_common(hid_t loc_id, const char *group_name, H5_index_t idx_type,
881
                              H5_iter_order_t order, hsize_t n, hid_t lapl_id, void **token_ptr,
882
                              H5VL_object_t **_vol_obj_ptr)
883
0
{
884
0
    H5VL_object_t  *tmp_vol_obj = NULL; /* Object for loc_id */
885
0
    H5VL_object_t **vol_obj_ptr =
886
0
        (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */
887
0
    H5VL_link_specific_args_t vol_cb_args;            /* Arguments to VOL callback */
888
0
    H5VL_loc_params_t         loc_params;             /* Location parameters for object access */
889
0
    herr_t                    ret_value = SUCCEED;    /* Return value */
890
891
0
    FUNC_ENTER_PACKAGE
892
893
    /* Check arguments */
894
0
    if (!group_name || !*group_name)
895
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified");
896
0
    if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
897
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified");
898
0
    if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
899
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified");
900
901
    /* Set up object access arguments */
902
0
    if (H5VL_setup_idx_args(loc_id, group_name, idx_type, order, n, true, lapl_id, vol_obj_ptr, &loc_params) <
903
0
        0)
904
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set object access arguments");
905
906
    /* Set up VOL callback arguments */
907
0
    vol_cb_args.op_type = H5VL_LINK_DELETE;
908
909
    /* Delete the link */
910
0
    if (H5VL_link_specific(*vol_obj_ptr, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, token_ptr) < 0)
911
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link");
912
913
0
done:
914
0
    FUNC_LEAVE_NOAPI(ret_value)
915
0
} /* H5L__delete_by_idx_api_common() */
916
917
/*-------------------------------------------------------------------------
918
 * Function:  H5Ldelete_by_idx
919
 *
920
 * Purpose: Removes the specified link from the group graph and
921
 *    decrements the link count for the object to which it
922
 *    points, according to the order within an index.
923
 *
924
 *    If the link count reaches zero then all file-space
925
 *    associated with the object will be reclaimed (but if the
926
 *    object is open, then the reclamation of the file space is
927
 *    delayed until all handles to the object are closed).
928
 *
929
 * Return:  Non-negative on success/Negative on failure
930
 *
931
 *-------------------------------------------------------------------------
932
 */
933
herr_t
934
H5Ldelete_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
935
                 hid_t lapl_id)
936
0
{
937
0
    herr_t ret_value = SUCCEED; /* Return value */
938
939
0
    FUNC_ENTER_API(FAIL)
940
941
    /* Delete a link synchronously */
942
0
    if (H5L__delete_by_idx_api_common(loc_id, group_name, idx_type, order, n, lapl_id, NULL, NULL) < 0)
943
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to synchronously delete link");
944
945
0
done:
946
0
    FUNC_LEAVE_API(ret_value)
947
0
} /* end H5Ldelete_by_idx() */
948
949
/*-------------------------------------------------------------------------
950
 * Function:    H5Ldelete_by_idx_async
951
 *
952
 * Purpose:     Asynchronous version of H5Ldelete_by_idx
953
 *
954
 * Return:      Non-negative on success/Negative on failure
955
 *
956
 *-------------------------------------------------------------------------
957
 */
958
herr_t
959
H5Ldelete_by_idx_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id,
960
                       const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
961
                       hid_t lapl_id, hid_t es_id)
962
0
{
963
0
    H5VL_object_t *vol_obj   = NULL;            /* Object for loc_id */
964
0
    void          *token     = NULL;            /* Request token for async operation        */
965
0
    void         **token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation        */
966
0
    herr_t         ret_value = SUCCEED;         /* Return value */
967
968
0
    FUNC_ENTER_API(FAIL)
969
970
    /* Set up request token pointer for asynchronous operation */
971
0
    if (H5ES_NONE != es_id)
972
0
        token_ptr = &token; /* Point at token for VOL connector to set up */
973
974
    /* Delete a link asynchronously */
975
0
    if (H5L__delete_by_idx_api_common(loc_id, group_name, idx_type, order, n, lapl_id, token_ptr, &vol_obj) <
976
0
        0)
977
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to asynchronously delete link");
978
979
    /* If a token was created, add the token to the event set */
980
0
    if (NULL != token)
981
        /* clang-format off */
982
0
        if (H5ES_insert(es_id, H5VL_OBJ_CONNECTOR(vol_obj), token,
983
0
                        H5ARG_TRACE10(__func__, "*s*sIui*sIiIohii", app_file, app_func, app_line, loc_id, group_name, idx_type, order, n, lapl_id, es_id)) < 0)
984
            /* clang-format on */
985
0
            HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set");
986
987
0
done:
988
0
    FUNC_LEAVE_API(ret_value)
989
0
} /* H5Ldelete_by_idx_async() */
990
991
/*-------------------------------------------------------------------------
992
 * Function:  H5Lget_val
993
 *
994
 * Purpose: Returns the link value of a link whose name is NAME.  For
995
 *              symbolic links, this is the path to which the link points,
996
 *              including the null terminator.  For user-defined links, it
997
 *              is the link buffer.
998
 *
999
 *              At most SIZE bytes are copied to the BUF result buffer.
1000
 *
1001
 * Return:  Success:  Non-negative with the link value in BUF.
1002
 *
1003
 *    Failure:  Negative
1004
 *
1005
 *-------------------------------------------------------------------------
1006
 */
1007
herr_t
1008
H5Lget_val(hid_t loc_id, const char *name, void *buf /*out*/, size_t size, hid_t lapl_id)
1009
0
{
1010
0
    H5VL_object_t       *vol_obj = NULL;      /* object of loc_id */
1011
0
    H5VL_link_get_args_t vol_cb_args;         /* Arguments to VOL callback */
1012
0
    H5VL_loc_params_t    loc_params;          /* Location parameters for object access */
1013
0
    herr_t               ret_value = SUCCEED; /* Return value */
1014
1015
0
    FUNC_ENTER_API(FAIL)
1016
1017
    /* Check arguments */
1018
0
    if (!name || !*name)
1019
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified");
1020
1021
    /* Verify access property list and set up collective metadata if appropriate */
1022
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, false) < 0)
1023
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
1024
1025
    /* Set up location struct */
1026
0
    loc_params.type                         = H5VL_OBJECT_BY_NAME;
1027
0
    loc_params.obj_type                     = H5I_get_type(loc_id);
1028
0
    loc_params.loc_data.loc_by_name.name    = name;
1029
0
    loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
1030
1031
    /* Get the VOL object */
1032
0
    if (NULL == (vol_obj = H5VL_vol_object(loc_id)))
1033
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
1034
1035
    /* Set up VOL callback arguments */
1036
0
    vol_cb_args.op_type               = H5VL_LINK_GET_VAL;
1037
0
    vol_cb_args.args.get_val.buf      = buf;
1038
0
    vol_cb_args.args.get_val.buf_size = size;
1039
1040
    /* Get the link value */
1041
0
    if (H5VL_link_get(vol_obj, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
1042
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link value for '%s'", name);
1043
1044
0
done:
1045
0
    FUNC_LEAVE_API(ret_value)
1046
0
} /* end H5Lget_val() */
1047
1048
/*-------------------------------------------------------------------------
1049
 * Function:  H5Lget_val_by_idx
1050
 *
1051
 * Purpose: Returns the link value of a link, according to the order of
1052
 *              an index.  For symbolic links, this is the path to which the
1053
 *              link points, including the null terminator.  For user-defined
1054
 *              links, it is the link buffer.
1055
 *
1056
 *              At most SIZE bytes are copied to the BUF result buffer.
1057
 *
1058
 * Return:  Success:  Non-negative with the link value in BUF.
1059
 *    Failure:  Negative
1060
 *
1061
 *-------------------------------------------------------------------------
1062
 */
1063
herr_t
1064
H5Lget_val_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
1065
                  void *buf /*out*/, size_t size, hid_t lapl_id)
1066
0
{
1067
0
    H5VL_object_t       *vol_obj = NULL;      /* object of loc_id */
1068
0
    H5VL_link_get_args_t vol_cb_args;         /* Arguments to VOL callback */
1069
0
    H5VL_loc_params_t    loc_params;          /* Location parameters for object access */
1070
0
    herr_t               ret_value = SUCCEED; /* Return value */
1071
1072
0
    FUNC_ENTER_API(FAIL)
1073
1074
    /* Check arguments */
1075
0
    if (!group_name || !*group_name)
1076
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified");
1077
0
    if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1078
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified");
1079
0
    if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1080
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified");
1081
1082
    /* Verify access property list and set up collective metadata if appropriate */
1083
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, false) < 0)
1084
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
1085
1086
    /* Set up location struct */
1087
0
    loc_params.type                         = H5VL_OBJECT_BY_IDX;
1088
0
    loc_params.loc_data.loc_by_idx.name     = group_name;
1089
0
    loc_params.loc_data.loc_by_idx.idx_type = idx_type;
1090
0
    loc_params.loc_data.loc_by_idx.order    = order;
1091
0
    loc_params.loc_data.loc_by_idx.n        = n;
1092
0
    loc_params.loc_data.loc_by_idx.lapl_id  = lapl_id;
1093
0
    loc_params.obj_type                     = H5I_get_type(loc_id);
1094
1095
    /* Get the VOL object */
1096
0
    if (NULL == (vol_obj = H5VL_vol_object(loc_id)))
1097
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
1098
1099
    /* Set up VOL callback arguments */
1100
0
    vol_cb_args.op_type               = H5VL_LINK_GET_VAL;
1101
0
    vol_cb_args.args.get_val.buf      = buf;
1102
0
    vol_cb_args.args.get_val.buf_size = size;
1103
1104
    /* Get the link value */
1105
0
    if (H5VL_link_get(vol_obj, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
1106
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link value");
1107
1108
0
done:
1109
0
    FUNC_LEAVE_API(ret_value)
1110
0
} /* end H5Lget_val_by_idx() */
1111
1112
/*--------------------------------------------------------------------------
1113
 *  NAME
1114
 *      H5L__exists_api_common
1115
 *  PURPOSE
1116
 *      Common helper routine for sync/async check if an attribute exists
1117
 *  RETURNS
1118
 *      Non-negative on success/Negative on failure
1119
 *
1120
 *--------------------------------------------------------------------------*/
1121
static herr_t
1122
H5L__exists_api_common(hid_t loc_id, const char *name, bool *exists, hid_t lapl_id, void **token_ptr,
1123
                       H5VL_object_t **_vol_obj_ptr)
1124
978
{
1125
978
    H5VL_object_t  *tmp_vol_obj = NULL; /* Object for loc_id */
1126
978
    H5VL_object_t **vol_obj_ptr =
1127
978
        (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */
1128
978
    H5VL_link_specific_args_t vol_cb_args;            /* Arguments to VOL callback */
1129
978
    H5VL_loc_params_t         loc_params;             /* Location parameters for object access */
1130
978
    herr_t                    ret_value = SUCCEED;    /* Return value */
1131
1132
978
    FUNC_ENTER_PACKAGE
1133
1134
    /* Check arguments */
1135
    /* name is verified in H5VL_setup_name_args() */
1136
978
    if (NULL == exists)
1137
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer for link existence");
1138
1139
    /* Set up object access arguments */
1140
978
    if (H5VL_setup_name_args(loc_id, name, false, lapl_id, vol_obj_ptr, &loc_params) < 0)
1141
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set object access arguments");
1142
1143
    /* Set up VOL callback arguments */
1144
978
    vol_cb_args.op_type            = H5VL_LINK_EXISTS;
1145
978
    vol_cb_args.args.exists.exists = exists;
1146
1147
    /* Check for the existence of the link */
1148
978
    if (H5VL_link_specific(*vol_obj_ptr, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, token_ptr) < 0)
1149
8
        HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link info");
1150
1151
978
done:
1152
978
    FUNC_LEAVE_NOAPI(ret_value)
1153
978
} /* H5L__exists_api_common() */
1154
1155
/*-------------------------------------------------------------------------
1156
 * Function:    H5Lexists
1157
 *
1158
 * Purpose:     Checks if a link of a given name exists in a group
1159
 *
1160
 * Return:      Success:    true/false/FAIL
1161
 *
1162
 *-------------------------------------------------------------------------
1163
 */
1164
htri_t
1165
H5Lexists(hid_t loc_id, const char *name, hid_t lapl_id)
1166
978
{
1167
978
    bool   exists;           /* Flag to indicate if link exists */
1168
978
    htri_t ret_value = FAIL; /* Return value */
1169
1170
1.95k
    FUNC_ENTER_API(FAIL)
1171
1172
    /* Synchronously check if a link exists */
1173
1.95k
    exists = false;
1174
1.95k
    if (H5L__exists_api_common(loc_id, name, &exists, lapl_id, NULL, NULL) < 0)
1175
8
        HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to synchronously check link existence");
1176
1177
    /* Set return value */
1178
970
    ret_value = (htri_t)exists;
1179
1180
978
done:
1181
978
    FUNC_LEAVE_API(ret_value)
1182
970
} /* end H5Lexists() */
1183
1184
/*--------------------------------------------------------------------------
1185
 * Function:    H5Lexists_async
1186
 *
1187
 * Purpose:     Asynchronous version of H5Lexists
1188
 *
1189
 * Return:      Success:    true/false/FAIL
1190
 *
1191
 *--------------------------------------------------------------------------*/
1192
herr_t
1193
H5Lexists_async(const char *app_file, const char *app_func, unsigned app_line, hid_t loc_id, const char *name,
1194
                bool *exists, hid_t lapl_id, hid_t es_id)
1195
0
{
1196
0
    H5VL_object_t *vol_obj   = NULL;            /* Object for loc_id */
1197
0
    void          *token     = NULL;            /* Request token for async operation        */
1198
0
    void         **token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation        */
1199
0
    herr_t         ret_value = SUCCEED;         /* Return value */
1200
1201
0
    FUNC_ENTER_API(FAIL)
1202
1203
    /* Set up request token pointer for asynchronous operation */
1204
0
    if (H5ES_NONE != es_id)
1205
0
        token_ptr = &token; /* Point at token for VOL connector to set up */
1206
1207
    /* Asynchronously check if a link exists */
1208
0
    if (H5L__exists_api_common(loc_id, name, exists, lapl_id, token_ptr, &vol_obj) < 0)
1209
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to asynchronously check link existence");
1210
1211
    /* If a token was created, add the token to the event set */
1212
0
    if (NULL != token)
1213
0
        if (H5ES_insert(es_id, H5VL_OBJ_CONNECTOR(vol_obj), token,
1214
                        /* clang-format off */
1215
0
                        H5ARG_TRACE8(__func__, "*s*sIui*s*bii", app_file, app_func, app_line, loc_id, name, exists, lapl_id, es_id)) < 0)
1216
            /* clang-format on */
1217
0
            HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set");
1218
1219
0
done:
1220
0
    FUNC_LEAVE_API(ret_value)
1221
0
} /* H5Lexists_async() */
1222
1223
/*-------------------------------------------------------------------------
1224
 * Function:    H5Lget_info2
1225
 *
1226
 * Purpose:     Gets metadata for a link.
1227
 *
1228
 * Return:      Success:    Non-negative with information in LINFO
1229
 *              Failure:    Negative
1230
 *
1231
 *-------------------------------------------------------------------------
1232
 */
1233
herr_t
1234
H5Lget_info2(hid_t loc_id, const char *name, H5L_info2_t *linfo /*out*/, hid_t lapl_id)
1235
0
{
1236
0
    H5VL_object_t       *vol_obj = NULL;      /* object of loc_id */
1237
0
    H5VL_link_get_args_t vol_cb_args;         /* Arguments to VOL callback */
1238
0
    H5VL_loc_params_t    loc_params;          /* Location parameters for object access */
1239
0
    herr_t               ret_value = SUCCEED; /* Return value */
1240
1241
0
    FUNC_ENTER_API(FAIL)
1242
1243
    /* Check arguments */
1244
0
    if (!name || !*name)
1245
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified");
1246
1247
    /* Verify access property list and set up collective metadata if appropriate */
1248
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, true) < 0)
1249
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
1250
1251
    /* Set up location struct */
1252
0
    loc_params.type                         = H5VL_OBJECT_BY_NAME;
1253
0
    loc_params.obj_type                     = H5I_get_type(loc_id);
1254
0
    loc_params.loc_data.loc_by_name.name    = name;
1255
0
    loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
1256
1257
    /* Get the location object */
1258
0
    if (NULL == (vol_obj = H5VL_vol_object(loc_id)))
1259
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
1260
1261
    /* Set up VOL callback arguments */
1262
0
    vol_cb_args.op_type             = H5VL_LINK_GET_INFO;
1263
0
    vol_cb_args.args.get_info.linfo = linfo;
1264
1265
    /* Get the link information */
1266
0
    if (H5VL_link_get(vol_obj, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
1267
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link info");
1268
1269
0
done:
1270
0
    FUNC_LEAVE_API(ret_value)
1271
0
} /* end H5Lget_info2() */
1272
1273
/*-------------------------------------------------------------------------
1274
 * Function:    H5Lget_info_by_idx2
1275
 *
1276
 * Purpose:     Gets metadata for a link, according to the order within an
1277
 *              index.
1278
 *
1279
 * Return:      Success:    Non-negative with information in LINFO
1280
 *              Failure:    Negative
1281
 *
1282
 *-------------------------------------------------------------------------
1283
 */
1284
herr_t
1285
H5Lget_info_by_idx2(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order,
1286
                    hsize_t n, H5L_info2_t *linfo /*out*/, hid_t lapl_id)
1287
0
{
1288
0
    H5VL_object_t       *vol_obj = NULL;      /* object of loc_id */
1289
0
    H5VL_link_get_args_t vol_cb_args;         /* Arguments to VOL callback */
1290
0
    H5VL_loc_params_t    loc_params;          /* Location parameters for object access */
1291
0
    herr_t               ret_value = SUCCEED; /* Return value */
1292
1293
0
    FUNC_ENTER_API(FAIL)
1294
1295
    /* Check arguments */
1296
0
    if (!group_name || !*group_name)
1297
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified");
1298
0
    if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1299
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified");
1300
0
    if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1301
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified");
1302
1303
    /* Verify access property list and set up collective metadata if appropriate */
1304
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, false) < 0)
1305
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
1306
1307
    /* Set up location struct */
1308
0
    loc_params.type                         = H5VL_OBJECT_BY_IDX;
1309
0
    loc_params.loc_data.loc_by_idx.name     = group_name;
1310
0
    loc_params.loc_data.loc_by_idx.idx_type = idx_type;
1311
0
    loc_params.loc_data.loc_by_idx.order    = order;
1312
0
    loc_params.loc_data.loc_by_idx.n        = n;
1313
0
    loc_params.loc_data.loc_by_idx.lapl_id  = lapl_id;
1314
0
    loc_params.obj_type                     = H5I_get_type(loc_id);
1315
1316
    /* Get the location object */
1317
0
    if (NULL == (vol_obj = H5VL_vol_object(loc_id)))
1318
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
1319
1320
    /* Set up VOL callback arguments */
1321
0
    vol_cb_args.op_type             = H5VL_LINK_GET_INFO;
1322
0
    vol_cb_args.args.get_info.linfo = linfo;
1323
1324
    /* Get the link information */
1325
0
    if (H5VL_link_get(vol_obj, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
1326
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to get link info");
1327
1328
0
done:
1329
0
    FUNC_LEAVE_API(ret_value)
1330
0
} /* end H5Lget_info_by_idx2() */
1331
1332
/*-------------------------------------------------------------------------
1333
 * Function:  H5Lregister
1334
 *
1335
 * Purpose: Registers a class of user-defined links, or changes the
1336
 *              behavior of an existing class.
1337
 *
1338
 *              The link class passed in will override any existing link
1339
 *              class for the specified link class ID. It must at least
1340
 *              include a H5L_class_t version (which should be
1341
 *              H5L_LINK_CLASS_T_VERS), a link class ID, and a traversal
1342
 *              function.
1343
 *
1344
 * Return:  Non-negative on success/Negative on failure
1345
 *
1346
 *-------------------------------------------------------------------------
1347
 */
1348
herr_t
1349
H5Lregister(const H5L_class_t *cls)
1350
0
{
1351
0
    herr_t ret_value = SUCCEED; /* Return value */
1352
1353
0
    FUNC_ENTER_API(FAIL)
1354
1355
    /* Check args */
1356
0
    if (cls == NULL)
1357
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link class");
1358
1359
    /* Check H5L_class_t version number; this is where a function to convert
1360
     * from an outdated version should be called.
1361
     *
1362
     * v0 of the H5L_class_t is only different in the parameters to the
1363
     * traversal callback, which is handled in H5G_traverse_ud()
1364
     * (in src/H5Gtraverse.c), so it's allowed to to pass through here. - QAK, 2018/02/06
1365
     */
1366
0
    if (cls->version > H5L_LINK_CLASS_T_VERS)
1367
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid H5L_class_t version number");
1368
0
#ifdef H5_NO_DEPRECATED_SYMBOLS
1369
0
    if (cls->version < H5L_LINK_CLASS_T_VERS)
1370
0
        HGOTO_ERROR(
1371
0
            H5E_ARGS, H5E_BADVALUE, FAIL,
1372
0
            "deprecated H5L_class_t version number (%d) and library built without deprecated symbol support",
1373
0
            cls->version);
1374
0
#endif /* H5_NO_DEPRECATED_SYMBOLS */
1375
1376
0
    if (cls->id < H5L_TYPE_UD_MIN || cls->id > H5L_TYPE_MAX)
1377
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link identification number");
1378
0
    if (cls->trav_func == NULL)
1379
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no traversal function specified");
1380
1381
    /* Do it */
1382
0
    if (H5L_register(cls) < 0)
1383
0
        HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "unable to register link type");
1384
1385
0
done:
1386
0
    FUNC_LEAVE_API(ret_value)
1387
0
} /* end H5Lregister() */
1388
1389
/*-------------------------------------------------------------------------
1390
 * Function:  H5Lunregister
1391
 *
1392
 * Purpose: Unregisters a class of user-defined links, preventing them
1393
 *              from being traversed, queried, moved, etc.
1394
 *
1395
 *              A link class can be re-registered using H5Lregister().
1396
 *
1397
 * Return:  Non-negative on success/Negative on failure
1398
 *
1399
 *-------------------------------------------------------------------------
1400
 */
1401
herr_t
1402
H5Lunregister(H5L_type_t id)
1403
0
{
1404
0
    herr_t ret_value = SUCCEED; /* Return value */
1405
1406
0
    FUNC_ENTER_API(FAIL)
1407
1408
    /* Check args */
1409
0
    if (id < 0 || id > H5L_TYPE_MAX)
1410
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link type");
1411
1412
    /* Do it */
1413
0
    if (H5L_unregister(id) < 0)
1414
0
        HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "unable to unregister link type");
1415
1416
0
done:
1417
0
    FUNC_LEAVE_API(ret_value)
1418
0
} /* end H5Lunregister() */
1419
1420
/*-------------------------------------------------------------------------
1421
 * Function:    H5Lis_registered
1422
 *
1423
 * Purpose:     Tests whether a user-defined link class has been registered
1424
 *              or not.
1425
 *
1426
 * Return:      true if the link class has been registered
1427
 *              false if it is unregistered
1428
 *              FAIL on error (if the class is not a valid UD class ID)
1429
 *
1430
 *-------------------------------------------------------------------------
1431
 */
1432
htri_t
1433
H5Lis_registered(H5L_type_t id)
1434
0
{
1435
0
    bool   is_registered = false;
1436
0
    htri_t ret_value     = false; /* Return value */
1437
1438
0
    FUNC_ENTER_API(FAIL)
1439
1440
    /* Check args */
1441
0
    if (id < 0 || id > H5L_TYPE_MAX)
1442
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link type id number");
1443
1444
    /* Is the link class already registered? */
1445
0
    if (H5L_is_registered(id, &is_registered) < 0)
1446
0
        HGOTO_ERROR(H5E_LINK, H5E_BADTYPE, FAIL, "could not determine registration status of UD link type");
1447
1448
0
    ret_value = is_registered ? true : false;
1449
1450
0
done:
1451
0
    FUNC_LEAVE_API(ret_value)
1452
0
} /* end H5Lis_registered() */
1453
1454
/*-------------------------------------------------------------------------
1455
 * Function:    H5Lget_name_by_idx
1456
 *
1457
 * Purpose:     Gets name for a link, according to the order within an
1458
 *              index.
1459
 *
1460
 *              Same pattern of behavior as H5Iget_name.
1461
 *
1462
 * Return:      Success:    Non-negative length of name, with information
1463
 *                          in NAME buffer
1464
 *
1465
 *              Failure:    -1
1466
 *
1467
 *-------------------------------------------------------------------------
1468
 */
1469
ssize_t
1470
H5Lget_name_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order,
1471
                   hsize_t n, char *name /*out*/, size_t size, hid_t lapl_id)
1472
2.87k
{
1473
2.87k
    H5VL_object_t       *vol_obj = NULL;     /* object of loc_id */
1474
2.87k
    H5VL_link_get_args_t vol_cb_args;        /* Arguments to VOL callback */
1475
2.87k
    H5VL_loc_params_t    loc_params;         /* Location parameters for object access */
1476
2.87k
    size_t               link_name_len = 0;  /* Length of the link name string */
1477
2.87k
    ssize_t              ret_value     = -1; /* Return value */
1478
1479
5.75k
    FUNC_ENTER_API((-1))
1480
1481
    /* Check arguments */
1482
5.75k
    if (!group_name || !*group_name)
1483
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "no name specified");
1484
2.87k
    if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1485
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid index type specified");
1486
2.87k
    if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1487
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid iteration order specified");
1488
1489
    /* Verify access property list and set up collective metadata if appropriate */
1490
2.87k
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, true) < 0)
1491
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, (-1), "can't set access property list info");
1492
1493
    /* Set up location struct */
1494
2.87k
    loc_params.type                         = H5VL_OBJECT_BY_IDX;
1495
2.87k
    loc_params.loc_data.loc_by_idx.name     = group_name;
1496
2.87k
    loc_params.loc_data.loc_by_idx.idx_type = idx_type;
1497
2.87k
    loc_params.loc_data.loc_by_idx.order    = order;
1498
2.87k
    loc_params.loc_data.loc_by_idx.n        = n;
1499
2.87k
    loc_params.loc_data.loc_by_idx.lapl_id  = lapl_id;
1500
2.87k
    loc_params.obj_type                     = H5I_get_type(loc_id);
1501
1502
    /* Get the VOL object */
1503
2.87k
    if (NULL == (vol_obj = H5VL_vol_object(loc_id)))
1504
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid location identifier");
1505
1506
    /* Set up VOL callback arguments */
1507
2.87k
    vol_cb_args.op_type                 = H5VL_LINK_GET_NAME;
1508
2.87k
    vol_cb_args.args.get_name.name_size = size;
1509
2.87k
    vol_cb_args.args.get_name.name      = name;
1510
2.87k
    vol_cb_args.args.get_name.name_len  = &link_name_len;
1511
1512
    /* Get the link information */
1513
2.87k
    if (H5VL_link_get(vol_obj, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
1514
3
        HGOTO_ERROR(H5E_LINK, H5E_CANTGET, (-1), "unable to get link name");
1515
1516
    /* Set the return value */
1517
2.87k
    ret_value = (ssize_t)link_name_len;
1518
1519
2.87k
done:
1520
2.87k
    FUNC_LEAVE_API(ret_value)
1521
2.87k
} /* end H5Lget_name_by_idx() */
1522
1523
/*-------------------------------------------------------------------------
1524
 * Function:    H5L__iterate_api_common
1525
 *
1526
 * Purpose:     This is the common function for iterating over links
1527
 *
1528
 * Return:      Non-negative on success/Negative on failure
1529
 *
1530
 *-------------------------------------------------------------------------
1531
 */
1532
static herr_t
1533
H5L__iterate_api_common(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx_p,
1534
                        H5L_iterate2_t op, void *op_data, void **token_ptr, H5VL_object_t **_vol_obj_ptr)
1535
2.09k
{
1536
2.09k
    H5VL_object_t  *tmp_vol_obj = NULL; /* Object for loc_id */
1537
2.09k
    H5VL_object_t **vol_obj_ptr =
1538
2.09k
        (_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj);   /* Ptr to object ptr for loc_id */
1539
2.09k
    H5VL_link_specific_args_t vol_cb_args;              /* Arguments to VOL callback */
1540
2.09k
    H5VL_loc_params_t         loc_params;               /* Location parameters for object access */
1541
2.09k
    H5I_type_t                id_type;                  /* Type of ID */
1542
2.09k
    herr_t                    ret_value = H5_ITER_CONT; /* Return value */
1543
1544
2.09k
    FUNC_ENTER_PACKAGE
1545
1546
    /* Check arguments */
1547
2.09k
    id_type = H5I_get_type(group_id);
1548
2.09k
    if (!(H5I_GROUP == id_type || H5I_FILE == id_type))
1549
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument");
1550
2.09k
    if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1551
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified");
1552
2.09k
    if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1553
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified");
1554
2.09k
    if (!op)
1555
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified");
1556
1557
    /* Set up object access arguments */
1558
2.09k
    if (H5VL_setup_self_args(group_id, vol_obj_ptr, &loc_params) < 0)
1559
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set object access arguments");
1560
1561
    /* Set up VOL callback arguments */
1562
2.09k
    vol_cb_args.op_type                = H5VL_LINK_ITER;
1563
2.09k
    vol_cb_args.args.iterate.recursive = false;
1564
2.09k
    vol_cb_args.args.iterate.idx_type  = idx_type;
1565
2.09k
    vol_cb_args.args.iterate.order     = order;
1566
2.09k
    vol_cb_args.args.iterate.idx_p     = idx_p;
1567
2.09k
    vol_cb_args.args.iterate.op        = op;
1568
2.09k
    vol_cb_args.args.iterate.op_data   = op_data;
1569
1570
    /* Iterate over the links */
1571
2.09k
    if ((ret_value = H5VL_link_specific(*vol_obj_ptr, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT,
1572
2.09k
                                        token_ptr)) < 0)
1573
510
        HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link iteration failed");
1574
1575
2.09k
done:
1576
2.09k
    FUNC_LEAVE_NOAPI(ret_value)
1577
2.09k
} /* H5L__iterate_api_common() */
1578
1579
/*-------------------------------------------------------------------------
1580
 * Function:    H5Literate2
1581
 *
1582
 * Purpose:     Iterates over links in a group, with user callback routine,
1583
 *              according to the order within an index.
1584
 *
1585
 *              Same pattern of behavior as H5Giterate.
1586
 *
1587
 * Return:      Success:    The return value of the first operator that
1588
 *                          returns non-zero, or zero if all members were
1589
 *                          processed with no operator returning non-zero.
1590
 *
1591
 *              Failure:    Negative if something goes wrong within the
1592
 *                          library, or the negative value returned by one
1593
 *                          of the operators.
1594
 *
1595
 *-------------------------------------------------------------------------
1596
 */
1597
herr_t
1598
H5Literate2(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx_p, H5L_iterate2_t op,
1599
            void *op_data)
1600
2.09k
{
1601
2.09k
    herr_t ret_value; /* Return value */
1602
1603
4.19k
    FUNC_ENTER_API(FAIL)
1604
1605
    /* Iterate over links synchronously */
1606
4.19k
    if ((ret_value = H5L__iterate_api_common(group_id, idx_type, order, idx_p, op, op_data, NULL, NULL)) < 0)
1607
510
        HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "synchronous link iteration failed");
1608
1609
2.09k
done:
1610
2.09k
    FUNC_LEAVE_API(ret_value)
1611
4.19k
} /* end H5Literate2() */
1612
1613
/*-------------------------------------------------------------------------
1614
 * Function:    H5Literate_async
1615
 *
1616
 * Purpose:     Asynchronous version of H5Literate2
1617
 *
1618
 * Return:      Success:    The return value of the first operator that
1619
 *                          returns non-zero, or zero if all members were
1620
 *                          processed with no operator returning non-zero.
1621
 *
1622
 *              Failure:    Negative if something goes wrong within the
1623
 *                          library, or the negative value returned by one
1624
 *                          of the operators.
1625
 *
1626
 *
1627
 *-------------------------------------------------------------------------
1628
 */
1629
herr_t
1630
H5Literate_async(const char *app_file, const char *app_func, unsigned app_line, hid_t group_id,
1631
                 H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx_p, H5L_iterate2_t op, void *op_data,
1632
                 hid_t es_id)
1633
0
{
1634
0
    H5VL_object_t *vol_obj   = NULL;            /* Object for loc_id */
1635
0
    void          *token     = NULL;            /* Request token for async operation        */
1636
0
    void         **token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation        */
1637
0
    herr_t         ret_value;                   /* Return value */
1638
1639
0
    FUNC_ENTER_API(FAIL)
1640
1641
    /* Set up request token pointer for asynchronous operation */
1642
0
    if (H5ES_NONE != es_id)
1643
0
        token_ptr = &token; /* Point at token for VOL connector to set up */
1644
1645
    /* Iterate over links asynchronously */
1646
0
    if ((ret_value =
1647
0
             H5L__iterate_api_common(group_id, idx_type, order, idx_p, op, op_data, token_ptr, &vol_obj)) < 0)
1648
0
        HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "asynchronous link iteration failed");
1649
1650
    /* If a token was created, add the token to the event set */
1651
0
    if (NULL != token)
1652
        /* clang-format off */
1653
0
        if (H5ES_insert(es_id, H5VL_OBJ_CONNECTOR(vol_obj), token,
1654
0
                        H5ARG_TRACE10(__func__, "*s*sIuiIiIo*hLI*xi", app_file, app_func, app_line, group_id, idx_type, order, idx_p, op, op_data, es_id)) < 0)
1655
            /* clang-format on */
1656
0
            HGOTO_ERROR(H5E_LINK, H5E_CANTINSERT, FAIL, "can't insert token into event set");
1657
1658
0
done:
1659
0
    FUNC_LEAVE_API(ret_value)
1660
0
} /* H5Literate_async() */
1661
1662
/*-------------------------------------------------------------------------
1663
 * Function:    H5Literate_by_name2
1664
 *
1665
 * Purpose:     Iterates over links in a group, with user callback routine,
1666
 *              according to the order within an index.
1667
 *
1668
 *              Same pattern of behavior as H5Giterate.
1669
 *
1670
 * Return:      Success:    The return value of the first operator that
1671
 *                          returns non-zero, or zero if all members were
1672
 *                          processed with no operator returning non-zero.
1673
 *
1674
 *              Failure:    Negative if something goes wrong within the
1675
 *                          library, or the negative value returned by one
1676
 *                          of the operators.
1677
 *
1678
 *
1679
 *-------------------------------------------------------------------------
1680
 */
1681
herr_t
1682
H5Literate_by_name2(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order,
1683
                    hsize_t *idx_p, H5L_iterate2_t op, void *op_data, hid_t lapl_id)
1684
0
{
1685
0
    H5VL_object_t            *vol_obj = NULL; /* Object of loc_id */
1686
0
    H5VL_link_specific_args_t vol_cb_args;    /* Arguments to VOL callback */
1687
0
    H5VL_loc_params_t         loc_params;     /* Location parameters for object access */
1688
0
    herr_t                    ret_value;      /* Return value */
1689
1690
0
    FUNC_ENTER_API(FAIL)
1691
1692
    /* Check arguments */
1693
0
    if (!group_name)
1694
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_name parameter cannot be NULL");
1695
0
    if (!*group_name)
1696
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_name parameter cannot be an empty string");
1697
0
    if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1698
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified");
1699
0
    if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1700
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified");
1701
0
    if (!op)
1702
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified");
1703
1704
    /* Verify access property list and set up collective metadata if appropriate */
1705
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, false) < 0)
1706
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
1707
1708
    /* Get the location object */
1709
0
    if (NULL == (vol_obj = H5VL_vol_object(loc_id)))
1710
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
1711
1712
    /* Set location struct fields */
1713
0
    loc_params.type                         = H5VL_OBJECT_BY_NAME;
1714
0
    loc_params.obj_type                     = H5I_get_type(loc_id);
1715
0
    loc_params.loc_data.loc_by_name.name    = group_name;
1716
0
    loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
1717
1718
    /* Set up VOL callback arguments */
1719
0
    vol_cb_args.op_type                = H5VL_LINK_ITER;
1720
0
    vol_cb_args.args.iterate.recursive = false;
1721
0
    vol_cb_args.args.iterate.idx_type  = idx_type;
1722
0
    vol_cb_args.args.iterate.order     = order;
1723
0
    vol_cb_args.args.iterate.idx_p     = idx_p;
1724
0
    vol_cb_args.args.iterate.op        = op;
1725
0
    vol_cb_args.args.iterate.op_data   = op_data;
1726
1727
    /* Iterate over the links */
1728
0
    if ((ret_value = H5VL_link_specific(vol_obj, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT,
1729
0
                                        H5_REQUEST_NULL)) < 0)
1730
0
        HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link iteration failed");
1731
1732
0
done:
1733
0
    FUNC_LEAVE_API(ret_value)
1734
0
} /* end H5Literate_by_name() */
1735
1736
/*-------------------------------------------------------------------------
1737
 * Function:    H5Lvisit2
1738
 *
1739
 * Purpose:     Recursively visit all the links in a group and all
1740
 *              the groups that are linked to from that group.  Links within
1741
 *              each group are visited according to the order within the
1742
 *              specified index (unless the specified index does not exist for
1743
 *              a particular group, then the "name" index is used).
1744
 *
1745
 *              NOTE: Each _link_ reachable from the initial group will only be
1746
 *              visited once.  However, because an object may be reached from
1747
 *              more than one link, the visitation may call the application's
1748
 *              callback with more than one link that points to a particular
1749
 *              _object_.
1750
 *
1751
 * Return:      Success:    The return value of the first operator that
1752
 *                          returns non-zero, or zero if all members were
1753
 *                          processed with no operator returning non-zero.
1754
 *
1755
 *              Failure:    Negative if something goes wrong within the
1756
 *                          library, or the negative value returned by one
1757
 *                          of the operators.
1758
 *
1759
 *-------------------------------------------------------------------------
1760
 */
1761
herr_t
1762
H5Lvisit2(hid_t group_id, H5_index_t idx_type, H5_iter_order_t order, H5L_iterate2_t op, void *op_data)
1763
0
{
1764
0
    H5VL_object_t            *vol_obj = NULL; /* Object of loc_id */
1765
0
    H5VL_link_specific_args_t vol_cb_args;    /* Arguments to VOL callback */
1766
0
    H5VL_loc_params_t         loc_params;     /* Location parameters for object access */
1767
0
    H5I_type_t                id_type;        /* Type of ID */
1768
0
    herr_t                    ret_value;      /* Return value */
1769
1770
0
    FUNC_ENTER_API(FAIL)
1771
1772
    /* Check args */
1773
0
    id_type = H5I_get_type(group_id);
1774
0
    if (!(H5I_GROUP == id_type || H5I_FILE == id_type))
1775
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument");
1776
0
    if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1777
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified");
1778
0
    if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1779
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified");
1780
0
    if (!op)
1781
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified");
1782
1783
    /* Set location struct fields */
1784
0
    loc_params.type     = H5VL_OBJECT_BY_SELF;
1785
0
    loc_params.obj_type = H5I_get_type(group_id);
1786
1787
    /* Get the location object */
1788
0
    if (NULL == (vol_obj = H5VL_vol_object(group_id)))
1789
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
1790
1791
    /* Set up VOL callback arguments */
1792
0
    vol_cb_args.op_type                = H5VL_LINK_ITER;
1793
0
    vol_cb_args.args.iterate.recursive = true;
1794
0
    vol_cb_args.args.iterate.idx_type  = idx_type;
1795
0
    vol_cb_args.args.iterate.order     = order;
1796
0
    vol_cb_args.args.iterate.idx_p     = NULL;
1797
0
    vol_cb_args.args.iterate.op        = op;
1798
0
    vol_cb_args.args.iterate.op_data   = op_data;
1799
1800
    /* Iterate over the links */
1801
0
    if ((ret_value = H5VL_link_specific(vol_obj, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT,
1802
0
                                        H5_REQUEST_NULL)) < 0)
1803
0
        HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed");
1804
1805
0
done:
1806
0
    FUNC_LEAVE_API(ret_value)
1807
0
} /* end H5Lvisit2() */
1808
1809
/*-------------------------------------------------------------------------
1810
 * Function:    H5Lvisit_by_name2
1811
 *
1812
 * Purpose:     Recursively visit all the links in a group and all
1813
 *              the groups that are linked to from that group.  Links within
1814
 *              each group are visited according to the order within the
1815
 *              specified index (unless the specified index does not exist for
1816
 *              a particular group, then the "name" index is used).
1817
 *
1818
 *              NOTE: Each _link_ reachable from the initial group will only be
1819
 *              visited once.  However, because an object may be reached from
1820
 *              more than one link, the visitation may call the application's
1821
 *              callback with more than one link that points to a particular
1822
 *              _object_.
1823
 *
1824
 * Return:      Success:    The return value of the first operator that
1825
 *                          returns non-zero, or zero if all members were
1826
 *                          processed with no operator returning non-zero.
1827
 *
1828
 *              Failure:    Negative if something goes wrong within the
1829
 *                          library, or the negative value returned by one
1830
 *                          of the operators.
1831
 *
1832
 *-------------------------------------------------------------------------
1833
 */
1834
herr_t
1835
H5Lvisit_by_name2(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5_iter_order_t order,
1836
                  H5L_iterate2_t op, void *op_data, hid_t lapl_id)
1837
0
{
1838
0
    H5VL_object_t            *vol_obj = NULL; /* Object of loc_id */
1839
0
    H5VL_link_specific_args_t vol_cb_args;    /* Arguments to VOL callback */
1840
0
    H5VL_loc_params_t         loc_params;     /* Location parameters for object access */
1841
0
    herr_t                    ret_value;      /* Return value */
1842
1843
0
    FUNC_ENTER_API(FAIL)
1844
1845
    /* Check args */
1846
0
    if (!group_name)
1847
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_name parameter cannot be NULL");
1848
0
    if (!*group_name)
1849
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group_name parameter cannot be an empty string");
1850
0
    if (idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1851
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified");
1852
0
    if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1853
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified");
1854
0
    if (!op)
1855
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified");
1856
1857
    /* Verify access property list and set up collective metadata if appropriate */
1858
0
    if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, loc_id, false) < 0)
1859
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info");
1860
1861
    /* get the location object */
1862
0
    if (NULL == (vol_obj = H5VL_vol_object(loc_id)))
1863
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier");
1864
1865
    /* Set location struct fields */
1866
0
    loc_params.type                         = H5VL_OBJECT_BY_NAME;
1867
0
    loc_params.obj_type                     = H5I_get_type(loc_id);
1868
0
    loc_params.loc_data.loc_by_name.name    = group_name;
1869
0
    loc_params.loc_data.loc_by_name.lapl_id = lapl_id;
1870
1871
    /* Set up VOL callback arguments */
1872
0
    vol_cb_args.op_type                = H5VL_LINK_ITER;
1873
0
    vol_cb_args.args.iterate.recursive = true;
1874
0
    vol_cb_args.args.iterate.idx_type  = idx_type;
1875
0
    vol_cb_args.args.iterate.order     = order;
1876
0
    vol_cb_args.args.iterate.idx_p     = NULL;
1877
0
    vol_cb_args.args.iterate.op        = op;
1878
0
    vol_cb_args.args.iterate.op_data   = op_data;
1879
1880
    /* Visit the links */
1881
0
    if ((ret_value = H5VL_link_specific(vol_obj, &loc_params, &vol_cb_args, H5P_DATASET_XFER_DEFAULT,
1882
0
                                        H5_REQUEST_NULL)) < 0)
1883
0
        HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed");
1884
1885
0
done:
1886
0
    FUNC_LEAVE_API(ret_value)
1887
0
} /* end H5Lvisit_by_name2() */
1888
1889
/*-------------------------------------------------------------------------
1890
 * Function: H5Lunpack_elink_val
1891
 *
1892
 * Purpose: Given a buffer holding the "link value" from an external link,
1893
 *              gets pointers to the information within the link value buffer.
1894
 *
1895
 *              External link link values contain some flags and
1896
 *              two NULL-terminated strings, one after the other.
1897
 *
1898
 *              The FLAGS value will be filled in and FILENAME and
1899
 *              OBJ_PATH will be set to pointers within ext_linkval (unless
1900
 *              any of these values is NULL).
1901
 *
1902
 *              Using this function on strings that aren't external link
1903
 *              udata buffers can result in segmentation faults.
1904
 *
1905
 * Return: Non-negative on success/ Negative on failure
1906
 *
1907
 *-------------------------------------------------------------------------
1908
 */
1909
herr_t
1910
H5Lunpack_elink_val(const void *_ext_linkval, size_t link_size, unsigned *flags, const char **filename,
1911
                    const char **obj_path)
1912
0
{
1913
0
    const uint8_t *ext_linkval = (const uint8_t *)_ext_linkval; /* Pointer to the link value */
1914
0
    unsigned       lnk_version;                                 /* External link format version */
1915
0
    unsigned       lnk_flags;                                   /* External link flags */
1916
0
    size_t         len;                                         /* Length of the filename in the linkval*/
1917
0
    herr_t         ret_value = SUCCEED;                         /* Return value */
1918
1919
0
    FUNC_ENTER_API(FAIL)
1920
1921
    /* Sanity check external link buffer */
1922
0
    if (ext_linkval == NULL)
1923
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an external link linkval buffer");
1924
0
    lnk_version = (*ext_linkval >> 4) & 0x0F;
1925
0
    lnk_flags   = *ext_linkval & 0x0F;
1926
0
    if (lnk_version > H5L_EXT_VERSION)
1927
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTDECODE, FAIL, "bad version number for external link");
1928
0
    if (lnk_flags & (unsigned)~H5L_EXT_FLAGS_ALL)
1929
0
        HGOTO_ERROR(H5E_LINK, H5E_CANTDECODE, FAIL, "bad flags for external link");
1930
0
    if (link_size <= 2)
1931
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid external link buffer");
1932
1933
    /* Try to do some error checking.  If the last character in the linkval
1934
     * (the last character of obj_path) isn't NULL, then something's wrong.
1935
     */
1936
0
    if (ext_linkval[link_size - 1] != '\0')
1937
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "linkval buffer is not NULL-terminated");
1938
1939
    /* We're now guaranteed that strlen won't segfault, since the buffer has
1940
     * at least one NULL in it.
1941
     */
1942
0
    len = strlen((const char *)ext_linkval + 1);
1943
1944
    /* If the first NULL we found was at the very end of the buffer, then
1945
     * this external link value has no object name and is invalid.
1946
     */
1947
0
    if ((len + 1) >= (link_size - 1))
1948
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "linkval buffer doesn't contain an object path");
1949
1950
    /* If we got here then the buffer contains (at least) two strings packed
1951
     * in the correct way.  Assume it's correct and return pointers to the
1952
     * filename and object path.
1953
     */
1954
0
    if (filename)
1955
0
        *filename = (const char *)ext_linkval + 1;
1956
0
    if (obj_path)
1957
0
        *obj_path = ((const char *)ext_linkval + 1) + len + 1; /* Add one for NULL terminator */
1958
1959
    /* Set the flags to return */
1960
0
    if (flags)
1961
0
        *flags = lnk_flags;
1962
1963
0
done:
1964
    FUNC_LEAVE_API(ret_value)
1965
0
} /* end H5Lunpack_elink_val() */