1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF5. The full HDF5 copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 /****************/
15 /* Module Setup */
16 /****************/
17
18 #include "H5Lmodule.h" /* This source code file is part of the H5L module */
19
20
21 /***********/
22 /* Headers */
23 /***********/
24 #include "H5private.h" /* Generic Functions */
25 #include "H5ACprivate.h" /* Metadata cache */
26 #include "H5Dprivate.h" /* Datasets */
27 #include "H5Eprivate.h" /* Error handling */
28 #include "H5Fprivate.h" /* File access */
29 #include "H5Gprivate.h" /* Groups */
30 #include "H5Iprivate.h" /* IDs */
31 #include "H5Lpkg.h" /* Links */
32 #include "H5MMprivate.h" /* Memory management */
33 #include "H5Oprivate.h" /* File objects */
34 #include "H5Pprivate.h" /* Property lists */
35
36 /****************/
37 /* Local Macros */
38 /****************/
39
40 #define H5L_MIN_TABLE_SIZE 32 /* Minimum size of the user-defined link type table if it is allocated */
41
42
43 /******************/
44 /* Local Typedefs */
45 /******************/
46
47 /* User data for path traversal routine for getting link info by name */
48 typedef struct {
49 H5L_info_t *linfo; /* Buffer to return to user */
50 hid_t dxpl_id; /* DXPL to use in callback */
51 } H5L_trav_gi_t;
52
53 /* User data for path traversal routine for getting link info by index */
54 typedef struct {
55 /* In */
56 H5_index_t idx_type; /* Index to use */
57 H5_iter_order_t order; /* Order to iterate in index */
58 hsize_t n; /* Offset of link within index */
59 hid_t dxpl_id; /* DXPL to use in callback */
60
61 /* Out */
62 H5L_info_t *linfo; /* Buffer to return to user */
63 } H5L_trav_gibi_t;
64
65 /* User data for path traversal callback to creating a link */
66 typedef struct {
67 H5F_t *file; /* Pointer to the file */
68 H5P_genplist_t *lc_plist; /* Link creation property list */
69 hid_t dxpl_id; /* Dataset transfer property list */
70 H5G_name_t *path; /* Path to object being linked */
71 H5O_obj_create_t *ocrt_info; /* Pointer to object creation info */
72 H5O_link_t *lnk; /* Pointer to link information to insert */
73 } H5L_trav_cr_t;
74
75 /* User data for path traversal routine for moving and renaming a link */
76 typedef struct {
77 const char *dst_name; /* Destination name for moving object */
78 H5T_cset_t cset; /* Char set for new name */
79 H5G_loc_t *dst_loc; /* Destination location for moving object */
80 unsigned dst_target_flags; /* Target flags for destination object */
81 hbool_t copy; /* TRUE if this is a copy operation */
82 hid_t lapl_id; /* LAPL to use in callback */
83 hid_t dxpl_id; /* DXPL to use in callback */
84 } H5L_trav_mv_t;
85
86 /* User data for path traversal routine for moving and renaming an object */
87 typedef struct {
88 H5F_t *file; /* Pointer to the file */
89 H5O_link_t *lnk; /* Pointer to link information to insert */
90 hbool_t copy; /* TRUE if this is a copy operation */
91 hid_t dxpl_id; /* Dataset transfer property list */
92 } H5L_trav_mv2_t;
93
94 /* User data for path traversal routine for checking if a link exists */
95 typedef struct {
96 /* Down */
97 char *sep; /* Pointer to next separator in the string */
98 hid_t lapl_id; /* Link access property list */
99 hid_t dxpl_id; /* Dataset transfer property list */
100
101 /* Up */
102 hbool_t exists; /* Whether the link exists or not */
103 } H5L_trav_le_t;
104
105 /* User data for path traversal routine for getting link value */
106 typedef struct {
107 size_t size; /* Size of user buffer */
108 void *buf; /* User buffer */
109 } H5L_trav_gv_t;
110
111 /* User data for path traversal routine for getting link value by index */
112 typedef struct {
113 /* In */
114 H5_index_t idx_type; /* Index to use */
115 H5_iter_order_t order; /* Order to iterate in index */
116 hsize_t n; /* Offset of link within index */
117 hid_t dxpl_id; /* DXPL to use in callback */
118 size_t size; /* Size of user buffer */
119
120 /* Out */
121 void *buf; /* User buffer */
122 } H5L_trav_gvbi_t;
123
124 /* User data for path traversal routine for removing link */
125 typedef struct {
126 hid_t dxpl_id; /* DXPL to use in callback */
127 } H5L_trav_rm_t;
128
129 /* User data for path traversal routine for removing link by index */
130 typedef struct {
131 /* In */
132 H5_index_t idx_type; /* Index to use */
133 H5_iter_order_t order; /* Order to iterate in index */
134 hsize_t n; /* Offset of link within index */
135 hid_t dxpl_id; /* DXPL to use in callback */
136 } H5L_trav_rmbi_t;
137
138 /* User data for path traversal routine for getting name by index */
139 typedef struct {
140 /* In */
141 H5_index_t idx_type; /* Index to use */
142 H5_iter_order_t order; /* Order to iterate in index */
143 hsize_t n; /* Offset of link within index */
144 size_t size; /* Size of name buffer */
145 hid_t dxpl_id; /* DXPL to use in callback */
146
147 /* Out */
148 char *name; /* Buffer to return name to user */
149 ssize_t name_len; /* Length of full name */
150 } H5L_trav_gnbi_t;
151
152 /********************/
153 /* Local Prototypes */
154 /********************/
155
156 static int H5L_find_class_idx(H5L_type_t id);
157 static herr_t H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
158 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
159 H5G_own_loc_t *own_loc/*out*/);
160 static herr_t H5L_create_real(const H5G_loc_t *link_loc, const char *link_name,
161 H5G_name_t *obj_path, H5F_t *obj_file, H5O_link_t *lnk, H5O_obj_create_t *ocrt_info,
162 hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id);
163 static herr_t H5L_get_val_real(const H5O_link_t *lnk, void *buf, size_t size);
164 static herr_t H5L_get_val_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
165 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
166 H5G_own_loc_t *own_loc/*out*/);
167 static herr_t H5L_get_val_by_idx_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
168 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
169 H5G_own_loc_t *own_loc/*out*/);
170 static herr_t H5L_delete_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
171 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
172 H5G_own_loc_t *own_loc/*out*/);
173 static herr_t H5L_delete_by_idx_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
174 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
175 H5G_own_loc_t *own_loc/*out*/);
176 static herr_t H5L_move_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
177 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
178 H5G_own_loc_t *own_loc/*out*/);
179 static herr_t H5L_move_dest_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
180 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
181 H5G_own_loc_t *own_loc/*out*/);
182 static herr_t H5L__exists_final_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
183 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
184 H5G_own_loc_t *own_loc/*out*/);
185 static herr_t H5L__exists_inter_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
186 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
187 H5G_own_loc_t *own_loc/*out*/);
188 static htri_t H5L__exists(const H5G_loc_t *loc, const char *name, hid_t lapl_id,
189 hid_t dxpl_id);
190 static herr_t H5L_get_info_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
191 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
192 H5G_own_loc_t *own_loc/*out*/);
193 static herr_t H5L_get_info_by_idx_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
194 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
195 H5G_own_loc_t *own_loc/*out*/);
196 static herr_t H5L_get_name_by_idx_cb(H5G_loc_t *grp_loc/*in*/,
197 const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
198 H5G_own_loc_t *own_loc/*out*/);
199
200 /*********************/
201 /* Package Variables */
202 /*********************/
203
204 /* Package initialization variable */
205 hbool_t H5_PKG_INIT_VAR = FALSE;
206
207
208 /*****************************/
209 /* Library Private Variables */
210 /*****************************/
211
212
213 /*******************/
214 /* Local Variables */
215 /*******************/
216
217 /* Information about user-defined links */
218 static size_t H5L_table_alloc_g = 0;
219 static size_t H5L_table_used_g = 0;
220 static H5L_class_t *H5L_table_g = NULL;
221
222
223 /*-------------------------------------------------------------------------
224 * Function: H5L_init
225 *
226 * Purpose: Initialize the interface from some other package.
227 *
228 * Return: Success: non-negative
229 *
230 * Failure: negative
231 *
232 * Programmer: James Laird
233 * Thursday, July 13, 2006
234 *
235 *-------------------------------------------------------------------------
236 */
237 herr_t
H5L_init(void)238 H5L_init(void)
239 {
240 herr_t ret_value = SUCCEED; /* Return value */
241
242 FUNC_ENTER_NOAPI(FAIL)
243 /* FUNC_ENTER() does all the work */
244
245 done:
246 FUNC_LEAVE_NOAPI(ret_value)
247 } /* end H5L_init() */
248
249
250 /*-------------------------------------------------------------------------
251 * Function: H5L__init_package
252 *
253 * Purpose: Initialize information specific to H5L interface.
254 *
255 * Return: Non-negative on success/Negative on failure
256 *
257 * Programmer: James Laird
258 * Tuesday, January 24, 2006
259 *
260 *-------------------------------------------------------------------------
261 */
262 herr_t
H5L__init_package(void)263 H5L__init_package(void)
264 {
265 herr_t ret_value = SUCCEED; /* Return value */
266
267 FUNC_ENTER_PACKAGE
268
269 /* Initialize user-defined link classes */
270 if(H5L_register_external() < 0)
271 HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "unable to register external link class")
272
273 done:
274 FUNC_LEAVE_NOAPI(ret_value)
275 } /* end H5L_init_package() */
276
277
278 /*-------------------------------------------------------------------------
279 * Function: H5L_term_package
280 *
281 * Purpose: Terminate any resources allocated in H5L__init_package.
282 *
283 * Return: Non-negative on success/Negative on failure
284 *
285 * Programmer: James Laird
286 * Tuesday, January 24, 2006
287 *
288 *-------------------------------------------------------------------------
289 */
290 int
H5L_term_package(void)291 H5L_term_package(void)
292 {
293 int n = 0;
294
295 FUNC_ENTER_NOAPI_NOINIT_NOERR
296
297 if(H5_PKG_INIT_VAR) {
298 /* Free the table of link types */
299 if(H5L_table_g) {
300 H5L_table_g = (H5L_class_t *)H5MM_xfree(H5L_table_g);
301 H5L_table_used_g = H5L_table_alloc_g = 0;
302 n++;
303 } /* end if */
304
305 /* Mark the interface as uninitialized */
306 if(0 == n)
307 H5_PKG_INIT_VAR = FALSE;
308 } /* end if */
309
310 FUNC_LEAVE_NOAPI(n)
311 } /* H5L_term_package() */
312
313
314 /*-------------------------------------------------------------------------
315 * Function: H5Lmove
316 *
317 * Purpose: Renames an object within an HDF5 file and moves it to a new
318 * group. The original name SRC is unlinked from the group graph
319 * and then inserted with the new name DST (which can specify a
320 * new path for the object) as an atomic operation. The names
321 * are interpreted relative to SRC_LOC_ID and
322 * DST_LOC_ID, which are either file IDs or group ID.
323 *
324 * Return: Non-negative on success/Negative on failure
325 *
326 * Programmer: James Laird
327 * Wednesday, March 29, 2006
328 *
329 *-------------------------------------------------------------------------
330 */
331 herr_t
H5Lmove(hid_t src_loc_id,const char * src_name,hid_t dst_loc_id,const char * dst_name,hid_t lcpl_id,hid_t lapl_id)332 H5Lmove(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
333 const char *dst_name, hid_t lcpl_id, hid_t lapl_id)
334 {
335 H5G_loc_t src_loc, *src_loc_p;
336 H5G_loc_t dst_loc, *dst_loc_p;
337 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
338 herr_t ret_value=SUCCEED; /* Return value */
339
340 FUNC_ENTER_API(FAIL)
341 H5TRACE6("e", "i*si*sii", src_loc_id, src_name, dst_loc_id, dst_name, lcpl_id,
342 lapl_id);
343
344 /* Check arguments */
345 if(src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC)
346 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC")
347 if(src_loc_id != H5L_SAME_LOC && H5G_loc(src_loc_id, &src_loc) < 0)
348 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
349 if(dst_loc_id != H5L_SAME_LOC && H5G_loc(dst_loc_id, &dst_loc) < 0)
350 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
351 if(!src_name || !*src_name)
352 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified")
353 if(!dst_name || !*dst_name)
354 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination name specified")
355 if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
356 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
357
358 /* Verify access property list and get correct dxpl */
359 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id,
360 ((src_loc_id != H5L_SAME_LOC) ? src_loc_id : dst_loc_id),
361 TRUE) < 0)
362 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
363
364 /* Set up src & dst location pointers */
365 src_loc_p = &src_loc;
366 dst_loc_p = &dst_loc;
367 if(src_loc_id == H5L_SAME_LOC)
368 src_loc_p = dst_loc_p;
369 else if(dst_loc_id == H5L_SAME_LOC)
370 dst_loc_p = src_loc_p;
371
372 /* Move the link */
373 if(H5L_move(src_loc_p, src_name, dst_loc_p, dst_name, FALSE, lcpl_id,
374 lapl_id, dxpl_id) < 0)
375 HGOTO_ERROR(H5E_LINK, H5E_CANTMOVE, FAIL, "unable to move link")
376
377 done:
378 FUNC_LEAVE_API(ret_value)
379 } /* end H5Lmove() */
380
381
382 /*-------------------------------------------------------------------------
383 * Function: H5Lcopy
384 *
385 * Purpose: Creates an identical copy of a link with the same creation
386 * time and target. The new link can have a different name
387 * and be in a different location than the original.
388 *
389 * Return: Non-negative on success/Negative on failure
390 *
391 * Programmer: James Laird
392 * Wednesday, March 29, 2006
393 *
394 *-------------------------------------------------------------------------
395 */
396 herr_t
H5Lcopy(hid_t src_loc_id,const char * src_name,hid_t dst_loc_id,const char * dst_name,hid_t lcpl_id,hid_t lapl_id)397 H5Lcopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
398 const char *dst_name, hid_t lcpl_id, hid_t lapl_id)
399 {
400 H5G_loc_t src_loc, *src_loc_p;
401 H5G_loc_t dst_loc, *dst_loc_p;
402 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
403 herr_t ret_value=SUCCEED; /* Return value */
404
405 FUNC_ENTER_API(FAIL)
406 H5TRACE6("e", "i*si*sii", src_loc_id, src_name, dst_loc_id, dst_name, lcpl_id,
407 lapl_id);
408
409 /* Check arguments */
410 if(src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC)
411 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC")
412 if(src_loc_id != H5L_SAME_LOC && H5G_loc(src_loc_id, &src_loc) < 0)
413 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
414 if(dst_loc_id != H5L_SAME_LOC && H5G_loc(dst_loc_id, &dst_loc) < 0)
415 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
416 if(!src_name || !*src_name)
417 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified")
418 if(!dst_name || !*dst_name)
419 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination name specified")
420 if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
421 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
422
423 /* Verify access property list and get correct dxpl */
424 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id,
425 ((src_loc_id != H5L_SAME_LOC) ? src_loc_id : dst_loc_id),
426 TRUE) < 0)
427 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
428
429 /* Set up src & dst location pointers */
430 src_loc_p = &src_loc;
431 dst_loc_p = &dst_loc;
432 if(src_loc_id == H5L_SAME_LOC)
433 src_loc_p = dst_loc_p;
434 else if(dst_loc_id == H5L_SAME_LOC)
435 dst_loc_p = src_loc_p;
436
437 /* Copy the link */
438 if(H5L_move(src_loc_p, src_name, dst_loc_p, dst_name, TRUE, lcpl_id,
439 lapl_id, dxpl_id) < 0)
440 HGOTO_ERROR(H5E_LINK, H5E_CANTMOVE, FAIL, "unable to move link")
441
442 done:
443 FUNC_LEAVE_API(ret_value)
444 } /* end H5Lcopy() */
445
446
447 /*-------------------------------------------------------------------------
448 * Function: H5Lcreate_soft
449 *
450 * Purpose: Creates a soft link from LINK_NAME to LINK_TARGET.
451 *
452 * LINK_TARGET can be anything and is interpreted at lookup
453 * time relative to the group which contains the final component
454 * of LINK_NAME. For instance, if LINK_TARGET is `./foo' and
455 * LINK_NAME is `./x/y/bar' and a request is made for `./x/y/bar'
456 * then the actual object looked up is `./x/y/./foo'.
457 *
458 * Return: Non-negative on success/Negative on failure
459 *
460 * Programmer: Robb Matzke
461 * Monday, April 6, 1998
462 *
463 *-------------------------------------------------------------------------
464 */
465 herr_t
H5Lcreate_soft(const char * link_target,hid_t link_loc_id,const char * link_name,hid_t lcpl_id,hid_t lapl_id)466 H5Lcreate_soft(const char *link_target,
467 hid_t link_loc_id, const char *link_name, hid_t lcpl_id, hid_t lapl_id)
468 {
469 H5G_loc_t link_loc; /* Group location for new link */
470 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
471 herr_t ret_value = SUCCEED; /* Return value */
472
473 FUNC_ENTER_API(FAIL)
474 H5TRACE5("e", "*si*sii", link_target, link_loc_id, link_name, lcpl_id, lapl_id);
475
476 /* Check arguments */
477 if(H5G_loc(link_loc_id, &link_loc) < 0)
478 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
479 if(!link_target || !*link_target)
480 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no target specified")
481 if(!link_name || !*link_name)
482 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new name specified")
483 if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
484 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
485
486 /* Verify access property list and get correct dxpl */
487 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, link_loc_id, TRUE) < 0)
488 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
489
490 /* Create the link */
491 if(H5L_create_soft(link_target, &link_loc, link_name, lcpl_id, lapl_id, dxpl_id) < 0)
492 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link")
493
494 done:
495 FUNC_LEAVE_API(ret_value)
496 } /* end H5Lcreate_soft() */
497
498
499 /*-------------------------------------------------------------------------
500 * Function: H5Lcreate_hard
501 *
502 * Purpose: Creates a hard link from NEW_NAME to CUR_NAME.
503 *
504 * CUR_NAME must name an existing object. CUR_NAME and
505 * NEW_NAME are interpreted relative to CUR_LOC_ID and
506 * NEW_LOC_ID, which are either file IDs or group IDs.
507 *
508 * Return: Non-negative on success/Negative on failure
509 *
510 * Programmer: Robb Matzke
511 * Monday, April 6, 1998
512 *
513 *-------------------------------------------------------------------------
514 */
515 herr_t
H5Lcreate_hard(hid_t cur_loc_id,const char * cur_name,hid_t new_loc_id,const char * new_name,hid_t lcpl_id,hid_t lapl_id)516 H5Lcreate_hard(hid_t cur_loc_id, const char *cur_name,
517 hid_t new_loc_id, const char *new_name, hid_t lcpl_id, hid_t lapl_id)
518 {
519 H5G_loc_t cur_loc, *cur_loc_p;
520 H5G_loc_t new_loc, *new_loc_p;
521 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
522 herr_t ret_value = SUCCEED; /* Return value */
523
524 FUNC_ENTER_API(FAIL)
525 H5TRACE6("e", "i*si*sii", cur_loc_id, cur_name, new_loc_id, new_name, lcpl_id,
526 lapl_id);
527
528 /* Check arguments */
529 if(cur_loc_id == H5L_SAME_LOC && new_loc_id == H5L_SAME_LOC)
530 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not be both H5L_SAME_LOC")
531 if(cur_loc_id != H5L_SAME_LOC && H5G_loc(cur_loc_id, &cur_loc) < 0)
532 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
533 if(new_loc_id != H5L_SAME_LOC && H5G_loc(new_loc_id, &new_loc) < 0)
534 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
535 if(!cur_name || !*cur_name)
536 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified")
537 if(!new_name || !*new_name)
538 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new name specified")
539 if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
540 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
541
542 /* Verify access property list and get correct dxpl */
543 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, cur_loc_id, TRUE) < 0)
544 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
545
546 /* Set up current & new location pointers */
547 cur_loc_p = &cur_loc;
548 new_loc_p = &new_loc;
549 if(cur_loc_id == H5L_SAME_LOC)
550 cur_loc_p = new_loc_p;
551 else if(new_loc_id == H5L_SAME_LOC)
552 new_loc_p = cur_loc_p;
553 else if(cur_loc_p->oloc->file != new_loc_p->oloc->file)
554 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should be in the same file.")
555
556 /* Create the link */
557 if(H5L_create_hard(cur_loc_p, cur_name, new_loc_p, new_name,
558 lcpl_id, lapl_id, dxpl_id) < 0)
559 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link")
560
561 done:
562 FUNC_LEAVE_API(ret_value)
563 } /* end H5Lcreate_hard() */
564
565
566 /*-------------------------------------------------------------------------
567 * Function: H5Lcreate_ud
568 *
569 * Purpose: Creates a user-defined link of type LINK_TYPE named LINK_NAME
570 * with user-specified data UDATA.
571 *
572 * The format of the information pointed to by UDATA is
573 * defined by the user. UDATA_SIZE holds the size of this buffer.
574 *
575 * LINK_NAME is interpreted relative to LINK_LOC_ID.
576 *
577 * The property list specified by LCPL_ID holds properties used
578 * to create the link.
579 *
580 * The link class of the new link must already be registered
581 * with the library.
582 *
583 * Return: Non-negative on success/Negative on failure
584 *
585 * Programmer: James Laird
586 * Tuesday, December 13, 2005
587 *
588 *-------------------------------------------------------------------------
589 */
590 herr_t
H5Lcreate_ud(hid_t link_loc_id,const char * link_name,H5L_type_t link_type,const void * udata,size_t udata_size,hid_t lcpl_id,hid_t lapl_id)591 H5Lcreate_ud(hid_t link_loc_id, const char *link_name, H5L_type_t link_type,
592 const void *udata, size_t udata_size, hid_t lcpl_id, hid_t lapl_id)
593 {
594 H5G_loc_t link_loc;
595 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
596 herr_t ret_value = SUCCEED; /* Return value */
597
598 FUNC_ENTER_API(FAIL)
599 H5TRACE7("e", "i*sLl*xzii", link_loc_id, link_name, link_type, udata,
600 udata_size, lcpl_id, lapl_id);
601
602 /* Check arguments */
603 if(H5G_loc(link_loc_id, &link_loc) < 0)
604 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
605 if(!link_name || !*link_name)
606 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no link name specified")
607 if(link_type < H5L_TYPE_UD_MIN || link_type > H5L_TYPE_MAX)
608 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link class")
609
610 /* Verify access property list and get correct dxpl */
611 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, link_loc_id, TRUE) < 0)
612 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
613
614 /* Create external link */
615 if(H5L_create_ud(&link_loc, link_name, udata, udata_size, link_type, lcpl_id, lapl_id, dxpl_id) < 0)
616 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link")
617
618 done:
619 FUNC_LEAVE_API(ret_value)
620 } /* end H5Lcreate_ud() */
621
622
623 /*-------------------------------------------------------------------------
624 * Function: H5Ldelete
625 *
626 * Purpose: Removes the specified NAME from the group graph and
627 * decrements the link count for the object to which NAME
628 * points. If the link count reaches zero then all file-space
629 * associated with the object will be reclaimed (but if the
630 * object is open, then the reclamation of the file space is
631 * delayed until all handles to the object are closed).
632 *
633 * Return: Non-negative on success/Negative on failure
634 *
635 * Programmer: Robb Matzke
636 * Monday, April 6, 1998
637 *
638 *-------------------------------------------------------------------------
639 */
640 herr_t
H5Ldelete(hid_t loc_id,const char * name,hid_t lapl_id)641 H5Ldelete(hid_t loc_id, const char *name, hid_t lapl_id)
642 {
643 H5G_loc_t loc; /* Group's location */
644 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
645 herr_t ret_value = SUCCEED; /* Return value */
646
647 FUNC_ENTER_API(FAIL)
648 H5TRACE3("e", "i*si", loc_id, name, lapl_id);
649
650 /* Check arguments */
651 if(H5G_loc(loc_id, &loc) < 0)
652 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
653 if(!name || !*name)
654 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
655
656 /* Verify access property list and get correct dxpl */
657 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, TRUE) < 0)
658 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
659
660 /* Unlink */
661 if(H5L_delete(&loc, name, lapl_id, dxpl_id) < 0)
662 HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link")
663
664 done:
665 FUNC_LEAVE_API(ret_value)
666 } /* end H5Ldelete() */
667
668
669 /*-------------------------------------------------------------------------
670 * Function: H5Ldelete_by_idx
671 *
672 * Purpose: Removes the specified link from the group graph and
673 * decrements the link count for the object to which it
674 * points, according to the order within an index.
675 *
676 * If the link count reaches zero then all file-space
677 * associated with the object will be reclaimed (but if the
678 * object is open, then the reclamation of the file space is
679 * delayed until all handles to the object are closed).
680 *
681 * Return: Non-negative on success/Negative on failure
682 *
683 * Programmer: Quincey Koziol
684 * Monday, November 13, 2006
685 *
686 *-------------------------------------------------------------------------
687 */
688 herr_t
H5Ldelete_by_idx(hid_t loc_id,const char * group_name,H5_index_t idx_type,H5_iter_order_t order,hsize_t n,hid_t lapl_id)689 H5Ldelete_by_idx(hid_t loc_id, const char *group_name,
690 H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id)
691 {
692 H5G_loc_t loc; /* Group's location */
693 H5L_trav_rmbi_t udata; /* User data for callback */
694 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
695 herr_t ret_value = SUCCEED; /* Return value */
696
697 FUNC_ENTER_API(FAIL)
698 H5TRACE6("e", "i*sIiIohi", loc_id, group_name, idx_type, order, n, lapl_id);
699
700 /* Check arguments */
701 if(H5G_loc(loc_id, &loc) < 0)
702 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
703 if(!group_name || !*group_name)
704 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
705 if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
706 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
707 if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
708 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
709
710 /* Verify access property list and get correct dxpl */
711 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, TRUE) < 0)
712 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
713
714 /* Set up user data for unlink operation */
715 udata.idx_type = idx_type;
716 udata.order = order;
717 udata.n = n;
718 udata.dxpl_id = dxpl_id;
719
720 /* Traverse the group hierarchy to remove the link */
721 if(H5G_traverse(&loc, group_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK|H5G_TARGET_MOUNT,
722 H5L_delete_by_idx_cb, &udata, lapl_id, dxpl_id) < 0)
723 HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist")
724
725 done:
726 FUNC_LEAVE_API(ret_value)
727 } /* end H5Ldelete_by_idx() */
728
729
730 /*-------------------------------------------------------------------------
731 * Function: H5Lget_val
732 *
733 * Purpose: Returns the link value of a link whose name is NAME. For
734 * symbolic links, this is the path to which the link points,
735 * including the null terminator. For user-defined links, it
736 * is the link buffer.
737 *
738 * At most SIZE bytes are copied to the BUF result buffer.
739 *
740 * Return: Success: Non-negative with the link value in BUF.
741 *
742 * Failure: Negative
743 *
744 * Programmer: Robb Matzke
745 * Monday, April 13, 1998
746 *
747 *-------------------------------------------------------------------------
748 */
749 herr_t
H5Lget_val(hid_t loc_id,const char * name,void * buf,size_t size,hid_t lapl_id)750 H5Lget_val(hid_t loc_id, const char *name, void *buf/*out*/, size_t size,
751 hid_t lapl_id)
752 {
753 H5G_loc_t loc; /* Group location for location to query */
754 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
755 herr_t ret_value = SUCCEED; /* Return value */
756
757 FUNC_ENTER_API(FAIL)
758 H5TRACE5("e", "i*sxzi", loc_id, name, buf, size, lapl_id);
759
760 /* Check arguments */
761 if(H5G_loc(loc_id, &loc))
762 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
763 if(!name || !*name)
764 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
765
766 /* Verify access property list and get correct dxpl */
767 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
768 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
769
770 /* Get the link value */
771 if(H5L_get_val(&loc, name, buf, size, lapl_id, dxpl_id) < 0)
772 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to get link value for '%s'", name)
773
774 done:
775 FUNC_LEAVE_API(ret_value)
776 } /* end H5Lget_val() */
777
778
779 /*-------------------------------------------------------------------------
780 * Function: H5Lget_val_by_idx
781 *
782 * Purpose: Returns the link value of a link, according to the order of
783 * an index. For symbolic links, this is the path to which the
784 * link points, including the null terminator. For user-defined
785 * links, it is the link buffer.
786 *
787 * At most SIZE bytes are copied to the BUF result buffer.
788 *
789 * Return: Success: Non-negative with the link value in BUF.
790 * Failure: Negative
791 *
792 * Programmer: Quincey Koziol
793 * Monday, November 13, 2006
794 *
795 *-------------------------------------------------------------------------
796 */
797 herr_t
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,void * buf,size_t size,hid_t lapl_id)798 H5Lget_val_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
799 H5_iter_order_t order, hsize_t n, void *buf/*out*/, size_t size,
800 hid_t lapl_id)
801 {
802 H5G_loc_t loc; /* Group location for location to query */
803 H5L_trav_gvbi_t udata; /* User data for callback */
804 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
805 herr_t ret_value = SUCCEED; /* Return value */
806
807 FUNC_ENTER_API(FAIL)
808 H5TRACE8("e", "i*sIiIohxzi", loc_id, group_name, idx_type, order, n, buf, size,
809 lapl_id);
810
811 /* Check arguments */
812 if(H5G_loc(loc_id, &loc))
813 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
814 if(!group_name || !*group_name)
815 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
816 if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
817 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
818 if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
819 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
820
821 /* Verify access property list and get correct dxpl */
822 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
823 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
824
825 /* Set up user data for retrieving information */
826 udata.idx_type = idx_type;
827 udata.order = order;
828 udata.n = n;
829 udata.dxpl_id = dxpl_id;
830 udata.buf = buf;
831 udata.size = size;
832
833 /* Traverse the group hierarchy to locate the object to get info about */
834 if(H5G_traverse(&loc, group_name, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, H5L_get_val_by_idx_cb,
835 &udata, lapl_id, dxpl_id) < 0)
836 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
837
838
839 done:
840 FUNC_LEAVE_API(ret_value)
841 } /* end H5Lget_val_by_idx() */
842
843
844 /*-------------------------------------------------------------------------
845 * Function: H5Lexists
846 *
847 * Purpose: Checks if a link of a given name exists in a group
848 *
849 * Return: Success: TRUE/FALSE
850 * Failure: Negative
851 *
852 * Programmer: Quincey Koziol
853 * Friday, March 16, 2007
854 *
855 *-------------------------------------------------------------------------
856 */
857 htri_t
H5Lexists(hid_t loc_id,const char * name,hid_t lapl_id)858 H5Lexists(hid_t loc_id, const char *name, hid_t lapl_id)
859 {
860 H5G_loc_t loc;
861 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
862 htri_t ret_value;
863
864 FUNC_ENTER_API(FAIL)
865 H5TRACE3("t", "i*si", loc_id, name, lapl_id);
866
867 /* Check arguments */
868 if(H5G_loc(loc_id, &loc))
869 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
870 if(!name || !*name)
871 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
872
873 /* Verify access property list and get correct dxpl */
874 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
875 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
876
877 /* Check for the existence of the link */
878 if((ret_value = H5L__exists(&loc, name, lapl_id, dxpl_id)) < 0)
879 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to get link info")
880
881 done:
882 FUNC_LEAVE_API(ret_value)
883 } /* end H5Lexists() */
884
885
886 /*-------------------------------------------------------------------------
887 * Function: H5Lget_info
888 *
889 * Purpose: Gets metadata for a link.
890 *
891 * Return: Success: Non-negative with information in LINFO
892 *
893 * Failure: Negative
894 *
895 * Programmer: James Laird
896 * Wednesday, June 21, 2006
897 *
898 *-------------------------------------------------------------------------
899 */
900 herr_t
H5Lget_info(hid_t loc_id,const char * name,H5L_info_t * linfo,hid_t lapl_id)901 H5Lget_info(hid_t loc_id, const char *name, H5L_info_t *linfo /*out*/,
902 hid_t lapl_id)
903 {
904 H5G_loc_t loc;
905 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
906 herr_t ret_value = SUCCEED;
907
908 FUNC_ENTER_API(FAIL)
909 H5TRACE4("e", "i*sxi", loc_id, name, linfo, lapl_id);
910
911 /* Check arguments */
912 if(H5G_loc(loc_id, &loc))
913 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
914 if(!name || !*name)
915 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
916
917 /* Verify access property list and get correct dxpl */
918 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
919 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
920
921 /* Get the link information */
922 if(H5L_get_info(&loc, name, linfo, lapl_id, dxpl_id) < 0)
923 HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link info")
924
925 done:
926 FUNC_LEAVE_API(ret_value)
927 } /* end H5Lget_info() */
928
929
930 /*-------------------------------------------------------------------------
931 * Function: H5Lget_info_by_idx
932 *
933 * Purpose: Gets metadata for a link, according to the order within an
934 * index.
935 *
936 * Return: Success: Non-negative with information in LINFO
937 * Failure: Negative
938 *
939 * Programmer: Quincey Koziol
940 * Monday, November 6, 2006
941 *
942 *-------------------------------------------------------------------------
943 */
944 herr_t
H5Lget_info_by_idx(hid_t loc_id,const char * group_name,H5_index_t idx_type,H5_iter_order_t order,hsize_t n,H5L_info_t * linfo,hid_t lapl_id)945 H5Lget_info_by_idx(hid_t loc_id, const char *group_name,
946 H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
947 H5L_info_t *linfo /*out*/, hid_t lapl_id)
948 {
949 H5G_loc_t loc; /* Group location for group to query */
950 H5L_trav_gibi_t udata; /* User data for callback */
951 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
952 herr_t ret_value = SUCCEED; /* Return value */
953
954 FUNC_ENTER_API(FAIL)
955 H5TRACE7("e", "i*sIiIohxi", loc_id, group_name, idx_type, order, n, linfo,
956 lapl_id);
957
958 /* Check arguments */
959 if(H5G_loc(loc_id, &loc))
960 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
961 if(!group_name || !*group_name)
962 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
963 if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
964 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
965 if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
966 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
967
968 /* Verify access property list and get correct dxpl */
969 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
970 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
971
972 /* Set up user data for callback */
973 udata.idx_type = idx_type;
974 udata.order = order;
975 udata.n = n;
976 udata.dxpl_id = dxpl_id;
977 udata.linfo = linfo;
978
979 /* Traverse the group hierarchy to locate the object to get info about */
980 if(H5G_traverse(&loc, group_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK,
981 H5L_get_info_by_idx_cb, &udata, lapl_id, dxpl_id) < 0)
982 HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link info")
983
984 done:
985 FUNC_LEAVE_API(ret_value)
986 } /* end H5Lget_info_by_idx() */
987
988
989 /*-------------------------------------------------------------------------
990 * Function: H5Lregister
991 *
992 * Purpose: Registers a class of user-defined links, or changes the
993 * behavior of an existing class.
994 *
995 * The link class passed in will override any existing link
996 * class for the specified link class ID. It must at least
997 * include a H5L_class_t version (which should be
998 * H5L_LINK_CLASS_T_VERS), a link class ID, and a traversal
999 * function.
1000 *
1001 * Return: Non-negative on success/Negative on failure
1002 *
1003 * Programmer: James Laird
1004 * Monday, July 10, 2006
1005 *
1006 *-------------------------------------------------------------------------
1007 */
1008 herr_t
H5Lregister(const H5L_class_t * cls)1009 H5Lregister(const H5L_class_t *cls)
1010 {
1011 herr_t ret_value = SUCCEED; /* Return value */
1012
1013 FUNC_ENTER_API(FAIL)
1014 H5TRACE1("e", "*x", cls);
1015
1016 /* Check args */
1017 if(cls == NULL)
1018 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link class")
1019
1020 /* Check H5L_class_t version number; this is where a function to convert
1021 * from an outdated version should be called.
1022 */
1023 if(cls->version != H5L_LINK_CLASS_T_VERS)
1024 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid H5L_class_t version number")
1025
1026 if(cls->id < H5L_TYPE_UD_MIN || cls->id > H5L_TYPE_MAX)
1027 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link identification number")
1028 if(cls->trav_func == NULL)
1029 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no traversal function specified")
1030
1031 /* Do it */
1032 if(H5L_register(cls) < 0)
1033 HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "unable to register link type")
1034
1035 done:
1036 FUNC_LEAVE_API(ret_value)
1037 } /* end H5Lregister() */
1038
1039
1040 /*-------------------------------------------------------------------------
1041 * Function: H5Lunregister
1042 *
1043 * Purpose: Unregisters a class of user-defined links, preventing them
1044 * from being traversed, queried, moved, etc.
1045 *
1046 * A link class can be re-registered using H5Lregister().
1047 *
1048 * Return: Non-negative on success/Negative on failure
1049 *
1050 * Programmer: James Laird
1051 * Monday, July 10, 2006
1052 *
1053 *-------------------------------------------------------------------------
1054 */
1055 herr_t
H5Lunregister(H5L_type_t id)1056 H5Lunregister(H5L_type_t id)
1057 {
1058 herr_t ret_value = SUCCEED; /* Return value */
1059
1060 FUNC_ENTER_API(FAIL)
1061 H5TRACE1("e", "Ll", id);
1062
1063 /* Check args */
1064 if(id < 0 || id > H5L_TYPE_MAX)
1065 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link type")
1066
1067 /* Do it */
1068 if(H5L_unregister(id) < 0)
1069 HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "unable to unregister link type")
1070
1071 done:
1072 FUNC_LEAVE_API(ret_value)
1073 } /* end H5Lunregister() */
1074
1075
1076 /*-------------------------------------------------------------------------
1077 * Function: H5Lis_registered
1078 *
1079 * Purpose: Tests whether a user-defined link class has been registered
1080 * or not.
1081 *
1082 * Return: Positive if the link class has been registered
1083 * Zero if it is unregistered
1084 * Negative on error (if the class is not a valid UD class ID)
1085 *
1086 * Programmer: James Laird
1087 * Monday, July 10, 2006
1088 *
1089 *-------------------------------------------------------------------------
1090 */
1091 htri_t
H5Lis_registered(H5L_type_t id)1092 H5Lis_registered(H5L_type_t id)
1093 {
1094 size_t i; /* Local index variable */
1095 htri_t ret_value = FALSE; /* Return value */
1096
1097 FUNC_ENTER_API(FAIL)
1098 H5TRACE1("t", "Ll", id);
1099
1100 /* Check args */
1101 if(id < 0 || id > H5L_TYPE_MAX)
1102 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link type id number")
1103
1104 /* Is the link class already registered? */
1105 for(i = 0; i < H5L_table_used_g; i++)
1106 if(H5L_table_g[i].id == id) {
1107 ret_value = TRUE;
1108 break;
1109 } /* end if */
1110
1111 done:
1112 FUNC_LEAVE_API(ret_value)
1113 } /* end H5Lis_registered() */
1114
1115
1116 /*-------------------------------------------------------------------------
1117 * Function: H5Lget_name_by_idx
1118 *
1119 * Purpose: Gets name for a link, according to the order within an
1120 * index.
1121 *
1122 * Same pattern of behavior as H5Iget_name.
1123 *
1124 * Return: Success: Non-negative length of name, with information
1125 * in NAME buffer
1126 * Failure: Negative
1127 *
1128 * Programmer: Quincey Koziol
1129 * Saturday, November 11, 2006
1130 *
1131 *-------------------------------------------------------------------------
1132 */
1133 ssize_t
H5Lget_name_by_idx(hid_t loc_id,const char * group_name,H5_index_t idx_type,H5_iter_order_t order,hsize_t n,char * name,size_t size,hid_t lapl_id)1134 H5Lget_name_by_idx(hid_t loc_id, const char *group_name,
1135 H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
1136 char *name /*out*/, size_t size, hid_t lapl_id)
1137 {
1138 H5G_loc_t loc; /* Location of group */
1139 H5L_trav_gnbi_t udata; /* User data for callback */
1140 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
1141 ssize_t ret_value; /* Return value */
1142
1143 FUNC_ENTER_API(FAIL)
1144 H5TRACE8("Zs", "i*sIiIohxzi", loc_id, group_name, idx_type, order, n, name, size,
1145 lapl_id);
1146
1147 /* Check arguments */
1148 if(H5G_loc(loc_id, &loc))
1149 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
1150 if(!group_name || !*group_name)
1151 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
1152 if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1153 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
1154 if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1155 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
1156
1157 /* Verify access property list and get correct dxpl */
1158 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
1159 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
1160
1161 /* Set up user data for callback */
1162 udata.idx_type = idx_type;
1163 udata.order = order;
1164 udata.n = n;
1165 udata.dxpl_id = dxpl_id;
1166 udata.name = name;
1167 udata.size = size;
1168 udata.name_len = -1;
1169
1170 /* Traverse the group hierarchy to locate the link to get name of */
1171 if(H5G_traverse(&loc, group_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK,
1172 H5L_get_name_by_idx_cb, &udata, lapl_id, dxpl_id) < 0)
1173 HGOTO_ERROR(H5E_LINK, H5E_EXISTS, FAIL, "name doesn't exist")
1174
1175 /* Set the return value */
1176 ret_value = udata.name_len;
1177
1178 done:
1179 FUNC_LEAVE_API(ret_value)
1180 } /* end H5Lget_name_by_idx() */
1181
1182
1183 /*-------------------------------------------------------------------------
1184 * Function: H5Literate
1185 *
1186 * Purpose: Iterates over links in a group, with user callback routine,
1187 * according to the order within an index.
1188 *
1189 * Same pattern of behavior as H5Giterate.
1190 *
1191 * Return: Success: The return value of the first operator that
1192 * returns non-zero, or zero if all members were
1193 * processed with no operator returning non-zero.
1194 *
1195 * Failure: Negative if something goes wrong within the
1196 * library, or the negative value returned by one
1197 * of the operators.
1198 *
1199 *
1200 * Programmer: Quincey Koziol
1201 * Thursday, November 16, 2006
1202 *
1203 *-------------------------------------------------------------------------
1204 */
1205 herr_t
H5Literate(hid_t grp_id,H5_index_t idx_type,H5_iter_order_t order,hsize_t * idx_p,H5L_iterate_t op,void * op_data)1206 H5Literate(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order,
1207 hsize_t *idx_p, H5L_iterate_t op, void *op_data)
1208 {
1209 H5I_type_t id_type; /* Type of ID */
1210 H5G_link_iterate_t lnk_op; /* Link operator */
1211 hsize_t last_lnk; /* Index of last object looked at */
1212 hsize_t idx; /* Internal location to hold index */
1213 herr_t ret_value; /* Return value */
1214
1215 FUNC_ENTER_API(FAIL)
1216 H5TRACE6("e", "iIiIo*hx*x", grp_id, idx_type, order, idx_p, op, op_data);
1217
1218 /* Check arguments */
1219 id_type = H5I_get_type(grp_id);
1220 if(!(H5I_GROUP == id_type || H5I_FILE == id_type))
1221 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
1222 if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1223 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
1224 if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1225 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
1226 if(!op)
1227 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified")
1228
1229 /* Set up iteration beginning/end info */
1230 idx = (idx_p == NULL ? 0 : *idx_p);
1231 last_lnk = 0;
1232
1233 /* Build link operator info */
1234 lnk_op.op_type = H5G_LINK_OP_NEW;
1235 lnk_op.op_func.op_new = op;
1236
1237 /* Iterate over the links */
1238 if((ret_value = H5G_iterate(grp_id, ".", idx_type, order, idx, &last_lnk, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_read_dxpl_id)) < 0)
1239 HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link iteration failed")
1240
1241 /* Set the index we stopped at */
1242 if(idx_p)
1243 *idx_p = last_lnk;
1244
1245 done:
1246 FUNC_LEAVE_API(ret_value)
1247 } /* end H5Literate() */
1248
1249
1250 /*-------------------------------------------------------------------------
1251 * Function: H5Literate_by_name
1252 *
1253 * Purpose: Iterates over links in a group, with user callback routine,
1254 * according to the order within an index.
1255 *
1256 * Same pattern of behavior as H5Giterate.
1257 *
1258 * Return: Success: The return value of the first operator that
1259 * returns non-zero, or zero if all members were
1260 * processed with no operator returning non-zero.
1261 *
1262 * Failure: Negative if something goes wrong within the
1263 * library, or the negative value returned by one
1264 * of the operators.
1265 *
1266 *
1267 * Programmer: Quincey Koziol
1268 * Thursday, November 16, 2006
1269 *
1270 *-------------------------------------------------------------------------
1271 */
1272 herr_t
H5Literate_by_name(hid_t loc_id,const char * group_name,H5_index_t idx_type,H5_iter_order_t order,hsize_t * idx_p,H5L_iterate_t op,void * op_data,hid_t lapl_id)1273 H5Literate_by_name(hid_t loc_id, const char *group_name,
1274 H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx_p,
1275 H5L_iterate_t op, void *op_data, hid_t lapl_id)
1276 {
1277 H5G_link_iterate_t lnk_op; /* Link operator */
1278 hsize_t last_lnk; /* Index of last object looked at */
1279 hsize_t idx; /* Internal location to hold index */
1280 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
1281 herr_t ret_value; /* Return value */
1282
1283 FUNC_ENTER_API(FAIL)
1284 H5TRACE8("e", "i*sIiIo*hx*xi", loc_id, group_name, idx_type, order, idx_p, op,
1285 op_data, lapl_id);
1286
1287 /* Check arguments */
1288 if(!group_name || !*group_name)
1289 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
1290 if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1291 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
1292 if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1293 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
1294 if(!op)
1295 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified")
1296
1297 /* Verify access property list and get correct dxpl */
1298 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
1299 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
1300
1301 /* Set up iteration beginning/end info */
1302 idx = (idx_p == NULL ? 0 : *idx_p);
1303 last_lnk = 0;
1304
1305 /* Build link operator info */
1306 lnk_op.op_type = H5G_LINK_OP_NEW;
1307 lnk_op.op_func.op_new = op;
1308
1309 /* Iterate over the links */
1310 if((ret_value = H5G_iterate(loc_id, group_name, idx_type, order, idx, &last_lnk, &lnk_op,
1311 op_data, lapl_id, dxpl_id)) < 0)
1312 HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link iteration failed")
1313
1314 /* Set the index we stopped at */
1315 if(idx_p)
1316 *idx_p = last_lnk;
1317
1318 done:
1319 FUNC_LEAVE_API(ret_value)
1320 } /* end H5Literate_by_name() */
1321
1322
1323 /*-------------------------------------------------------------------------
1324 * Function: H5Lvisit
1325 *
1326 * Purpose: Recursively visit all the links in a group and all
1327 * the groups that are linked to from that group. Links within
1328 * each group are visited according to the order within the
1329 * specified index (unless the specified index does not exist for
1330 * a particular group, then the "name" index is used).
1331 *
1332 * NOTE: Each _link_ reachable from the initial group will only be
1333 * visited once. However, because an object may be reached from
1334 * more than one link, the visitation may call the application's
1335 * callback with more than one link that points to a particular
1336 * _object_.
1337 *
1338 * Return: Success: The return value of the first operator that
1339 * returns non-zero, or zero if all members were
1340 * processed with no operator returning non-zero.
1341 *
1342 * Failure: Negative if something goes wrong within the
1343 * library, or the negative value returned by one
1344 * of the operators.
1345 *
1346 * Programmer: Quincey Koziol
1347 * November 24 2007
1348 *
1349 *-------------------------------------------------------------------------
1350 */
1351 herr_t
H5Lvisit(hid_t grp_id,H5_index_t idx_type,H5_iter_order_t order,H5L_iterate_t op,void * op_data)1352 H5Lvisit(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order,
1353 H5L_iterate_t op, void *op_data)
1354 {
1355 H5I_type_t id_type; /* Type of ID */
1356 herr_t ret_value; /* Return value */
1357
1358 FUNC_ENTER_API(FAIL)
1359 H5TRACE5("e", "iIiIox*x", grp_id, idx_type, order, op, op_data);
1360
1361 /* Check args */
1362 id_type = H5I_get_type(grp_id);
1363 if(!(H5I_GROUP == id_type || H5I_FILE == id_type))
1364 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
1365 if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1366 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
1367 if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1368 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
1369 if(!op)
1370 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified")
1371
1372 /* Call internal group visitation routine */
1373 if((ret_value = H5G_visit(grp_id, ".", idx_type, order, op, op_data, H5P_DEFAULT, H5AC_ind_read_dxpl_id)) < 0)
1374 HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link visitation failed")
1375
1376 done:
1377 FUNC_LEAVE_API(ret_value)
1378 } /* end H5Lvisit() */
1379
1380
1381 /*-------------------------------------------------------------------------
1382 * Function: H5Lvisit_by_name
1383 *
1384 * Purpose: Recursively visit all the links in a group and all
1385 * the groups that are linked to from that group. Links within
1386 * each group are visited according to the order within the
1387 * specified index (unless the specified index does not exist for
1388 * a particular group, then the "name" index is used).
1389 *
1390 * NOTE: Each _link_ reachable from the initial group will only be
1391 * visited once. However, because an object may be reached from
1392 * more than one link, the visitation may call the application's
1393 * callback with more than one link that points to a particular
1394 * _object_.
1395 *
1396 * Return: Success: The return value of the first operator that
1397 * returns non-zero, or zero if all members were
1398 * processed with no operator returning non-zero.
1399 *
1400 * Failure: Negative if something goes wrong within the
1401 * library, or the negative value returned by one
1402 * of the operators.
1403 *
1404 * Programmer: Quincey Koziol
1405 * November 3 2007
1406 *
1407 *-------------------------------------------------------------------------
1408 */
1409 herr_t
H5Lvisit_by_name(hid_t loc_id,const char * group_name,H5_index_t idx_type,H5_iter_order_t order,H5L_iterate_t op,void * op_data,hid_t lapl_id)1410 H5Lvisit_by_name(hid_t loc_id, const char *group_name, H5_index_t idx_type,
1411 H5_iter_order_t order, H5L_iterate_t op, void *op_data, hid_t lapl_id)
1412 {
1413 hid_t dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
1414 herr_t ret_value; /* Return value */
1415
1416 FUNC_ENTER_API(FAIL)
1417 H5TRACE7("e", "i*sIiIox*xi", loc_id, group_name, idx_type, order, op, op_data,
1418 lapl_id);
1419
1420 /* Check args */
1421 if(!group_name || !*group_name)
1422 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
1423 if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1424 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
1425 if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1426 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
1427 if(!op)
1428 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified")
1429
1430 /* Verify access property list and get correct dxpl */
1431 if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
1432 HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
1433
1434 /* Call internal group visitation routine */
1435 if((ret_value = H5G_visit(loc_id, group_name, idx_type, order, op, op_data, lapl_id, dxpl_id)) < 0)
1436 HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed")
1437
1438 done:
1439 FUNC_LEAVE_API(ret_value)
1440 } /* end H5Lvisit_by_name() */
1441
1442 /*
1443 *-------------------------------------------------------------------------
1444 *-------------------------------------------------------------------------
1445 * N O A P I F U N C T I O N S B E Y O N D T H I S P O I N T
1446 *-------------------------------------------------------------------------
1447 *-------------------------------------------------------------------------
1448 */
1449
1450
1451 /*-------------------------------------------------------------------------
1452 * Function: H5L_find_class_idx
1453 *
1454 * Purpose: Given a link class ID, return the offset in the global array
1455 * that holds all the registered link classes.
1456 *
1457 * Return: Success: Non-negative index of entry in global
1458 * link class table.
1459 * Failure: Negative
1460 *
1461 * Programmer: James Laird
1462 * Monday, July 10, 2006
1463 *
1464 *-------------------------------------------------------------------------
1465 */
1466 static int
H5L_find_class_idx(H5L_type_t id)1467 H5L_find_class_idx(H5L_type_t id)
1468 {
1469 size_t i; /* Local index variable */
1470 int ret_value = FAIL; /* Return value */
1471
1472 FUNC_ENTER_NOAPI_NOINIT_NOERR
1473
1474 for(i = 0; i < H5L_table_used_g; i++)
1475 if(H5L_table_g[i].id == id)
1476 HGOTO_DONE((int)i)
1477
1478 done:
1479 FUNC_LEAVE_NOAPI(ret_value)
1480 } /* end H5L_find_class_idx */
1481
1482
1483 /*-------------------------------------------------------------------------
1484 * Function: H5L_find_class
1485 *
1486 * Purpose: Given a link class ID return a pointer to a global struct that
1487 * defines the link class.
1488 *
1489 * Return: Success: Ptr to entry in global link class table.
1490 * Failure: NULL
1491 *
1492 * Programmer: James Laird
1493 * Monday, July 10, 2006
1494 *
1495 *-------------------------------------------------------------------------
1496 */
1497 const H5L_class_t *
H5L_find_class(H5L_type_t id)1498 H5L_find_class(H5L_type_t id)
1499 {
1500 int idx; /* Filter index in global table */
1501 H5L_class_t *ret_value = NULL; /* Return value */
1502
1503 FUNC_ENTER_NOAPI(NULL)
1504
1505 /* Get the index in the global table */
1506 if((idx = H5L_find_class_idx(id)) < 0)
1507 HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, NULL, "unable to find link class")
1508
1509 /* Set return value */
1510 ret_value = H5L_table_g+idx;
1511
1512 done:
1513 FUNC_LEAVE_NOAPI(ret_value)
1514 } /* end H5L_find_class */
1515
1516
1517 /*-------------------------------------------------------------------------
1518 * Function: H5L_register
1519 *
1520 * Purpose: Registers a class of user-defined links, or changes the
1521 * behavior of an existing class.
1522 *
1523 * See H5Lregister for full documentation.
1524 *
1525 * Return: Non-negative on success/Negative on failure
1526 *
1527 * Programmer: James Laird
1528 * Monday, July 10, 2006
1529 *
1530 *-------------------------------------------------------------------------
1531 */
1532 herr_t
H5L_register(const H5L_class_t * cls)1533 H5L_register(const H5L_class_t *cls)
1534 {
1535 size_t i; /* Local index variable */
1536 herr_t ret_value = SUCCEED; /* Return value */
1537
1538 FUNC_ENTER_NOAPI(FAIL)
1539
1540 HDassert(cls);
1541 HDassert(cls->id >= 0 && cls->id <= H5L_TYPE_MAX);
1542
1543 /* Is the link type already registered? */
1544 for(i = 0; i < H5L_table_used_g; i++)
1545 if(H5L_table_g[i].id == cls->id)
1546 break;
1547
1548 /* Filter not already registered */
1549 if(i >= H5L_table_used_g) {
1550 if(H5L_table_used_g >= H5L_table_alloc_g) {
1551 size_t n = MAX(H5L_MIN_TABLE_SIZE, (2 * H5L_table_alloc_g));
1552 H5L_class_t *table = (H5L_class_t *)H5MM_realloc(H5L_table_g, (n * sizeof(H5L_class_t)));
1553 if(!table)
1554 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to extend link type table")
1555 H5L_table_g = table;
1556 H5L_table_alloc_g = n;
1557 } /* end if */
1558
1559 /* Initialize */
1560 i = H5L_table_used_g++;
1561 } /* end if */
1562
1563 /* Copy link class info into table */
1564 HDmemcpy(H5L_table_g + i, cls, sizeof(H5L_class_t));
1565
1566 done:
1567 FUNC_LEAVE_NOAPI(ret_value)
1568 } /* end H5L_register */
1569
1570
1571 /*-------------------------------------------------------------------------
1572 * Function: H5L_unregister
1573 *
1574 * Purpose: Unregisters a class of user-defined links.
1575 *
1576 * See H5Lunregister for full documentation.
1577 *
1578 * Return: Non-negative on success/Negative on failure
1579 *
1580 * Programmer: James Laird
1581 * Monday, July 10, 2006
1582 *
1583 *-------------------------------------------------------------------------
1584 */
1585 herr_t
H5L_unregister(H5L_type_t id)1586 H5L_unregister(H5L_type_t id)
1587 {
1588 size_t i; /* Local index variable */
1589 herr_t ret_value = SUCCEED; /* Return value */
1590
1591 FUNC_ENTER_NOAPI(FAIL)
1592
1593 HDassert(id >= 0 && id <= H5L_TYPE_MAX);
1594
1595 /* Is the filter already registered? */
1596 for(i = 0; i < H5L_table_used_g; i++)
1597 if(H5L_table_g[i].id == id)
1598 break;
1599
1600 /* Fail if filter not found */
1601 if(i >= H5L_table_used_g)
1602 HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "link class is not registered")
1603
1604 /* Remove filter from table */
1605 /* Don't worry about shrinking table size (for now) */
1606 HDmemmove(&H5L_table_g[i], &H5L_table_g[i + 1], sizeof(H5L_class_t) * ((H5L_table_used_g - 1) - i));
1607 H5L_table_used_g--;
1608
1609 done:
1610 FUNC_LEAVE_NOAPI(ret_value)
1611 } /* end H5L_unregister() */
1612
1613
1614 /*-------------------------------------------------------------------------
1615 * Function: H5L_link
1616 *
1617 * Purpose: Creates a link from OBJ_ID to CUR_NAME. See H5Olink() for
1618 * full documentation.
1619 *
1620 * Return: Non-negative on success/Negative on failure
1621 *
1622 * Programmer: James Laird
1623 * Tuesday, December 13, 2005
1624 *
1625 *-------------------------------------------------------------------------
1626 */
1627 herr_t
H5L_link(const H5G_loc_t * new_loc,const char * new_name,H5G_loc_t * obj_loc,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id)1628 H5L_link(const H5G_loc_t *new_loc, const char *new_name, H5G_loc_t *obj_loc,
1629 hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id)
1630 {
1631 H5O_link_t lnk; /* Link to insert */
1632 herr_t ret_value = SUCCEED; /* Return value */
1633
1634 FUNC_ENTER_NOAPI_NOINIT
1635
1636 /* Check args */
1637 HDassert(new_loc);
1638 HDassert(obj_loc);
1639 HDassert(new_name && *new_name);
1640
1641 /* The link callback will check that the object isn't being hard linked
1642 * into a different file, so we don't need to do it here (there could be
1643 * external links along the path).
1644 */
1645
1646 /* Construct link information for eventual insertion */
1647 lnk.type = H5L_TYPE_HARD;
1648 lnk.u.hard.addr = obj_loc->oloc->addr;
1649
1650 /* Create the link */
1651 if(H5L_create_real(new_loc, new_name, obj_loc->path, obj_loc->oloc->file, &lnk, NULL, lcpl_id, lapl_id, dxpl_id) < 0)
1652 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link to object")
1653
1654 done:
1655 FUNC_LEAVE_NOAPI(ret_value)
1656 } /* end H5L_link() */
1657
1658
1659 /*-------------------------------------------------------------------------
1660 * Function: H5L_link_object
1661 *
1662 * Purpose: Creates a new object and a link to it.
1663 *
1664 * Return: Non-negative on success/Negative on failure
1665 *
1666 * Programmer: Quincey Koziol
1667 * Monday, April 9, 2007
1668 *
1669 *-------------------------------------------------------------------------
1670 */
1671 herr_t
H5L_link_object(const H5G_loc_t * new_loc,const char * new_name,H5O_obj_create_t * ocrt_info,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id)1672 H5L_link_object(const H5G_loc_t *new_loc, const char *new_name,
1673 H5O_obj_create_t *ocrt_info, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id)
1674 {
1675 H5O_link_t lnk; /* Link to insert */
1676 herr_t ret_value = SUCCEED; /* Return value */
1677
1678 FUNC_ENTER_NOAPI_NOINIT
1679
1680 /* Check args */
1681 HDassert(new_loc);
1682 HDassert(new_name && *new_name);
1683 HDassert(ocrt_info);
1684
1685 /* The link callback will check that the object isn't being hard linked
1686 * into a different file, so we don't need to do it here (there could be
1687 * external links along the path).
1688 */
1689
1690 /* Construct link information for eventual insertion */
1691 lnk.type = H5L_TYPE_HARD;
1692
1693 /* Create the link */
1694 if(H5L_create_real(new_loc, new_name, NULL, NULL, &lnk, ocrt_info, lcpl_id, lapl_id, dxpl_id) < 0)
1695 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link to object")
1696
1697 done:
1698 FUNC_LEAVE_NOAPI(ret_value)
1699 } /* end H5L_link_object() */
1700
1701
1702 /*-------------------------------------------------------------------------
1703 * Function: H5L_link_cb
1704 *
1705 * Purpose: Callback for creating a link to an object.
1706 *
1707 * Return: Non-negative on success/Negative on failure
1708 *
1709 * Programmer: Quincey Koziol
1710 * Monday, September 19, 2005
1711 *
1712 *-------------------------------------------------------------------------
1713 */
1714 static herr_t
H5L_link_cb(H5G_loc_t * grp_loc,const char * name,const H5O_link_t H5_ATTR_UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)1715 H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t H5_ATTR_UNUSED *lnk,
1716 H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/)
1717 {
1718 H5L_trav_cr_t *udata = (H5L_trav_cr_t *)_udata; /* User data passed in */
1719 H5G_t *grp = NULL; /* H5G_t for this group, opened to pass to user callback */
1720 hid_t grp_id = FAIL; /* Id for this group (passed to user callback */
1721 H5G_loc_t temp_loc; /* For UD callback */
1722 hbool_t temp_loc_init = FALSE; /* Temporary location for UD callback (temp_loc) has been initialized */
1723 hbool_t obj_created = FALSE; /* Whether an object was created (through a hard link) */
1724 herr_t ret_value = SUCCEED; /* Return value */
1725
1726 FUNC_ENTER_NOAPI_NOINIT
1727
1728 /* Check if the name in this group resolved to a valid location */
1729 /* (which is not what we want) */
1730 if(obj_loc != NULL)
1731 HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name already exists")
1732
1733 /* Check for crossing file boundaries with a new hard link */
1734 if(udata->lnk->type == H5L_TYPE_HARD) {
1735 /* Check for creating an object */
1736 /* (only for hard links) */
1737 if(udata->ocrt_info) {
1738 H5G_loc_t new_loc; /* Group location for new object */
1739
1740 /* Create new object at this location */
1741 if(NULL == (udata->ocrt_info->new_obj = H5O_obj_create(grp_loc->oloc->file, udata->ocrt_info->obj_type, udata->ocrt_info->crt_info, &new_loc, udata->dxpl_id)))
1742 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create object")
1743
1744 /* Set address for hard link */
1745 udata->lnk->u.hard.addr = new_loc.oloc->addr;
1746
1747 /* Set object path to use for setting object name (below) */
1748 udata->path = new_loc.path;
1749
1750 /* Indicate that an object was created */
1751 obj_created = TRUE;
1752 } /* end if */
1753 else {
1754 /* Check that both objects are in same file */
1755 if(!H5F_SAME_SHARED(grp_loc->oloc->file, udata->file))
1756 HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "interfile hard links are not allowed")
1757 } /* end else */
1758 } /* end if */
1759
1760 /* Set 'standard' aspects of link */
1761 udata->lnk->corder = 0; /* Will be re-written during group insertion, if the group is tracking creation order */
1762 udata->lnk->corder_valid = FALSE; /* Creation order not valid (yet) */
1763
1764 /* Check for non-default link creation properties */
1765 if(udata->lc_plist) {
1766 /* Get character encoding property */
1767 if(H5P_get(udata->lc_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &udata->lnk->cset) < 0)
1768 HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for character encoding")
1769 } /* end if */
1770 else
1771 udata->lnk->cset = H5F_DEFAULT_CSET; /* Default character encoding for link */
1772
1773 /* Set the link's name correctly */
1774 /* Casting away const OK -QAK */
1775 udata->lnk->name = (char *)name;
1776
1777 /* Insert link into group */
1778 if(H5G_obj_insert(grp_loc->oloc, name, udata->lnk, TRUE,
1779 udata->ocrt_info ? udata->ocrt_info->obj_type : H5O_TYPE_UNKNOWN,
1780 udata->ocrt_info ? udata->ocrt_info->crt_info : NULL,
1781 udata->dxpl_id) < 0)
1782 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link for object")
1783
1784 /* Set object's path if it has been passed in and is not set */
1785 if(udata->path != NULL && udata->path->user_path_r == NULL)
1786 if(H5G_name_set(grp_loc->path, udata->path, name) < 0)
1787 HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name")
1788
1789 /* If link is a user-defined link, trigger its creation callback if it has one */
1790 if(udata->lnk->type >= H5L_TYPE_UD_MIN) {
1791 const H5L_class_t *link_class; /* User-defined link class */
1792
1793 /* Get the link class for this type of link. */
1794 if(NULL == (link_class = H5L_find_class(udata->lnk->type)))
1795 HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "unable to get class of UD link")
1796
1797 if(link_class->create_func != NULL) {
1798 H5O_loc_t temp_oloc;
1799 H5G_name_t temp_path;
1800
1801 /* Create a temporary location (or else H5G_open will do a shallow
1802 * copy and wipe out grp_loc)
1803 */
1804 H5G_name_reset(&temp_path);
1805 if(H5O_loc_copy(&temp_oloc, grp_loc->oloc, H5_COPY_DEEP) < 0)
1806 HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location")
1807
1808 temp_loc.oloc = &temp_oloc;
1809 temp_loc.path = &temp_path;
1810 temp_loc_init = TRUE;
1811
1812 /* Set up location for user-defined callback */
1813 if((grp = H5G_open(&temp_loc, udata->dxpl_id)) == NULL)
1814 HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
1815 if((grp_id = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
1816 HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register ID for group")
1817
1818 /* Make callback */
1819 if((link_class->create_func)(name, grp_id, udata->lnk->u.ud.udata, udata->lnk->u.ud.size, H5P_DEFAULT) < 0)
1820 HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "link creation callback failed")
1821 } /* end if */
1822 } /* end if */
1823
1824 done:
1825 /* Check if an object was created */
1826 if(obj_created) {
1827 H5O_loc_t oloc; /* Object location for created object */
1828
1829 /* Set up object location */
1830 HDmemset(&oloc, 0, sizeof(oloc));
1831 oloc.file = grp_loc->oloc->file;
1832 oloc.addr = udata->lnk->u.hard.addr;
1833
1834 /* Decrement refcount on new object's object header in memory */
1835 if(H5O_dec_rc_by_loc(&oloc, udata->dxpl_id) < 0)
1836 HDONE_ERROR(H5E_LINK, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object")
1837 } /* end if */
1838
1839 /* Close the location given to the user callback if it was created */
1840 if(grp_id >= 0) {
1841 if(H5I_dec_app_ref(grp_id) < 0)
1842 HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback")
1843 } /* end if */
1844 else if(grp != NULL) {
1845 if(H5G_close(grp) < 0)
1846 HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close group given to UD callback")
1847 } /* end if */
1848 else if(temp_loc_init)
1849 H5G_loc_free(&temp_loc);
1850
1851 /* Indicate that this callback didn't take ownership of the group *
1852 * location for the object */
1853 *own_loc = H5G_OWN_NONE;
1854
1855 FUNC_LEAVE_NOAPI(ret_value)
1856 } /* end H5L_link_cb() */
1857
1858
1859 /*-------------------------------------------------------------------------
1860 * Function: H5L_create_real
1861 *
1862 * Purpose: Creates a link at a path location
1863 *
1864 * lnk should have linkclass-specific information already
1865 * set, but this function will take care of setting name.
1866 *
1867 * obj_path can be NULL if the object's path doesn't need to
1868 * be set, and obj_file can be NULL if the object is not a
1869 * hard link.
1870 *
1871 * Return: Non-negative on success/Negative on failure
1872 *
1873 * Programmer: Quincey Koziol
1874 * Monday, December 5, 2005
1875 *
1876 *-------------------------------------------------------------------------
1877 */
1878 static herr_t
H5L_create_real(const H5G_loc_t * link_loc,const char * link_name,H5G_name_t * obj_path,H5F_t * obj_file,H5O_link_t * lnk,H5O_obj_create_t * ocrt_info,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id)1879 H5L_create_real(const H5G_loc_t *link_loc, const char *link_name,
1880 H5G_name_t *obj_path, H5F_t *obj_file, H5O_link_t *lnk,
1881 H5O_obj_create_t *ocrt_info, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id)
1882 {
1883 char *norm_link_name = NULL; /* Pointer to normalized link name */
1884 unsigned target_flags = H5G_TARGET_NORMAL; /* Flags to pass to group traversal function */
1885 H5P_genplist_t *lc_plist = NULL; /* Link creation property list */
1886 H5L_trav_cr_t udata; /* User data for callback */
1887 herr_t ret_value = SUCCEED; /* Return value */
1888
1889 FUNC_ENTER_NOAPI_NOINIT
1890
1891 /* Check args */
1892 HDassert(link_loc);
1893 HDassert(link_name && *link_name);
1894 HDassert(lnk);
1895 HDassert(lnk->type >= H5L_TYPE_HARD && lnk->type <= H5L_TYPE_MAX);
1896
1897 /* Get normalized link name */
1898 if((norm_link_name = H5G_normalize(link_name)) == NULL)
1899 HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name")
1900
1901 /* Check for flags present in creation property list */
1902 if(lcpl_id != H5P_DEFAULT) {
1903 unsigned crt_intmd_group;
1904
1905 /* Get link creation property list */
1906 if(NULL == (lc_plist = (H5P_genplist_t *)H5I_object(lcpl_id)))
1907 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
1908
1909 /* Get intermediate group creation property */
1910 if(H5P_get(lc_plist, H5L_CRT_INTERMEDIATE_GROUP_NAME, &crt_intmd_group) < 0)
1911 HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for creating missing groups")
1912
1913 if(crt_intmd_group > 0)
1914 target_flags |= H5G_CRT_INTMD_GROUP;
1915 } /* end if */
1916
1917 /* Set up user data
1918 * FILE is used to make sure that hard links don't cross files, and
1919 * should be NULL for other link types.
1920 * LC_PLIST is a pointer to the link creation property list.
1921 * DXPL_ID is the dxpl ID that needs to be used during writes and reads.
1922 * PATH is a pointer to the path of the object being inserted if this is
1923 * a hard link; this is used to set the paths to objects when they are
1924 * created. For other link types, this is NULL.
1925 * OCRT_INFO is a pointer to the structure for object creation.
1926 * LNK is the link struct passed into this function. At this point all
1927 * of its fields should be populated except for name, which is set when
1928 * inserting it in the callback.
1929 */
1930 udata.file = obj_file;
1931 udata.lc_plist = lc_plist;
1932 udata.dxpl_id = dxpl_id;
1933 udata.path = obj_path;
1934 udata.ocrt_info = ocrt_info;
1935 udata.lnk = lnk;
1936
1937 /* Traverse the destination path & create new link */
1938 if(H5G_traverse(link_loc, link_name, target_flags, H5L_link_cb, &udata, lapl_id, dxpl_id) < 0)
1939 HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert link")
1940
1941 done:
1942 /* Free the normalized path name */
1943 if(norm_link_name)
1944 H5MM_xfree(norm_link_name);
1945
1946 FUNC_LEAVE_NOAPI(ret_value)
1947 } /* end H5L_create_real() */
1948
1949
1950 /*-------------------------------------------------------------------------
1951 * Function: H5L_create_hard
1952 *
1953 * Purpose: Creates a hard link from NEW_NAME to CUR_NAME.
1954 *
1955 * Return: Non-negative on success/Negative on failure
1956 *
1957 * Programmer: Robb Matzke
1958 * Monday, April 6, 1998
1959 *
1960 *-------------------------------------------------------------------------
1961 */
1962 herr_t
H5L_create_hard(H5G_loc_t * cur_loc,const char * cur_name,const H5G_loc_t * link_loc,const char * link_name,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id)1963 H5L_create_hard(H5G_loc_t *cur_loc, const char *cur_name,
1964 const H5G_loc_t *link_loc, const char *link_name, hid_t lcpl_id,
1965 hid_t lapl_id, hid_t dxpl_id)
1966 {
1967 char *norm_cur_name = NULL; /* Pointer to normalized current name */
1968 H5F_t *link_file = NULL; /* Pointer to file to link to */
1969 H5O_link_t lnk; /* Link to insert */
1970 H5G_loc_t obj_loc; /* Location of object to link to */
1971 H5G_name_t path; /* obj_loc's path*/
1972 H5O_loc_t oloc; /* obj_loc's oloc */
1973 hbool_t loc_valid = FALSE;
1974 herr_t ret_value = SUCCEED; /* Return value */
1975
1976 FUNC_ENTER_NOAPI(FAIL)
1977
1978 /* Check args */
1979 HDassert(cur_loc);
1980 HDassert(cur_name && *cur_name);
1981 HDassert(link_loc);
1982 HDassert(link_name && *link_name);
1983
1984 /* Get normalized copy of the current name */
1985 if((norm_cur_name = H5G_normalize(cur_name)) == NULL)
1986 HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name")
1987
1988 /* Set up link data specific to hard links */
1989 lnk.type = H5L_TYPE_HARD;
1990
1991 /* Get object location for object pointed to */
1992 obj_loc.path = &path;
1993 obj_loc.oloc = &oloc;
1994 H5G_loc_reset(&obj_loc);
1995 if(H5G_loc_find(cur_loc, norm_cur_name, &obj_loc, lapl_id, dxpl_id) < 0)
1996 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "source object not found")
1997 loc_valid = TRUE;
1998
1999 /* Construct link information for eventual insertion */
2000 lnk.u.hard.addr = obj_loc.oloc->addr;
2001
2002 /* Set destination's file information */
2003 link_file = obj_loc.oloc->file;
2004
2005 /* Create actual link to the object. Pass in NULL for the path, since this
2006 * function shouldn't change an object's user path. */
2007 if(H5L_create_real(link_loc, link_name, NULL, link_file, &lnk, NULL, lcpl_id, lapl_id, dxpl_id) < 0)
2008 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link to object")
2009
2010 done:
2011 /* Free the object header location */
2012 if(loc_valid)
2013 if(H5G_loc_free(&obj_loc) < 0)
2014 HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to free location")
2015
2016 /* Free the normalized path name */
2017 if(norm_cur_name)
2018 H5MM_xfree(norm_cur_name);
2019
2020 FUNC_LEAVE_NOAPI(ret_value)
2021 } /* end H5L_create_hard() */
2022
2023
2024 /*-------------------------------------------------------------------------
2025 * Function: H5L_create_soft
2026 *
2027 * Purpose: Creates a soft link from LINK_NAME to TARGET_PATH.
2028 *
2029 * Return: Non-negative on success/Negative on failure
2030 *
2031 * Programmer: Robb Matzke
2032 * Monday, April 6, 1998
2033 *
2034 *-------------------------------------------------------------------------
2035 */
2036 herr_t
H5L_create_soft(const char * target_path,const H5G_loc_t * link_loc,const char * link_name,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id)2037 H5L_create_soft(const char *target_path, const H5G_loc_t *link_loc,
2038 const char *link_name, hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id)
2039 {
2040 char *norm_target = NULL; /* Pointer to normalized current name */
2041 H5O_link_t lnk; /* Link to insert */
2042 herr_t ret_value = SUCCEED; /* Return value */
2043
2044 FUNC_ENTER_NOAPI(FAIL)
2045
2046 /* Check args */
2047 HDassert(link_loc);
2048 HDassert(target_path && *target_path);
2049 HDassert(link_name && *link_name);
2050
2051 /* Get normalized copy of the link target */
2052 if((norm_target = H5G_normalize(target_path)) == NULL)
2053 HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name")
2054
2055 /* Set up link data specific to soft links */
2056 lnk.type = H5L_TYPE_SOFT;
2057 lnk.u.soft.name = norm_target;
2058
2059 /* Create actual link to the object */
2060 if(H5L_create_real(link_loc, link_name, NULL, NULL, &lnk, NULL, lcpl_id, lapl_id, dxpl_id) < 0)
2061 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link to object")
2062
2063 done:
2064 /* Free the normalized target name */
2065 if(norm_target)
2066 H5MM_xfree(norm_target);
2067
2068 FUNC_LEAVE_NOAPI(ret_value)
2069 } /* end H5L_create_soft() */
2070
2071
2072 /*-------------------------------------------------------------------------
2073 * Function: H5L_create_ud
2074 *
2075 * Purpose: Creates a user-defined link. See H5Lcreate_ud for
2076 * full documentation.
2077 *
2078 * Return: Non-negative on success/Negative on failure
2079 *
2080 * Programmer: James Laird
2081 * Friday, May 19, 2006
2082 *
2083 *-------------------------------------------------------------------------
2084 */
2085 herr_t
H5L_create_ud(const H5G_loc_t * link_loc,const char * link_name,const void * ud_data,size_t ud_data_size,H5L_type_t type,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id)2086 H5L_create_ud(const H5G_loc_t *link_loc, const char *link_name,
2087 const void *ud_data, size_t ud_data_size, H5L_type_t type, hid_t lcpl_id,
2088 hid_t lapl_id, hid_t dxpl_id)
2089 {
2090 H5O_link_t lnk; /* Link to insert */
2091 herr_t ret_value = SUCCEED; /* Return value */
2092
2093 FUNC_ENTER_NOAPI_NOINIT
2094
2095 /* Check args */
2096 HDassert(type >= H5L_TYPE_UD_MIN && type <= H5L_TYPE_MAX);
2097 HDassert(link_loc);
2098 HDassert(link_name && *link_name);
2099 HDassert(ud_data_size == 0 || ud_data);
2100
2101 /* Initialize the link struct's pointer to its udata buffer */
2102 lnk.u.ud.udata = NULL;
2103
2104 /* Make sure that this link class is registered */
2105 if(H5L_find_class_idx(type) < 0)
2106 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "link class has not been registered with library")
2107
2108 /* Fill in UD link-specific information in the link struct*/
2109 if(ud_data_size > 0) {
2110 lnk.u.ud.udata = H5MM_malloc((size_t)ud_data_size);
2111 HDmemcpy(lnk.u.ud.udata, ud_data, (size_t) ud_data_size);
2112 } /* end if */
2113 else
2114 lnk.u.ud.udata = NULL;
2115
2116 lnk.u.ud.size = ud_data_size;
2117 lnk.type = type;
2118
2119 /* Create actual link to the object */
2120 if(H5L_create_real(link_loc, link_name, NULL, NULL, &lnk, NULL, lcpl_id, lapl_id, dxpl_id) < 0)
2121 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to register new name for object")
2122
2123 done:
2124 /* Free the link's udata buffer if it's been allocated */
2125 H5MM_xfree(lnk.u.ud.udata);
2126
2127 FUNC_LEAVE_NOAPI(ret_value)
2128 } /* end H5L_create_ud() */
2129
2130
2131 /*-------------------------------------------------------------------------
2132 * Function: H5L_get_val_real
2133 *
2134 * Purpose: Retrieve link value from a link object
2135 *
2136 * Return: Non-negative on success/Negative on failure
2137 *
2138 * Programmer: Quincey Koziol
2139 * Monday, November 13 2006
2140 *
2141 *-------------------------------------------------------------------------
2142 */
2143 static herr_t
H5L_get_val_real(const H5O_link_t * lnk,void * buf,size_t size)2144 H5L_get_val_real(const H5O_link_t *lnk, void *buf, size_t size)
2145 {
2146 herr_t ret_value = SUCCEED; /* Return value */
2147
2148 FUNC_ENTER_NOAPI_NOINIT
2149
2150 /* Sanity check */
2151 HDassert(lnk);
2152
2153 /* Check for soft link */
2154 if(H5L_TYPE_SOFT == lnk->type) {
2155 /* Copy to output buffer */
2156 if(size > 0 && buf) {
2157 HDstrncpy((char *)buf, lnk->u.soft.name, size);
2158 if(HDstrlen(lnk->u.soft.name) >= size)
2159 ((char *)buf)[size - 1] = '\0';
2160 } /* end if */
2161 } /* end if */
2162 /* Check for user-defined link */
2163 else if(lnk->type >= H5L_TYPE_UD_MIN) {
2164 const H5L_class_t *link_class; /* User-defined link class */
2165
2166 /* Get the link class for this type of link. It's okay if the class
2167 * isn't registered, though--we just can't give any more information
2168 * about it
2169 */
2170 link_class = H5L_find_class(lnk->type);
2171
2172 if(link_class != NULL && link_class->query_func != NULL) {
2173 if((link_class->query_func)(lnk->name, lnk->u.ud.udata, lnk->u.ud.size, buf, size) < 0)
2174 HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "query callback returned failure")
2175 } /* end if */
2176 else if(buf && size > 0)
2177 ((char *)buf)[0] = '\0';
2178 } /* end if */
2179 else
2180 HGOTO_ERROR(H5E_LINK, H5E_BADTYPE, FAIL, "object is not a symbolic or user-defined link")
2181
2182 done:
2183 FUNC_LEAVE_NOAPI(ret_value)
2184 } /* end H5L_get_val_real() */
2185
2186
2187 /*-------------------------------------------------------------------------
2188 * Function: H5L_get_val_cb
2189 *
2190 * Purpose: Callback for retrieving link value or udata.
2191 *
2192 * Return: Non-negative on success/Negative on failure
2193 *
2194 * Programmer: Quincey Koziol
2195 * Tuesday, September 20, 2005
2196 *
2197 *-------------------------------------------------------------------------
2198 */
2199 static herr_t
H5L_get_val_cb(H5G_loc_t H5_ATTR_UNUSED * grp_loc,const char * name,const H5O_link_t * lnk,H5G_loc_t H5_ATTR_UNUSED * obj_loc,void * _udata,H5G_own_loc_t * own_loc)2200 H5L_get_val_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc/*in*/, const char *name, const H5O_link_t *lnk,
2201 H5G_loc_t H5_ATTR_UNUSED *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/)
2202 {
2203 H5L_trav_gv_t *udata = (H5L_trav_gv_t *)_udata; /* User data passed in */
2204 herr_t ret_value = SUCCEED; /* Return value */
2205
2206 FUNC_ENTER_NOAPI_NOINIT
2207
2208 /* Check if the name in this group resolved to a valid link */
2209 if(lnk == NULL)
2210 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "'%s' doesn't exist", name)
2211
2212 /* Retrieve the value for the link */
2213 if(H5L_get_val_real(lnk, udata->buf, udata->size) < 0)
2214 HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't retrieve link value")
2215
2216 done:
2217 /* Indicate that this callback didn't take ownership of the group *
2218 * location for the object */
2219 *own_loc = H5G_OWN_NONE;
2220
2221 FUNC_LEAVE_NOAPI(ret_value)
2222 } /* end H5L_get_val_cb() */
2223
2224
2225 /*-------------------------------------------------------------------------
2226 * Function: H5L_get_val
2227 *
2228 * Purpose: Returns the value of a symbolic link or the udata for a
2229 * user-defined link.
2230 *
2231 * Return: Success: Non-negative, with at most SIZE bytes of the
2232 * link value copied into the BUF buffer. If the
2233 * link value is larger than SIZE characters
2234 * counting the null terminator then the BUF
2235 * result will not be null terminated.
2236 *
2237 * Failure: Negative
2238 *
2239 * Programmer: Robb Matzke
2240 * Monday, April 13, 1998
2241 *
2242 *-------------------------------------------------------------------------
2243 */
2244 herr_t
H5L_get_val(H5G_loc_t * loc,const char * name,void * buf,size_t size,hid_t lapl_id,hid_t dxpl_id)2245 H5L_get_val(H5G_loc_t *loc, const char *name, void *buf/*out*/, size_t size,
2246 hid_t lapl_id, hid_t dxpl_id)
2247 {
2248 H5L_trav_gv_t udata; /* User data for callback */
2249 herr_t ret_value = SUCCEED; /* Return value */
2250
2251 FUNC_ENTER_NOAPI(FAIL)
2252
2253 /* Sanity check */
2254 HDassert(loc);
2255 HDassert(name && *name);
2256
2257 /* Set up user data for retrieving information */
2258 udata.size = size;
2259 udata.buf = buf;
2260
2261 /* Traverse the group hierarchy to locate the object to get info about */
2262 if(H5G_traverse(loc, name, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, H5L_get_val_cb, &udata, lapl_id, dxpl_id) < 0)
2263 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
2264
2265 done:
2266 FUNC_LEAVE_NOAPI(ret_value)
2267 } /* H5L_get_val() */
2268
2269
2270 /*-------------------------------------------------------------------------
2271 * Function: H5L_get_val_by_idx_cb
2272 *
2273 * Purpose: Callback for retrieving a link's value according to an
2274 * index's order.
2275 *
2276 * Return: Non-negative on success/Negative on failure
2277 *
2278 * Programmer: Quincey Koziol
2279 * Monday, November 13 2006
2280 *
2281 *-------------------------------------------------------------------------
2282 */
2283 static herr_t
H5L_get_val_by_idx_cb(H5G_loc_t H5_ATTR_UNUSED * grp_loc,const char H5_ATTR_UNUSED * name,const H5O_link_t H5_ATTR_UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)2284 H5L_get_val_by_idx_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc/*in*/, const char H5_ATTR_UNUSED *name,
2285 const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
2286 H5G_own_loc_t *own_loc/*out*/)
2287 {
2288 H5L_trav_gvbi_t *udata = (H5L_trav_gvbi_t *)_udata; /* User data passed in */
2289 H5O_link_t fnd_lnk; /* Link within group */
2290 hbool_t lnk_copied = FALSE; /* Whether the link was copied */
2291 herr_t ret_value = SUCCEED; /* Return value */
2292
2293 FUNC_ENTER_NOAPI_NOINIT
2294
2295 /* Check if the name of the group resolved to a valid object */
2296 if(obj_loc == NULL)
2297 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist")
2298
2299 /* Query link */
2300 if(H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order,
2301 udata->n, &fnd_lnk, udata->dxpl_id) < 0)
2302 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found")
2303 lnk_copied = TRUE;
2304
2305 /* Retrieve the value for the link */
2306 if(H5L_get_val_real(&fnd_lnk, udata->buf, udata->size) < 0)
2307 HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't retrieve link value")
2308
2309 done:
2310 /* Reset the link information, if we have a copy */
2311 if(lnk_copied)
2312 H5O_msg_reset(H5O_LINK_ID, &fnd_lnk);
2313
2314 /* Indicate that this callback didn't take ownership of the group *
2315 * location for the object */
2316 *own_loc = H5G_OWN_NONE;
2317
2318 FUNC_LEAVE_NOAPI(ret_value)
2319 } /* end H5L_get_val_by_idx_cb() */
2320
2321
2322 /*-------------------------------------------------------------------------
2323 * Function: H5L_delete_cb
2324 *
2325 * Purpose: Callback for deleting a link. This routine
2326 * actually deletes the link
2327 *
2328 * Return: Non-negative on success/Negative on failure
2329 *
2330 * Programmer: Quincey Koziol
2331 * Monday, September 19, 2005
2332 *
2333 *-------------------------------------------------------------------------
2334 */
2335 static herr_t
H5L_delete_cb(H5G_loc_t * grp_loc,const char * name,const H5O_link_t * lnk,H5G_loc_t H5_ATTR_UNUSED * obj_loc,void * _udata,H5G_own_loc_t * own_loc)2336 H5L_delete_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk,
2337 H5G_loc_t H5_ATTR_UNUSED *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/)
2338 {
2339 H5L_trav_rm_t *udata = (H5L_trav_rm_t *)_udata; /* User data passed in */
2340 herr_t ret_value = SUCCEED;
2341
2342 FUNC_ENTER_NOAPI_NOINIT
2343
2344 /* Check if the group resolved to a valid link */
2345 if(grp_loc == NULL)
2346 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist")
2347
2348 /* Check if the name in this group resolved to a valid link */
2349 if(name == NULL)
2350 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
2351
2352 /* Check for non-existent (NULL) link.
2353 * Note that this can also occur when attempting to remove '.'
2354 */
2355 if(lnk == NULL)
2356 HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "callback link pointer is NULL (specified link may be '.' or not exist)")
2357
2358 /* Remove the link from the group */
2359 if(H5G_obj_remove(grp_loc->oloc, grp_loc->path->full_path_r, name, udata->dxpl_id) < 0)
2360 HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to remove link from group")
2361
2362 done:
2363 /* Indicate that this callback didn't take ownership of the group *
2364 * location for the object */
2365 *own_loc = H5G_OWN_NONE;
2366
2367 FUNC_LEAVE_NOAPI(ret_value)
2368 } /* end H5L_delete_cb() */
2369
2370
2371 /*-------------------------------------------------------------------------
2372 * Function: H5L_delete
2373 *
2374 * Purpose: Delete a link from a group.
2375 *
2376 * Return: Non-negative on success/Negative on failure
2377 *
2378 * Programmer: Robb Matzke
2379 * Thursday, September 17, 1998
2380 *
2381 *-------------------------------------------------------------------------
2382 */
2383 herr_t
H5L_delete(H5G_loc_t * loc,const char * name,hid_t lapl_id,hid_t dxpl_id)2384 H5L_delete(H5G_loc_t *loc, const char *name, hid_t lapl_id, hid_t dxpl_id)
2385 {
2386 H5L_trav_rm_t udata; /* User data for callback */
2387 char *norm_name = NULL; /* Pointer to normalized name */
2388 herr_t ret_value = SUCCEED; /* Return value */
2389
2390 FUNC_ENTER_NOAPI(FAIL)
2391
2392 /* Sanity check */
2393 HDassert(loc);
2394 HDassert(name && *name);
2395
2396 /* Get normalized copy of the name */
2397 if((norm_name = H5G_normalize(name)) == NULL)
2398 HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name")
2399
2400 /* Set up user data for unlink operation */
2401 udata.dxpl_id = dxpl_id;
2402 if(H5G_traverse(loc, norm_name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK|H5G_TARGET_MOUNT, H5L_delete_cb, &udata, lapl_id, dxpl_id) < 0)
2403 HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "can't unlink object")
2404
2405 done:
2406 /* Free the normalized path name */
2407 if(norm_name)
2408 H5MM_xfree(norm_name);
2409
2410 FUNC_LEAVE_NOAPI(ret_value)
2411 } /* end H5L_delete() */
2412
2413
2414 /*-------------------------------------------------------------------------
2415 * Function: H5L_delete_by_idx_cb
2416 *
2417 * Purpose: Callback for removing a link according to an index's order.
2418 *
2419 * Return: Non-negative on success/Negative on failure
2420 *
2421 * Programmer: Quincey Koziol
2422 * Monday, November 13 2006
2423 *
2424 *-------------------------------------------------------------------------
2425 */
2426 static herr_t
H5L_delete_by_idx_cb(H5G_loc_t H5_ATTR_UNUSED * grp_loc,const char H5_ATTR_UNUSED * name,const H5O_link_t H5_ATTR_UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)2427 H5L_delete_by_idx_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc/*in*/, const char H5_ATTR_UNUSED *name,
2428 const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
2429 H5G_own_loc_t *own_loc/*out*/)
2430 {
2431 H5L_trav_gvbi_t *udata = (H5L_trav_gvbi_t *)_udata; /* User data passed in */
2432 herr_t ret_value = SUCCEED; /* Return value */
2433
2434 FUNC_ENTER_NOAPI_NOINIT_TAG(udata->dxpl_id, (obj_loc) ? (obj_loc->oloc->addr) : HADDR_UNDEF, FAIL)
2435
2436 /* Check if the name of the group resolved to a valid object */
2437 if(obj_loc == NULL)
2438 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist")
2439
2440 /* Delete link */
2441 if(H5G_obj_remove_by_idx(obj_loc->oloc, obj_loc->path->full_path_r,
2442 udata->idx_type, udata->order, udata->n, udata->dxpl_id) < 0)
2443 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found")
2444
2445 done:
2446 /* Indicate that this callback didn't take ownership of the group *
2447 * location for the object */
2448 *own_loc = H5G_OWN_NONE;
2449
2450 FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
2451 } /* end H5L_delete_by_idx_cb() */
2452
2453
2454 /*-------------------------------------------------------------------------
2455 * Function: H5L_move_dest_cb
2456 *
2457 * Purpose: Second callback for moving and renaming an object. This routine
2458 * inserts a new link into the group returned by the traversal.
2459 * It is called by H5L_move_cb.
2460 *
2461 * Return: Non-negative on success/Negative on failure
2462 *
2463 * Programmer: James Laird
2464 * Monday, April 3, 2006
2465 *
2466 *-------------------------------------------------------------------------
2467 */
2468 static herr_t
H5L_move_dest_cb(H5G_loc_t * grp_loc,const char * name,const H5O_link_t H5_ATTR_UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)2469 H5L_move_dest_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
2470 const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
2471 H5G_own_loc_t *own_loc/*out*/)
2472 {
2473 H5L_trav_mv2_t *udata = (H5L_trav_mv2_t *)_udata; /* User data passed in */
2474 H5G_t *grp = NULL; /* H5G_t for this group, opened to pass to user callback */
2475 hid_t grp_id = FAIL; /* ID for this group (passed to user callback */
2476 H5G_loc_t temp_loc; /* For UD callback */
2477 hbool_t temp_loc_init = FALSE;
2478 herr_t ret_value = SUCCEED; /* Return value */
2479
2480 FUNC_ENTER_NOAPI_NOINIT
2481
2482 /* Make sure an object with this name doesn't already exist */
2483 if(obj_loc != NULL)
2484 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "an object with that name already exists")
2485
2486 /* Check for crossing file boundaries with a new hard link */
2487 if(udata->lnk->type == H5L_TYPE_HARD) {
2488 /* Check that both objects are in same file */
2489 if(!H5F_SAME_SHARED(grp_loc->oloc->file, udata->file))
2490 HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "moving a link across files is not allowed")
2491 } /* end if */
2492
2493 /* Give the object its new name */
2494 /* Casting away const okay -JML */
2495 HDassert(udata->lnk->name == NULL);
2496 udata->lnk->name = (char *)name;
2497
2498 /* Insert the link into the group */
2499 if(H5G_obj_insert(grp_loc->oloc, name, udata->lnk, TRUE, H5O_TYPE_UNKNOWN,
2500 NULL, udata->dxpl_id) < 0)
2501 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link to object")
2502
2503 /* If the link was a user-defined link, call its move callback if it has one */
2504 if(udata->lnk->type >= H5L_TYPE_UD_MIN) {
2505 const H5L_class_t *link_class; /* User-defined link class */
2506
2507 /* Get the link class for this type of link. */
2508 if(NULL == (link_class = H5L_find_class(udata->lnk->type)))
2509 HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "link class is not registered")
2510
2511 if((!udata->copy && link_class->move_func) || (udata->copy && link_class->copy_func)) {
2512 H5O_loc_t temp_oloc;
2513 H5G_name_t temp_path;
2514
2515 /* Create a temporary location (or else H5G_open will do a shallow
2516 * copy and wipe out grp_loc)
2517 */
2518 H5G_name_reset(&temp_path);
2519 if(H5O_loc_copy(&temp_oloc, grp_loc->oloc, H5_COPY_DEEP) < 0)
2520 HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location")
2521
2522 temp_loc.oloc = &temp_oloc;
2523 temp_loc.path = &temp_path;
2524 temp_loc_init = TRUE;
2525
2526 /* Set up location for user-defined callback */
2527 if((grp = H5G_open(&temp_loc, udata->dxpl_id)) == NULL)
2528 HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
2529 if((grp_id = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
2530 HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group ID")
2531
2532 if(udata->copy) {
2533 if((link_class->copy_func)(udata->lnk->name, grp_id, udata->lnk->u.ud.udata, udata->lnk->u.ud.size) < 0)
2534 HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "UD copy callback returned error")
2535 } /* end if */
2536 else {
2537 if((link_class->move_func)(udata->lnk->name, grp_id, udata->lnk->u.ud.udata, udata->lnk->u.ud.size) < 0)
2538 HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "UD move callback returned error")
2539 } /* end else */
2540 } /* end if */
2541 } /* end if */
2542
2543 done:
2544 /* Close the location given to the user callback if it was created */
2545 if(grp_id >= 0) {
2546 if(H5I_dec_app_ref(grp_id) < 0)
2547 HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback")
2548 } /* end if */
2549 else if(grp != NULL) {
2550 if(H5G_close(grp) < 0)
2551 HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close group given to UD callback")
2552 } /* end if */
2553 else if(temp_loc_init)
2554 H5G_loc_free(&temp_loc);
2555
2556 /* Indicate that this callback didn't take ownership of the group *
2557 * location for the object */
2558 *own_loc = H5G_OWN_NONE;
2559
2560 /* Reset the "name" field in udata->lnk because it is owned by traverse()
2561 * and must not be manipulated after traverse closes */
2562 udata->lnk->name = NULL;
2563
2564 FUNC_LEAVE_NOAPI(ret_value)
2565 } /* end H5L_move_dest_cb() */
2566
2567
2568 /*-------------------------------------------------------------------------
2569 * Function: H5L_move_cb
2570 *
2571 * Purpose: Callback for moving and renaming an object. This routine
2572 * replaces the names of open objects with the moved object
2573 * in the path
2574 *
2575 * Return: Non-negative on success/Negative on failure
2576 *
2577 * Programmer: James Laird
2578 * Friday, April 3, 2006
2579 *
2580 *-------------------------------------------------------------------------
2581 */
2582 static herr_t
H5L_move_cb(H5G_loc_t * grp_loc,const char * name,const H5O_link_t * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)2583 H5L_move_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk,
2584 H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/)
2585 {
2586 H5L_trav_mv_t *udata = (H5L_trav_mv_t *)_udata; /* User data passed in */
2587 H5L_trav_mv2_t udata_out; /* User data for H5L_move_dest_cb traversal */
2588 char * orig_name = NULL; /* The name of the link in this group */
2589 hbool_t link_copied = FALSE; /* Has udata_out.lnk been allocated? */
2590 herr_t ret_value = SUCCEED; /* Return value */
2591
2592 FUNC_ENTER_NOAPI_NOINIT
2593
2594 /* Check if the name in this group resolved to a valid link */
2595 if(obj_loc == NULL)
2596 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
2597
2598 /* Check for operations on '.' */
2599 if(lnk == NULL)
2600 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "the name of a link must be supplied to move or copy")
2601
2602 /* Set up user data for move_dest_cb */
2603 if(NULL == (udata_out.lnk = (H5O_link_t *)H5O_msg_copy(H5O_LINK_ID, lnk, NULL)))
2604 HGOTO_ERROR(H5E_LINK, H5E_CANTCOPY, FAIL, "unable to copy link to be moved")
2605
2606 /* In this special case, the link's name is going to be replaced at its
2607 * destination, so we should free it here.
2608 */
2609 udata_out.lnk->name = (char *)H5MM_xfree(udata_out.lnk->name);
2610 link_copied = TRUE;
2611
2612 udata_out.lnk->cset = udata->cset;
2613 udata_out.file = grp_loc->oloc->file;
2614 udata_out.copy = udata->copy;
2615 udata_out.dxpl_id = udata->dxpl_id;
2616
2617 /* Keep a copy of link's name (it's "owned" by the H5G_traverse() routine) */
2618 orig_name = H5MM_xstrdup(name);
2619
2620 /* Insert the link into its new location */
2621 if(H5G_traverse(udata->dst_loc, udata->dst_name, udata->dst_target_flags,
2622 H5L_move_dest_cb, &udata_out, udata->lapl_id, udata->dxpl_id) < 0)
2623 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to follow symbolic link")
2624
2625 /* If this is a move and not a copy operation, change the object's name and remove the old link */
2626 if(!udata->copy) {
2627 H5RS_str_t *dst_name_r; /* Ref-counted version of dest name */
2628
2629 /* Make certain that the destination name is a full (not relative) path */
2630 if(*(udata->dst_name) != '/') {
2631 HDassert(udata->dst_loc->path->full_path_r);
2632
2633 /* Create reference counted string for full dst path */
2634 if((dst_name_r = H5G_build_fullpath_refstr_str(udata->dst_loc->path->full_path_r,
2635 udata->dst_name)) == NULL)
2636 HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build destination path name")
2637 } /* end if */
2638 else
2639 dst_name_r = H5RS_wrap(udata->dst_name);
2640 HDassert(dst_name_r);
2641
2642 /* Fix names up */
2643 if(H5G_name_replace(lnk, H5G_NAME_MOVE, obj_loc->oloc->file, obj_loc->path->full_path_r,
2644 udata->dst_loc->oloc->file, dst_name_r, udata->dxpl_id) < 0) {
2645 H5RS_decr(dst_name_r);
2646 HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name")
2647 } /* end if */
2648
2649 /* Remove the old link */
2650 if(H5G_obj_remove(grp_loc->oloc, grp_loc->path->full_path_r, orig_name, udata->dxpl_id) < 0) {
2651 H5RS_decr(dst_name_r);
2652 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to remove old name")
2653 } /* end if */
2654
2655 H5RS_decr(dst_name_r);
2656 } /* end if */
2657
2658 done:
2659 /* Cleanup */
2660 if(orig_name)
2661 H5MM_xfree(orig_name);
2662
2663 /* If udata_out.lnk was copied, free any memory allocated
2664 * In this special case, the H5L_move_dest_cb callback resets the name
2665 * so H5O_msg_free shouldn't try to free it
2666 */
2667 if(link_copied)
2668 H5O_msg_free(H5O_LINK_ID, udata_out.lnk);
2669
2670 /* Indicate that this callback didn't take ownership of the group *
2671 * location for the object */
2672 *own_loc = H5G_OWN_NONE;
2673
2674 FUNC_LEAVE_NOAPI(ret_value)
2675 } /* end H5L_move_cb() */
2676
2677
2678 /*-------------------------------------------------------------------------
2679 * Function: H5L_move
2680 *
2681 * Purpose: Atomically move or copy a link.
2682 *
2683 * Creates a copy of a link in a new destination with a new name.
2684 * SRC_LOC and SRC_NAME together define the link's original
2685 * location, while DST_LOC and DST_NAME together define its
2686 * final location.
2687 *
2688 * If copy_flag is FALSE, the original link is removed
2689 * (effectively moving the link).
2690 *
2691 * Return: Non-negative on success/Negative on failure
2692 *
2693 * Programmer: James Laird
2694 * Monday, May 1, 2006
2695 *
2696 *-------------------------------------------------------------------------
2697 */
2698 herr_t
H5L_move(H5G_loc_t * src_loc,const char * src_name,H5G_loc_t * dst_loc,const char * dst_name,hbool_t copy_flag,hid_t lcpl_id,hid_t lapl_id,hid_t dxpl_id)2699 H5L_move(H5G_loc_t *src_loc, const char *src_name, H5G_loc_t *dst_loc,
2700 const char *dst_name, hbool_t copy_flag, hid_t lcpl_id, hid_t lapl_id,
2701 hid_t dxpl_id)
2702 {
2703 unsigned dst_target_flags = H5G_TARGET_NORMAL;
2704 H5T_cset_t char_encoding = H5F_DEFAULT_CSET; /* Character encoding for link */
2705 H5P_genplist_t* lc_plist; /* Link creation property list */
2706 H5P_genplist_t* la_plist; /* Link access property list */
2707 H5L_trav_mv_t udata; /* User data for traversal */
2708 hid_t lapl_copy; /* Copy of lapl for this function */
2709 herr_t ret_value = SUCCEED; /* Return value */
2710
2711 FUNC_ENTER_NOAPI_NOINIT
2712
2713 /* Sanity check */
2714 HDassert(src_loc);
2715 HDassert(dst_loc);
2716 HDassert(src_name && *src_name);
2717 HDassert(dst_name && *dst_name);
2718
2719 /* Check for flags present in creation property list */
2720 if(lcpl_id != H5P_DEFAULT) {
2721 unsigned crt_intmd_group;
2722
2723 if(NULL == (lc_plist = (H5P_genplist_t *)H5I_object(lcpl_id)))
2724 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
2725
2726 /* Get intermediate group creation property */
2727 if(H5P_get(lc_plist, H5L_CRT_INTERMEDIATE_GROUP_NAME, &crt_intmd_group) < 0)
2728 HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for creating missing groups")
2729
2730 /* Set target flags for source and destination */
2731 if(crt_intmd_group > 0)
2732 dst_target_flags |= H5G_CRT_INTMD_GROUP;
2733
2734 /* Get character encoding property */
2735 if(H5P_get(lc_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &char_encoding) < 0)
2736 HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for character encoding")
2737 } /* end if */
2738
2739 /* Copy the link access property list because traversing UD links will
2740 * decrease the NLINKS property. HDF5 should have NLINKS traversals to
2741 * get to the source and NLINKS more to get to the destination. */
2742 if(lapl_id == H5P_DEFAULT)
2743 lapl_copy = lapl_id;
2744 else {
2745 if(NULL == (la_plist = (H5P_genplist_t *)H5I_object(lapl_id)))
2746 HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a valid access PL")
2747 if((lapl_copy = H5P_copy_plist(la_plist, FALSE)) < 0)
2748 HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy access properties")
2749 } /* end else */
2750
2751 /* Set up user data */
2752 udata.dst_loc = dst_loc;
2753 udata.dst_name= dst_name;
2754 udata.dst_target_flags = dst_target_flags;
2755 udata.cset = char_encoding;
2756 udata.copy = copy_flag;
2757 udata.lapl_id = lapl_copy;
2758 udata.dxpl_id = dxpl_id;
2759
2760 /* Do the move */
2761 if(H5G_traverse(src_loc, src_name, H5G_TARGET_MOUNT | H5G_TARGET_SLINK | H5G_TARGET_UDLINK,
2762 H5L_move_cb, &udata, lapl_id, dxpl_id) < 0)
2763 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to find link")
2764
2765 done:
2766 FUNC_LEAVE_NOAPI(ret_value)
2767 } /* end H5L_move() */
2768
2769
2770 /*-------------------------------------------------------------------------
2771 * Function: H5L__exists_final_cb
2772 *
2773 * Purpose: Callback for checking whether a link exists, as the final
2774 * component of a path
2775 *
2776 * Return: Non-negative on success/Negative on failure
2777 *
2778 * Programmer: Quincey Koziol
2779 * Friday, March 16 2007
2780 *
2781 *-------------------------------------------------------------------------
2782 */
2783 static herr_t
H5L__exists_final_cb(H5G_loc_t H5_ATTR_UNUSED * grp_loc,const char H5_ATTR_UNUSED * name,const H5O_link_t * lnk,H5G_loc_t H5_ATTR_UNUSED * obj_loc,void * _udata,H5G_own_loc_t * own_loc)2784 H5L__exists_final_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc/*in*/, const char H5_ATTR_UNUSED *name,
2785 const H5O_link_t *lnk, H5G_loc_t H5_ATTR_UNUSED *obj_loc, void *_udata/*in,out*/,
2786 H5G_own_loc_t *own_loc/*out*/)
2787 {
2788 H5L_trav_le_t *udata = (H5L_trav_le_t *)_udata; /* User data passed in */
2789
2790 FUNC_ENTER_STATIC_NOERR
2791
2792 /* Check if the name in this group resolved to a valid link */
2793 udata->exists = (hbool_t)(lnk != NULL);
2794
2795 /* Indicate that this callback didn't take ownership of the group *
2796 * location for the object */
2797 *own_loc = H5G_OWN_NONE;
2798
2799 FUNC_LEAVE_NOAPI(SUCCEED)
2800 } /* end H5L__exists_final_cb() */
2801
2802
2803 /*-------------------------------------------------------------------------
2804 * Function: H5L__exists_inter_cb
2805 *
2806 * Purpose: Callback for checking whether a link exists, as an intermediate
2807 * component of a path
2808 *
2809 * Return: Non-negative on success/Negative on failure
2810 *
2811 * Programmer: Quincey Koziol
2812 * Thursday, December 31 2015
2813 *
2814 *-------------------------------------------------------------------------
2815 */
2816 static herr_t
H5L__exists_inter_cb(H5G_loc_t H5_ATTR_UNUSED * grp_loc,const char H5_ATTR_UNUSED * name,const H5O_link_t * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)2817 H5L__exists_inter_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc/*in*/, const char H5_ATTR_UNUSED *name,
2818 const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
2819 H5G_own_loc_t *own_loc/*out*/)
2820 {
2821 H5L_trav_le_t *udata = (H5L_trav_le_t *)_udata; /* User data passed in */
2822 herr_t ret_value = SUCCEED; /* Return value */
2823
2824 FUNC_ENTER_STATIC
2825
2826 /* Check if the name in this group resolved to a valid link */
2827 if(lnk != NULL) {
2828 /* Check for more components to the path */
2829 if(udata->sep) {
2830 H5G_traverse_t cb_func; /* Callback function for tranversal */
2831 char *next; /* Pointer to next component name */
2832
2833 /* Look for another separator */
2834 next = udata->sep;
2835 if(NULL == (udata->sep = HDstrchr(udata->sep, '/')))
2836 cb_func = H5L__exists_final_cb;
2837 else {
2838 /* Chew through adjacent separators, if present */
2839 do {
2840 *udata->sep = '\0';
2841 udata->sep++;
2842 } while('/' == *udata->sep);
2843 cb_func = H5L__exists_inter_cb;
2844 } /* end else */
2845 if(H5G_traverse(obj_loc, next, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, cb_func, udata, udata->lapl_id, udata->dxpl_id) < 0)
2846 HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't determine if link exists")
2847 } /* end if */
2848 else
2849 udata->exists = TRUE;
2850 } /* end if */
2851 else
2852 udata->exists = FALSE;
2853
2854 /* Indicate that this callback didn't take ownership of the group *
2855 * location for the object */
2856 *own_loc = H5G_OWN_NONE;
2857
2858 done:
2859 FUNC_LEAVE_NOAPI(ret_value)
2860 } /* end H5L__exists_inter_cb() */
2861
2862
2863 /*-------------------------------------------------------------------------
2864 * Function: H5L_exists_tolerant
2865 *
2866 * Purpose: Returns whether a link exists in a group
2867 *
2868 * Note: Same as H5L_exists, except that missing links are reported
2869 * as 'FALSE' instead of causing failures
2870 *
2871 * Return: Non-negative (TRUE/FALSE) on success/Negative on failure
2872 *
2873 * Programmer: Quincey Koziol
2874 * Thursday, December 31 2015
2875 *
2876 *-------------------------------------------------------------------------
2877 */
2878 htri_t
H5L_exists_tolerant(const H5G_loc_t * loc,const char * name,hid_t lapl_id,hid_t dxpl_id)2879 H5L_exists_tolerant(const H5G_loc_t *loc, const char *name, hid_t lapl_id, hid_t dxpl_id)
2880 {
2881 H5L_trav_le_t udata; /* User data for traversal */
2882 H5G_traverse_t cb_func; /* Callback function for tranversal */
2883 char *name_copy = NULL; /* Duplicate of name */
2884 char *name_trav; /* Name to traverse */
2885 htri_t ret_value = FAIL; /* Return value */
2886
2887 FUNC_ENTER_NOAPI(FAIL)
2888
2889 /* Sanity checks */
2890 HDassert(loc);
2891 HDassert(name);
2892
2893 /* Copy the name and skip leading '/'s */
2894 name_trav = name_copy = H5MM_strdup(name);
2895 while('/' == *name_trav)
2896 name_trav++;
2897
2898 /* A path of "/" will always exist in a file */
2899 if('\0' == *name_trav)
2900 HGOTO_DONE(TRUE)
2901
2902 /* Set up user data & correct callback */
2903 udata.lapl_id = lapl_id;
2904 udata.dxpl_id = dxpl_id;
2905 udata.exists = FALSE;
2906 if(NULL == (udata.sep = HDstrchr(name_trav, '/')))
2907 cb_func = H5L__exists_final_cb;
2908 else {
2909 /* Chew through adjacent separators, if present */
2910 do {
2911 *udata.sep = '\0';
2912 udata.sep++;
2913 } while('/' == *udata.sep);
2914 cb_func = H5L__exists_inter_cb;
2915 } /* end else */
2916
2917 /* Traverse the group hierarchy to locate the link to check */
2918 if(H5G_traverse(loc, name_trav, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, cb_func, &udata, lapl_id, dxpl_id) < 0)
2919 HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't determine if link exists")
2920
2921 /* Set return value */
2922 ret_value = (htri_t)udata.exists;
2923
2924 done:
2925 /* Release duplicated string */
2926 H5MM_xfree(name_copy);
2927
2928 FUNC_LEAVE_NOAPI(ret_value)
2929 } /* H5L_exists_tolerant() */
2930
2931
2932 /*-------------------------------------------------------------------------
2933 * Function: H5L__exists
2934 *
2935 * Purpose: Returns whether a link exists in a group
2936 *
2937 * Note: Same as H5L_exists_tolerant, except that missing links are reported
2938 * as failures
2939 *
2940 * Return: Non-negative (TRUE/FALSE) on success/Negative on failure
2941 *
2942 * Programmer: Quincey Koziol
2943 * Friday, March 16 2007
2944 *
2945 *-------------------------------------------------------------------------
2946 */
2947 static htri_t
H5L__exists(const H5G_loc_t * loc,const char * name,hid_t lapl_id,hid_t dxpl_id)2948 H5L__exists(const H5G_loc_t *loc, const char *name, hid_t lapl_id, hid_t dxpl_id)
2949 {
2950 H5L_trav_le_t udata; /* User data for traversal */
2951 htri_t ret_value = FAIL; /* Return value */
2952
2953 FUNC_ENTER_STATIC
2954
2955 /* A path of "/" will always exist in a file */
2956 if(0 == HDstrcmp(name, "/"))
2957 HGOTO_DONE(TRUE)
2958
2959 /* Traverse the group hierarchy to locate the object to get info about */
2960 udata.exists = FALSE;
2961 if(H5G_traverse(loc, name, H5G_TARGET_SLINK | H5G_TARGET_UDLINK, H5L__exists_final_cb, &udata, lapl_id, dxpl_id) < 0)
2962 HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "path doesn't exist")
2963
2964 /* Set return value */
2965 ret_value = (htri_t)udata.exists;
2966
2967 done:
2968 FUNC_LEAVE_NOAPI(ret_value)
2969 } /* H5L__exists() */
2970
2971
2972 /*-------------------------------------------------------------------------
2973 * Function: H5L_get_info_cb
2974 *
2975 * Purpose: Callback for retrieving a link's metadata
2976 *
2977 * Return: Non-negative on success/Negative on failure
2978 *
2979 * Programmer: James Laird
2980 * Monday, April 17 2006
2981 *
2982 *-------------------------------------------------------------------------
2983 */
2984 static herr_t
H5L_get_info_cb(H5G_loc_t H5_ATTR_UNUSED * grp_loc,const char H5_ATTR_UNUSED * name,const H5O_link_t * lnk,H5G_loc_t H5_ATTR_UNUSED * obj_loc,void * _udata,H5G_own_loc_t * own_loc)2985 H5L_get_info_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc/*in*/, const char H5_ATTR_UNUSED *name,
2986 const H5O_link_t *lnk, H5G_loc_t H5_ATTR_UNUSED *obj_loc, void *_udata/*in,out*/,
2987 H5G_own_loc_t *own_loc/*out*/)
2988 {
2989 H5L_trav_gi_t *udata = (H5L_trav_gi_t *)_udata; /* User data passed in */
2990 herr_t ret_value = SUCCEED; /* Return value */
2991
2992 FUNC_ENTER_NOAPI_NOINIT
2993
2994 /* Check if the name in this group resolved to a valid link */
2995 if(lnk == NULL)
2996 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
2997
2998 /* Get information from the link */
2999 if(H5G_link_to_info(lnk, udata->linfo) < 0)
3000 HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link info")
3001
3002 done:
3003 /* Indicate that this callback didn't take ownership of the group *
3004 * location for the object */
3005 *own_loc = H5G_OWN_NONE;
3006
3007 FUNC_LEAVE_NOAPI(ret_value)
3008 } /* end H5L_get_info_cb() */
3009
3010
3011 /*-------------------------------------------------------------------------
3012 * Function: H5L_get_info
3013 *
3014 * Purpose: Returns metadata about a link.
3015 *
3016 * Return: Non-negative on success/Negative on failure
3017 *
3018 * Programmer: James Laird
3019 * Monday, April 17 2006
3020 *
3021 *-------------------------------------------------------------------------
3022 */
3023 herr_t
H5L_get_info(const H5G_loc_t * loc,const char * name,H5L_info_t * linfo,hid_t lapl_id,hid_t dxpl_id)3024 H5L_get_info(const H5G_loc_t *loc, const char *name,
3025 H5L_info_t *linfo/*out*/, hid_t lapl_id, hid_t dxpl_id)
3026 {
3027 H5L_trav_gi_t udata; /* User data for callback */
3028 herr_t ret_value = SUCCEED; /* Return value */
3029
3030 FUNC_ENTER_NOAPI(FAIL)
3031
3032 udata.linfo = linfo;
3033 udata.dxpl_id = dxpl_id;
3034
3035 /* Traverse the group hierarchy to locate the object to get info about */
3036 if(H5G_traverse(loc, name, H5G_TARGET_SLINK|H5G_TARGET_UDLINK, H5L_get_info_cb, &udata, lapl_id, dxpl_id) < 0)
3037 HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist")
3038
3039 done:
3040 FUNC_LEAVE_NOAPI(ret_value)
3041 } /* H5L_get_info() */
3042
3043
3044 /*-------------------------------------------------------------------------
3045 * Function: H5L_get_info_by_idx_cb
3046 *
3047 * Purpose: Callback for retrieving a link's metadata according to an
3048 * index's order.
3049 *
3050 * Return: Non-negative on success/Negative on failure
3051 *
3052 * Programmer: Quincey Koziol
3053 * Monday, November 6 2006
3054 *
3055 *-------------------------------------------------------------------------
3056 */
3057 static herr_t
H5L_get_info_by_idx_cb(H5G_loc_t H5_ATTR_UNUSED * grp_loc,const char H5_ATTR_UNUSED * name,const H5O_link_t H5_ATTR_UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)3058 H5L_get_info_by_idx_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc/*in*/, const char H5_ATTR_UNUSED *name,
3059 const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
3060 H5G_own_loc_t *own_loc/*out*/)
3061 {
3062 H5L_trav_gibi_t *udata = (H5L_trav_gibi_t *)_udata; /* User data passed in */
3063 H5O_link_t fnd_lnk; /* Link within group */
3064 hbool_t lnk_copied = FALSE; /* Whether the link was copied */
3065 herr_t ret_value = SUCCEED; /* Return value */
3066
3067 FUNC_ENTER_NOAPI_NOINIT
3068
3069 /* Check if the name of the group resolved to a valid object */
3070 if(obj_loc == NULL)
3071 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist")
3072
3073 /* Query link */
3074 if(H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order,
3075 udata->n, &fnd_lnk, udata->dxpl_id) < 0)
3076 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found")
3077 lnk_copied = TRUE;
3078
3079 /* Get information from the link */
3080 if(H5G_link_to_info(&fnd_lnk, udata->linfo) < 0)
3081 HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link info")
3082
3083 done:
3084 /* Reset the link information, if we have a copy */
3085 if(lnk_copied)
3086 H5O_msg_reset(H5O_LINK_ID, &fnd_lnk);
3087
3088 /* Indicate that this callback didn't take ownership of the group *
3089 * location for the object */
3090 *own_loc = H5G_OWN_NONE;
3091
3092 FUNC_LEAVE_NOAPI(ret_value)
3093 } /* end H5L_get_info_by_idx_cb() */
3094
3095
3096 /*-------------------------------------------------------------------------
3097 * Function: H5L_get_default_lcpl
3098 *
3099 * Purpose: Accessor for the default Link Creation Property List
3100 *
3101 * Return: Success: ID of the deafult lcpl
3102 *
3103 * Failure: Negative
3104 *
3105 * Programmer: James Laird
3106 * Tuesday, July 4, 2006
3107 *
3108 *-------------------------------------------------------------------------
3109 */
3110 hid_t
H5L_get_default_lcpl(void)3111 H5L_get_default_lcpl(void)
3112 {
3113 hid_t ret_value = H5I_INVALID_HID; /* Return value */
3114
3115 FUNC_ENTER_NOAPI(FAIL)
3116
3117 ret_value = H5P_LINK_CREATE_DEFAULT;
3118
3119 done:
3120 FUNC_LEAVE_NOAPI(ret_value)
3121 } /* H5L_get_default_lcpl */
3122
3123
3124 /*-------------------------------------------------------------------------
3125 * Function: H5L_get_name_by_idx_cb
3126 *
3127 * Purpose: Callback for retrieving a link's name according to an
3128 * index's order.
3129 *
3130 * Return: Non-negative on success/Negative on failure
3131 *
3132 * Programmer: Quincey Koziol
3133 * Saturday, November 11 2006
3134 *
3135 *-------------------------------------------------------------------------
3136 */
3137 static herr_t
H5L_get_name_by_idx_cb(H5G_loc_t H5_ATTR_UNUSED * grp_loc,const char H5_ATTR_UNUSED * name,const H5O_link_t H5_ATTR_UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)3138 H5L_get_name_by_idx_cb(H5G_loc_t H5_ATTR_UNUSED *grp_loc/*in*/, const char H5_ATTR_UNUSED *name,
3139 const H5O_link_t H5_ATTR_UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
3140 H5G_own_loc_t *own_loc/*out*/)
3141 {
3142 H5L_trav_gnbi_t *udata = (H5L_trav_gnbi_t *)_udata; /* User data passed in */
3143 herr_t ret_value = SUCCEED; /* Return value */
3144
3145 FUNC_ENTER_NOAPI_NOINIT
3146
3147 /* Check if the name of the group resolved to a valid object */
3148 if(obj_loc == NULL)
3149 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist")
3150
3151 /* Query link */
3152 if((udata->name_len = H5G_obj_get_name_by_idx(obj_loc->oloc, udata->idx_type, udata->order,
3153 udata->n, udata->name, udata->size, udata->dxpl_id)) < 0)
3154 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found")
3155
3156 done:
3157 /* Indicate that this callback didn't take ownership of the group *
3158 * location for the object */
3159 *own_loc = H5G_OWN_NONE;
3160
3161 FUNC_LEAVE_NOAPI(ret_value)
3162 } /* end H5L_get_name_by_idx_cb() */
3163
3164
3165 /*-------------------------------------------------------------------------
3166 * Function: H5L_link_copy_file
3167 *
3168 * Purpose: Copy a link and the object it points to from one file to
3169 * another.
3170 *
3171 * Return: Non-negative on success/Negative on failure
3172 *
3173 * Programmer: Quincey Koziol
3174 * koziol@hdfgroup.org
3175 * Sep 29 2006
3176 *
3177 *-------------------------------------------------------------------------
3178 */
3179 herr_t
H5L_link_copy_file(H5F_t * dst_file,hid_t dxpl_id,const H5O_link_t * _src_lnk,const H5O_loc_t * src_oloc,H5O_link_t * dst_lnk,H5O_copy_t * cpy_info)3180 H5L_link_copy_file(H5F_t *dst_file, hid_t dxpl_id, const H5O_link_t *_src_lnk,
3181 const H5O_loc_t *src_oloc, H5O_link_t *dst_lnk, H5O_copy_t *cpy_info)
3182 {
3183 H5O_link_t tmp_src_lnk; /* Temporary copy of src link, when needed */
3184 const H5O_link_t *src_lnk = _src_lnk; /* Source link */
3185 hbool_t dst_lnk_init = FALSE; /* Whether the destination link is initialized */
3186 hbool_t expanded_link_open = FALSE; /* Whether the target location has been opened */
3187 H5G_loc_t tmp_src_loc; /* Group location holding target object */
3188 H5G_name_t tmp_src_path; /* Path for target object */
3189 H5O_loc_t tmp_src_oloc; /* Object location for target object */
3190 herr_t ret_value = SUCCEED; /* Return value */
3191
3192 FUNC_ENTER_NOAPI(FAIL)
3193
3194 /* check arguments */
3195 HDassert(dst_file);
3196 HDassert(src_lnk);
3197 HDassert(dst_lnk);
3198 HDassert(cpy_info);
3199
3200 /* Expand soft or external link, if requested */
3201 if((H5L_TYPE_SOFT == src_lnk->type && cpy_info->expand_soft_link)
3202 || (H5L_TYPE_EXTERNAL == src_lnk->type
3203 && cpy_info->expand_ext_link)) {
3204 H5G_loc_t lnk_grp_loc; /* Group location holding link */
3205 H5G_name_t lnk_grp_path; /* Path for link */
3206 htri_t tar_exists; /* Whether the target object exists */
3207
3208 /* Set up group location for link */
3209 H5G_name_reset(&lnk_grp_path);
3210 lnk_grp_loc.path = &lnk_grp_path;
3211 lnk_grp_loc.oloc = (H5O_loc_t *)src_oloc; /* Casting away const OK -QAK */
3212
3213 /* Check if the target object exists */
3214 if((tar_exists = H5G_loc_exists(&lnk_grp_loc, src_lnk->name, H5P_DEFAULT,
3215 dxpl_id)) < 0)
3216 HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to check if target object exists")
3217
3218 if(tar_exists) {
3219 /* Make a temporary copy of the link, so that it will not change the
3220 * info in the cache when we change it to a hard link */
3221 if(NULL == H5O_msg_copy(H5O_LINK_ID, src_lnk, &tmp_src_lnk))
3222 HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy message")
3223
3224 /* Set up group location for target object. Let H5G_traverse expand
3225 * the link. */
3226 tmp_src_loc.path = &tmp_src_path;
3227 tmp_src_loc.oloc = &tmp_src_oloc;
3228 if(H5G_loc_reset(&tmp_src_loc) < 0)
3229 HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to reset location")
3230
3231 /* Find the target object */
3232 if(H5G_loc_find(&lnk_grp_loc, src_lnk->name, &tmp_src_loc,
3233 H5P_DEFAULT, dxpl_id) < 0)
3234 HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to find target object")
3235 expanded_link_open = TRUE;
3236
3237 /* Convert symbolic link to hard link */
3238 if(tmp_src_lnk.type == H5L_TYPE_SOFT)
3239 tmp_src_lnk.u.soft.name =
3240 (char *)H5MM_xfree(tmp_src_lnk.u.soft.name);
3241 else if(tmp_src_lnk.u.ud.size > 0)
3242 tmp_src_lnk.u.ud.udata = H5MM_xfree(tmp_src_lnk.u.ud.udata);
3243 tmp_src_lnk.type = H5L_TYPE_HARD;
3244 tmp_src_lnk.u.hard.addr = tmp_src_oloc.addr;
3245 src_lnk = &tmp_src_lnk;
3246 } /* end if */
3247 } /* end if */
3248
3249 /* Copy src link information to dst link information */
3250 if(NULL == H5O_msg_copy(H5O_LINK_ID, src_lnk, dst_lnk))
3251 HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy message")
3252 dst_lnk_init = TRUE;
3253
3254 /* Check if object in source group is a hard link & copy it */
3255 if(H5L_TYPE_HARD == src_lnk->type) {
3256 H5O_loc_t new_dst_oloc; /* Copied object location in destination */
3257
3258 /* Set up copied object location to fill in */
3259 H5O_loc_reset(&new_dst_oloc);
3260 new_dst_oloc.file = dst_file;
3261
3262 if(!expanded_link_open) {
3263 /* Build temporary object location for source */
3264 H5O_loc_reset(&tmp_src_oloc);
3265 tmp_src_oloc.file = src_oloc->file;
3266 tmp_src_oloc.addr = src_lnk->u.hard.addr;
3267 } /* end if */
3268 HDassert(H5F_addr_defined(tmp_src_oloc.addr));
3269
3270 /* Copy the shared object from source to destination */
3271 /* Don't care about obj_type or udata because those are only important
3272 * for old style groups */
3273 if(H5O_copy_header_map(&tmp_src_oloc, &new_dst_oloc, dxpl_id, cpy_info,
3274 TRUE, NULL, NULL) < 0)
3275 HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
3276
3277 /* Copy new destination object's information for eventual insertion */
3278 dst_lnk->u.hard.addr = new_dst_oloc.addr;
3279 } /* end if */
3280
3281 done:
3282 /* Check if we used a temporary src link */
3283 if(src_lnk != _src_lnk) {
3284 HDassert(src_lnk == &tmp_src_lnk);
3285 H5O_msg_reset(H5O_LINK_ID, &tmp_src_lnk);
3286 } /* end if */
3287 if(ret_value < 0)
3288 if(dst_lnk_init)
3289 H5O_msg_reset(H5O_LINK_ID, dst_lnk);
3290 /* Check if we need to free the temp source oloc */
3291 if(expanded_link_open)
3292 if(H5G_loc_free(&tmp_src_loc) < 0)
3293 HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object")
3294
3295 FUNC_LEAVE_NOAPI(ret_value)
3296 } /* end H5L_link_copy_file() */
3297
3298