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