summaryrefslogtreecommitdiffstats
path: root/src/H5L.c
diff options
context:
space:
mode:
authorJames Laird <jlaird@hdfgroup.org>2006-07-05 19:01:50 (GMT)
committerJames Laird <jlaird@hdfgroup.org>2006-07-05 19:01:50 (GMT)
commit801ca2f9cb803b368b36a6c280684c1f6624f169 (patch)
treeed2543e9bc1f2beb9857f442fc8b52b3c371299f /src/H5L.c
parentd582c7bc8ac8679911e4787f5f92cc37b1c9989c (diff)
downloadhdf5-801ca2f9cb803b368b36a6c280684c1f6624f169.zip
hdf5-801ca2f9cb803b368b36a6c280684c1f6624f169.tar.gz
hdf5-801ca2f9cb803b368b36a6c280684c1f6624f169.tar.bz2
[svn-r12452] Purpose:
Feature Description: Revised Link APIs. Solution: New link APIs use H5L* H5*create_expand do not create links to the objects created; this must be done manually with H5Llink. Added APIs to link an object given its ID (H5Llink), to copy links (H5Lcopy), and changed creation APIs (H5Lcreate_hard and H5Lcreate_soft) and query API (H5Lget_linkinfo instead of H5Gget_objinfo). All old APIs are still supported in H5Gdeprec.c . Platforms tested: sol, mir, copper Misc. update: Forgot to update MANIFEST and release docs. Will do after checkin.
Diffstat (limited to 'src/H5L.c')
-rw-r--r--src/H5L.c1547
1 files changed, 1547 insertions, 0 deletions
diff --git a/src/H5L.c b/src/H5L.c
new file mode 100644
index 0000000..fe52dc9
--- /dev/null
+++ b/src/H5L.c
@@ -0,0 +1,1547 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5G_PACKAGE /*suppress error about including H5Gpkg */
+#define H5L_PACKAGE /*suppress error about including H5Gpkg */
+
+/* Interface initialization */
+#define H5_INTERFACE_INIT_FUNC H5L_init_interface
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Lpkg.h" /* Links */
+#include "H5Fpkg.h" /* File access */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Oprivate.h" /* File objects */
+#include "H5Dprivate.h" /* Datasets */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5Gpkg.h" /* Groups */
+
+/* Local typedefs */
+#define H5L_MOVE_OP 1
+#define H5L_RENAME_OP 2
+
+/* User data for path traversal routine for getting link metadata */
+typedef struct {
+ H5L_linkinfo_t *linfo; /* Buffer to return to user */
+ hid_t dxpl_id; /* dxpl to use in callback */
+} H5L_trav_ud1_t;
+
+/* User data for path traversal callback to creating a link */
+typedef struct {
+ H5F_t *file; /* Pointer to the file */
+ hid_t dxpl_id; /* Dataset transfer property list */
+ H5G_name_t *path; /* Path to object being linked */
+ H5O_link_t *lnk; /* Pointer to link information to insert */
+} H5L_trav_ud3_t;
+
+/* User data for path traversal routine for moving and renaming a link */
+typedef struct {
+ const char *dst_name; /* Destination name for moving object */
+ H5T_cset_t cset; /* Char set for new name */
+ H5G_loc_t *dst_loc; /* Destination location for moving object */
+ hbool_t copy; /* TRUE if this is a copy operation */
+ hid_t dxpl_id; /* dxpl to use in callback */
+} H5L_trav_ud4_t;
+
+/* User data for path traversal routine for getting soft link value */
+typedef struct {
+ size_t size; /* Size of user buffer */
+ char *buf; /* User buffer */
+} H5L_trav_ud5_t;
+
+/* User data for path traversal routine for removing link (i.e. unlink) */
+typedef struct {
+ hid_t dxpl_id; /* Dataset transfer property list */
+} H5L_trav_ud6_t;
+
+/* User data for path traversal routine for retrieving link creation property list */
+typedef struct {
+ H5P_genplist_t *lcpl; /* Copy of default property list to be set */
+} H5L_trav_ud8_t;
+
+/* User data for path traversal routine for moving and renaming an object */
+typedef struct {
+ H5F_t *file; /* Pointer to the file */
+ H5O_link_t *lnk; /* Pointer to link information to insert */
+ hid_t dxpl_id; /* Dataset transfer property list */
+} H5L_trav_ud10_t;
+
+/* Package variables */
+
+/* Local variables */
+
+/* Private prototypes */
+static herr_t H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
+ const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/);
+static herr_t H5L_create_real(H5G_loc_t *link_loc, const char *link_name,
+ H5G_name_t *obj_path, H5F_t *obj_file, H5O_link_t *lnk, hid_t dxpl_id,
+ hid_t lcpl_id);
+static herr_t H5L_create_hard(H5G_loc_t *cur_loc, const char *cur_name,
+ H5G_loc_t *link_loc, const char *link_name, hid_t dxpl_id, hid_t lcpl_id);
+static herr_t H5L_create_soft(const char *target_path, H5G_loc_t *loc,
+ const char *name, hid_t dxpl_id, hid_t lcpl_id);
+static herr_t H5L_linkval_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
+ const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/);
+static herr_t H5L_linkval(H5G_loc_t *loc, const char *name, size_t size,
+ char *buf/*out*/, hid_t dxpl_id);
+static herr_t H5L_unlink_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
+ const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/);
+static herr_t H5L_unlink(H5G_loc_t *loc, const char *name, hid_t dxpl_id);
+static 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 dxpl_id);
+static herr_t H5L_move_rename_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
+ const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/);
+static herr_t H5L_move_rename_dest_cb(H5G_loc_t *grp_loc/*in*/,
+ const char *name, const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/);
+static herr_t H5L_get_linkinfo(H5G_loc_t *loc, const char *name,
+ H5L_linkinfo_t *linkbuf/*out*/, hid_t dxpl_id);
+static herr_t H5L_get_linfo_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name,
+ const H5O_link_t *lnk, H5G_loc_t UNUSED *obj_loc, void *_udata/*in,out*/);
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_init_interface
+ *
+ * Purpose: Initialize information specific to H5L interface.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Tuesday, January 24, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_init_interface(void)
+{
+ H5P_genclass_t *crt_pclass;
+ size_t nprops; /* Number of properties */
+ unsigned intmd_group = H5L_CRT_INTERMEDIATE_GROUP_DEF;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_init_interface)
+
+ /* =========Link Creation Property Class Initialization========= */
+ /* Register the default attribute creation properties */
+ assert(H5P_CLS_LINK_CREATE_g!=(-1));
+
+ /* Get the pointer to the link creation class */
+ if (NULL == (crt_pclass = H5I_object(H5P_CLS_LINK_CREATE_g)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class")
+
+ /* Get the number of properties in the class */
+ if(H5P_get_nprops_pclass(crt_pclass,&nprops,FALSE)<0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't query number of properties")
+
+ /* Assume that if there are properties in the class, they are the default ones */
+ if(nprops==0) {
+ /* Register create intermediate groups property */
+ if(H5P_register(crt_pclass,H5L_CRT_INTERMEDIATE_GROUP_NAME,H5L_CRT_INTERMEDIATE_GROUP_SIZE,
+ &intmd_group,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ }
+
+ /* Only register the default property list if it hasn't been created yet */
+ if(H5P_LST_LINK_CREATE_g==(-1)) {
+ /* Register the default link creation property list */
+ if ((H5P_LST_LINK_CREATE_g = H5P_create_id (crt_pclass))<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register default property list")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_term_interface
+ *
+ * Purpose: Terminate any resources allocated in H5L_init_interface.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Tuesday, January 24, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5L_term_interface(void)
+{
+ int n=0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5L_term_interface)
+
+ /* The H5L interface currently has no resources that need to be freed. */
+
+ FUNC_LEAVE_NOAPI(n)
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Lmove
+ *
+ * Purpose: Renames an object within an HDF5 file and moves it to a new
+ * group using H5Lrename and H5Lmove. The original name SRC
+ * is unlinked from the group graph and the inserted with the new
+ * name DST (which can specify a new path for the object) as an atomic
+ * operation. The names are interpreted relative to SRC_LOC_ID and
+ * DST_LOC_ID, which are either file IDs or group ID.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Wednesday, March 29, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ H5G_loc_t src_loc, *src_loc_p;
+ H5G_loc_t dst_loc, *dst_loc_p;
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(H5Lmove, FAIL)
+ H5TRACE5("e","isisi",src_loc_id,src_name,dst_loc_id,dst_name,lcpl_id);
+
+ /* Check arguments */
+ if(src_loc_id != H5L_SAME_LOC && H5G_loc(src_loc_id, &src_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(dst_loc_id != H5L_SAME_LOC && H5G_loc(dst_loc_id, &dst_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(!src_name || !*src_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified")
+ if(!dst_name || !*dst_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination name specified")
+
+ /* Set up src & dst location pointers */
+ src_loc_p = &src_loc;
+ dst_loc_p = &dst_loc;
+ if(src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC")
+ else if(src_loc_id == H5L_SAME_LOC)
+ src_loc_p = dst_loc_p;
+ else if(dst_loc_id == H5L_SAME_LOC)
+ dst_loc_p = src_loc_p;
+
+ if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
+
+ if(H5L_move(src_loc_p, src_name, dst_loc_p, dst_name,
+ FALSE, lcpl_id, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to move link")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Lcopy
+ *
+ * Purpose: Creates an identical copy of a link with the same creation
+ * time and target. The new link can have a different name
+ * and be in a different location than the original.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Wednesday, March 29, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ H5G_loc_t src_loc, *src_loc_p;
+ H5G_loc_t dst_loc, *dst_loc_p;
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(H5Lcopy, FAIL)
+ H5TRACE5("e","isisi",src_loc_id,src_name,dst_loc_id,dst_name,lcpl_id);
+
+ /* Check arguments */
+ if(src_loc_id != H5L_SAME_LOC && H5G_loc(src_loc_id, &src_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(dst_loc_id != H5L_SAME_LOC && H5G_loc(dst_loc_id, &dst_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(!src_name || !*src_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified")
+ if(!dst_name || !*dst_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination name specified")
+
+ /* Set up src & dst location pointers */
+ src_loc_p = &src_loc;
+ dst_loc_p = &dst_loc;
+ if(src_loc_id == H5L_SAME_LOC && dst_loc_id == H5L_SAME_LOC)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not both be H5L_SAME_LOC")
+ else if(src_loc_id == H5L_SAME_LOC)
+ src_loc_p = dst_loc_p;
+ else if(dst_loc_id == H5L_SAME_LOC)
+ dst_loc_p = src_loc_p;
+
+ if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
+
+ if(H5L_move(src_loc_p, src_name, dst_loc_p, dst_name, TRUE, lcpl_id, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to move link")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Llink
+ *
+ * Purpose: Creates a hard link from NEW_NAME to the object specified
+ * by OBJ_ID using properties defined in the Link Creation
+ * Property List LCPL.
+ *
+ * This function should be used to link objects that have just
+ * been created.
+ *
+ * CUR_NAME and NEW_NAME are interpreted relative to
+ * CUR_LOC_ID and NEW_LOC_ID, which is either a file ID or a
+ * group ID.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Tuesday, December 13, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Llink(hid_t new_loc_id, const char *new_name, hid_t obj_id, hid_t lcpl_id)
+{
+ H5G_loc_t new_loc;
+ H5G_loc_t obj_loc;
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(H5Llink, FAIL)
+ H5TRACE4("e","isii",new_loc_id,new_name,obj_id,lcpl_id);
+
+ /* Check arguments */
+ if(new_loc_id == H5L_SAME_LOC)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot use H5L_SAME_LOC when only one location is specified")
+ if(H5G_loc(new_loc_id, &new_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(H5G_loc(obj_id, &obj_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(!new_name || !*new_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
+
+ if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
+
+ if(H5L_link(&new_loc, new_name, &obj_loc, H5AC_dxpl_id, lcpl_id ) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "unable to create link")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Llink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Lcreate_soft
+ *
+ * Purpose: Creates a soft link from NEW_NAME to TARGET_PATH.
+ *
+ * TARGET_PATH can be anything and is interpreted at lookup
+ * time relative to the group which contains the final component
+ * of NEW_NAME. For instance, if TARGET_PATH is `./foo' and
+ * NEW_NAME is `./x/y/bar' and a request is made for `./x/y/bar'
+ * then the actual object looked up is `./x/y/./foo'.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 6, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Lcreate_soft(const char *target_path,
+ hid_t loc_id, const char *name, hid_t lcpl_id)
+{
+ H5G_loc_t new_loc, *new_loc_p;
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(H5Lcreate_soft, FAIL)
+ H5TRACE4("e","sisi",target_path,loc_id,name,lcpl_id);
+
+ /* Check arguments */
+ if(H5G_loc(loc_id, &new_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(!target_path || !*target_path)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no target specified")
+ if(!name || !*name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new name specified")
+
+ if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
+
+ new_loc_p = &new_loc;
+
+ if(H5L_create_soft(target_path, new_loc_p, name, H5AC_dxpl_id, lcpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "unable to create link")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Lcreate_soft() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Lcreate_hard
+ *
+ * Purpose: Creates a hard link from NEW_NAME to CUR_NAME.
+ *
+ * CUR_NAME must name an existing object. CUR_NAME and
+ * NEW_NAME are interpreted relative to CUR_LOC_ID and
+ * NEW_LOC_ID, which are either file IDs or group IDs.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 6, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ H5G_loc_t cur_loc, *cur_loc_p;
+ H5G_loc_t new_loc, *new_loc_p;
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(H5Lcreate_hard, FAIL)
+ H5TRACE5("e","isisi",cur_loc_id,cur_name,new_loc_id,new_name,lcpl_id);
+
+ /* Check arguments */
+ if(cur_loc_id != H5L_SAME_LOC && H5G_loc(cur_loc_id, &cur_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(new_loc_id != H5L_SAME_LOC && H5G_loc(new_loc_id, &new_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(!cur_name || !*cur_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified")
+ if(!new_name || !*new_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new name specified")
+
+ if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
+
+ /* Set up current & new location pointers */
+ cur_loc_p = &cur_loc;
+ new_loc_p = &new_loc;
+ if(cur_loc_id == H5L_SAME_LOC && new_loc_id == H5L_SAME_LOC)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not be both H5L_SAME_LOC")
+ else if(cur_loc_id == H5L_SAME_LOC)
+ cur_loc_p = new_loc_p;
+ else if(new_loc_id == H5L_SAME_LOC)
+ new_loc_p = cur_loc_p;
+ else if(cur_loc_p->oloc->file != new_loc_p->oloc->file)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should be in the same file.")
+
+ if(H5L_create_hard(cur_loc_p, cur_name, new_loc_p, new_name, H5AC_dxpl_id, lcpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "unable to create link")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Lcreate_hard() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Lunlink
+ *
+ * Purpose: Removes the specified NAME from the group graph and
+ * decrements the link count for the object to which NAME
+ * points. If the link count reaches zero then all file-space
+ * associated with the object will be reclaimed (but if the
+ * object is open, then the reclamation of the file space is
+ * delayed until all handles to the object are closed).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 6, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Lunlink(hid_t loc_id, const char *name)
+{
+ H5G_loc_t loc;
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(H5Lunlink, FAIL)
+ H5TRACE2("e","is",loc_id,name);
+
+ /* Check arguments */
+ if(H5G_loc(loc_id, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(!name || !*name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
+
+ /* Unlink */
+ if(H5L_unlink(&loc, name, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to unlink object")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Lunlink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Lget_linkval
+ *
+ * Purpose: Returns the link value of a link whose name is NAME. For
+ * symbolic links, this is the path to which the link points,
+ * including the null terminator. For user-defined links, it
+ * is the link buffer.
+ *
+ * At most SIZE bytes are copied to the BUF result buffer.
+ *
+ * Return: Success: Non-negative with the link value in BUF.
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 13, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Lget_linkval(hid_t loc_id, const char *name, size_t size, char *buf/*out*/)
+{
+ H5G_loc_t loc;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(H5Lget_linkval, FAIL)
+ H5TRACE4("e","iszx",loc_id,name,size,buf);
+
+ /* Check arguments */
+ if(H5G_loc(loc_id, &loc))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(!name || !*name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
+
+ /* Get the link value */
+ if(H5L_linkval(&loc, name, size, buf, H5AC_ind_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to get link value")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Lget_linkval() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Lget_linkinfo
+ *
+ * Purpose: Gets metadata for a link.
+ *
+ * Return: Success: Non-negative with information in LINKBUF
+ *
+ * Failure: Negative
+ *
+ * Programmer: James Laird
+ * Wednesday, June 21, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Lget_linkinfo(hid_t loc_id, const char *name, H5L_linkinfo_t *linkbuf /*out*/)
+{
+ H5G_loc_t loc;
+ herr_t ret_value = SUCCEED;
+ FUNC_ENTER_API(H5Lget_linkinfo, FAIL)
+ H5TRACE3("e","isx",loc_id,name,linkbuf);
+
+ /* Check arguments */
+ if(H5G_loc(loc_id, &loc))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(!name || !*name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
+
+ /* Get the creation time */
+ if(H5L_get_linkinfo(&loc, name, linkbuf, H5AC_ind_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to get link info")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+}
+
+
+
+/*
+ *-------------------------------------------------------------------------
+ *-------------------------------------------------------------------------
+ * 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
+ *-------------------------------------------------------------------------
+ *-------------------------------------------------------------------------
+ */
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_link
+ *
+ * Purpose: Creates a link from OBJ_ID to CUR_NAME. See H5Llink() for
+ * full documentation.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Tuesday, December 13, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5L_link(H5G_loc_t *new_loc, const char *new_name, H5G_loc_t *obj_loc,
+ hid_t dxpl_id, hid_t lcpl_id)
+{
+ char *norm_new_name = NULL; /* Pointer to normalized new name */
+ H5F_t *file = NULL; /* File link will be in */
+ H5O_link_t lnk; /* Link to insert */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_link)
+
+ /* Check args */
+ HDassert(new_loc);
+ HDassert(obj_loc);
+ HDassert(new_name && *new_name);
+
+ /* Check that the object is not being hard linked into a different file */
+ if(NULL == (file = H5G_insertion_file(new_loc, new_name, dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to identify insertion file")
+ if(obj_loc->oloc->file != file)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cannot link an object from another file")
+
+ /* Construct link information for eventual insertion */
+ lnk.type = H5L_LINK_HARD;
+ lnk.u.hard.addr = obj_loc->oloc->addr;
+
+ /* Create the link */
+ if( H5L_create_real(new_loc, new_name, obj_loc->path, obj_loc->oloc->file, &lnk, dxpl_id, lcpl_id) <0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to register new name for object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_link() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_link_cb
+ *
+ * Purpose: Callback for creating a link to an object.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, September 19, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED *lnk,
+ H5G_loc_t *obj_loc, void *_udata/*in,out*/)
+{
+ H5L_trav_ud3_t *udata = (H5L_trav_ud3_t *)_udata; /* User data passed in */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_link_cb)
+
+ /* Check if the name in this group resolved to a valid location */
+ /* (which is not what we want) */
+ if(obj_loc != NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name already exists")
+
+ /* Check for crossing file boundaries with a new hard link */
+ if(udata->lnk->type == H5L_LINK_HARD) {
+ /* Check that both objects are in same file */
+ if(grp_loc->oloc->file->shared != udata->file->shared)
+ HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "interfile hard links are not allowed")
+ } /* end if */
+
+ /* Set the link's name correctly */
+ /* Casting away const OK -QAK */
+ udata->lnk->name = name;
+
+ /* Insert link into group */
+ if(H5G_obj_insert(grp_loc->oloc, name, udata->lnk, (hbool_t)(udata->lnk->type == H5L_LINK_HARD ? TRUE : FALSE), udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create new name/link for object")
+
+ /* Set object's path if it has been passed in and is not set */
+ if(udata->path != NULL && udata->path->user_path_r == NULL)
+ {
+ if(H5G_name_set(grp_loc->path, udata->path, name) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name")
+ }
+
+done:
+ if(ret_value < 0) {
+ /* Release the group location for the object */
+ /* (Group traversal callbacks are responsible for either taking ownership
+ * of the group location for the object, or freeing it. - QAK)
+ */
+ if(obj_loc)
+ H5G_loc_free(obj_loc);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_link_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_create_real
+ *
+ * Purpose: Creates a link at a path location
+ *
+ * lnk should have linkclass-specific information already
+ * set, but this function will take care of setting
+ * creation time and name.
+ *
+ * obj_path can be NULL if the object's path doesn't need to
+ * be set, and obj_file can be NULL if the object is not a
+ * hard link.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, December 5, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_create_real(H5G_loc_t *link_loc, const char *link_name, H5G_name_t *obj_path,
+ H5F_t *obj_file, H5O_link_t *lnk, hid_t dxpl_id, hid_t lcpl_id)
+{
+ char *norm_link_name = NULL; /* Pointer to normalized link name */
+ unsigned target_flags = H5G_TARGET_NORMAL; /* Flags to pass to group traversal function */
+ H5T_cset_t char_encoding = H5F_CRT_DEFAULT_CSET; /* Character encoding for link */
+ H5P_genplist_t* lc_plist; /* Link creation property list */
+ H5L_trav_ud3_t udata; /* User data for callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_create_real)
+
+ /* Check args */
+ HDassert(link_loc);
+ HDassert(link_name && *link_name);
+ HDassert(lnk);
+
+ /* Get normalized link name */
+ if((norm_link_name = H5G_normalize(link_name)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name")
+
+ /* Check for flags present in creation property list */
+ if(lcpl_id != H5P_DEFAULT)
+ {
+ unsigned crt_intmd_group;
+
+ if(NULL == (lc_plist = H5I_object(lcpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* Get intermediate group creation property */
+ if(H5P_get(lc_plist, H5L_CRT_INTERMEDIATE_GROUP_NAME, &crt_intmd_group) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for creating missing groups")
+
+ if (crt_intmd_group > 0)
+ target_flags |= H5G_CRT_INTMD_GROUP;
+
+ /* Get character encoding property */
+ if(H5P_get(lc_plist, H5P_CHAR_ENCODING_NAME, &char_encoding) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for character encoding")
+ } /* end if */
+
+ /* Fill in common data for the link struct */
+ lnk->cset = char_encoding;
+#ifdef H5_HAVE_GETTIMEOFDAY
+ {
+ struct timeval now_tv;
+
+ HDgettimeofday(&now_tv, NULL);
+ lnk->ctime = now_tv.tv_sec;
+ }
+#else /* H5_HAVE_GETTIMEOFDAY */
+ lnk->ctime = HDtime(NULL);
+#endif /* H5_HAVE_GETTIMEOFDAY */
+
+ /* Set up user data
+ * file is used to make sure that hard links don't cross files, and
+ * should be NULL for other link types.
+ * lnk is the link struct passed into this function. At this point all
+ * of its fields should be populated except for name, which is set when
+ * inserting it in the callback.
+ * dxpl_id is the dxpl ID that needs to be used during writes and reads.
+ * path is a pointer to the path of the object being inserted if this is
+ * a hard link; this is used to set the paths to objects when they are
+ * created. For other link types, this is NULL.
+ */
+ udata.file = obj_file;
+ udata.lnk = lnk;
+ udata.dxpl_id = dxpl_id;
+ udata.path = obj_path;
+
+ /* Traverse the destination path & create new link */
+ if(H5G_traverse(link_loc, link_name, target_flags, H5L_link_cb, &udata, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert link")
+
+done:
+ /* Free the normalized path name */
+ if(norm_link_name)
+ H5MM_xfree(norm_link_name);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_create_real() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_create_hard
+ *
+ * Purpose: Creates a hard link from NEW_NAME to CUR_NAME.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 6, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_create_hard(H5G_loc_t *cur_loc, const char *cur_name,
+ H5G_loc_t *link_loc, const char *link_name, hid_t dxpl_id, hid_t lcpl_id)
+{
+ char *norm_cur_name = NULL; /* Pointer to normalized current name */
+ H5F_t *link_file = NULL; /* Pointer to file to link to */
+ H5O_link_t lnk; /* Link to insert */
+ H5O_loc_t obj_oloc; /* Location of object to link to */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_create_hard)
+
+ /* Check args */
+ HDassert(cur_loc);
+ HDassert(link_loc);
+ HDassert(cur_name && *cur_name);
+ HDassert(link_name && *link_name);
+
+ /* Get normalized copy of the current name */
+ if((norm_cur_name = H5G_normalize(cur_name)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name")
+
+ /* Set up link data specific to hard links */
+ lnk.type = H5L_LINK_HARD;
+
+ /* Get object location for object pointed to */
+ if(H5G_obj_find(cur_loc, norm_cur_name, H5G_TARGET_NORMAL, NULL, &obj_oloc, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "source object not found")
+
+ /* Construct link information for eventual insertion */
+ lnk.u.hard.addr = obj_oloc.addr;
+
+ /* Set destination's file information */
+ link_file = obj_oloc.file;
+
+ /* Create actual link to the object. Pass in NULL for the path, since this
+ * function shouldn't change an object's user path. */
+ if(H5L_create_real(link_loc, link_name, NULL, link_file, &lnk, dxpl_id, lcpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to register new name for object")
+
+done:
+ /* Free the normalized path name */
+ if(norm_cur_name)
+ H5MM_xfree(norm_cur_name);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_create_hard() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_create_soft
+ *
+ * Purpose: Creates a soft link from NEW_NAME to CUR_NAME.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 6, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_create_soft( const char *target_path, H5G_loc_t *link_loc,
+ const char *link_name, hid_t dxpl_id, hid_t lcpl_id)
+{
+ char *norm_target = NULL; /* Pointer to normalized current name */
+ H5O_link_t lnk; /* Link to insert */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_create_soft)
+
+ /* Check args */
+ HDassert(link_loc);
+ HDassert(target_path && *target_path);
+ HDassert(link_name && *link_name);
+
+ /* Get normalized copy of the link target */
+ if((norm_target = H5G_normalize(target_path)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name")
+
+ /* Set up link data specific to soft links */
+ lnk.type = H5L_LINK_SOFT;
+ lnk.u.soft.name = norm_target;
+
+ /* Create actual link to the object */
+ if(H5L_create_real(link_loc, link_name, NULL, NULL, &lnk, dxpl_id, lcpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to register new name for object")
+
+done:
+ /* Free the normalized target name */
+ if(norm_target)
+ H5MM_xfree(norm_target);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_create_soft() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_linkval_cb
+ *
+ * Purpose: Callback for retrieving soft link value for an object.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, September 20, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_linkval_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t *lnk,
+ H5G_loc_t UNUSED *obj_loc, void *_udata/*in,out*/)
+{
+ H5L_trav_ud5_t *udata = (H5L_trav_ud5_t *)_udata; /* User data passed in */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_linkval_cb)
+
+ /* Check if the name in this group resolved to a valid link */
+ if(lnk == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
+
+ if(H5L_LINK_SOFT != lnk->type)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object is not a symbolic link")
+
+ /* Copy to output buffer */
+ if(udata->size > 0 && udata->buf) {
+ HDstrncpy(udata->buf, lnk->u.soft.name, udata->size);
+ if(HDstrlen(lnk->u.soft.name) >= udata->size)
+ udata->buf[udata->size - 1] = '\0';
+ } /* end if */
+
+done:
+ /* Release the group location for the object */
+ /* (Group traversal callbacks are responsible for either taking ownership
+ * of the group location for the object, or freeing it. - QAK)
+ */
+ if(obj_loc)
+ H5G_loc_free(obj_loc);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_linkval_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_linkval
+ *
+ * Purpose: Returns the value of a symbolic link.
+ *
+ * Return: Success: Non-negative, with at most SIZE bytes of the
+ * link value copied into the BUF buffer. If the
+ * link value is larger than SIZE characters
+ * counting the null terminator then the BUF
+ * result will not be null terminated.
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 13, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_linkval(H5G_loc_t *loc, const char *name, size_t size, char *buf/*out*/, hid_t dxpl_id)
+{
+ H5L_trav_ud5_t udata; /* User data for callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_linkval)
+
+ /* Set up user data for retrieving information */
+ udata.size = size;
+ udata.buf = buf;
+
+ /* Traverse the group hierarchy to locate the object to get info about */
+ if(H5G_traverse(loc, name, H5G_TARGET_SLINK, H5L_linkval_cb, &udata, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5L_linkval() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_unlink_cb
+ *
+ * Purpose: Callback for unlinking an object. This routine
+ * deletes the link
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, September 19, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_unlink_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED *lnk,
+ H5G_loc_t *obj_loc, void *_udata/*in,out*/)
+{
+ H5L_trav_ud6_t *udata = (H5L_trav_ud6_t *)_udata; /* User data passed in */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_unlink_cb)
+
+ /* Check if the name in this group resolved to a valid link */
+ if(obj_loc == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
+
+ /* Check for removing '.' */
+ if(lnk == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't delete self")
+
+ /* Remove the link from the group */
+ if(H5G_loc_remove(grp_loc, name, obj_loc, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to unlink name from group")
+
+done:
+ /* Release the group location for the object */
+ /* (Group traversal callbacks are responsible for either taking ownership
+ * of the group location for the object, or freeing it. - QAK)
+ */
+ if(obj_loc)
+ H5G_loc_free(obj_loc);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_unlink_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_unlink
+ *
+ * Purpose: Unlink a name from a group.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, September 17, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_unlink(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
+{
+ H5L_trav_ud6_t udata; /* User data for callback */
+ char *norm_name = NULL; /* Pointer to normalized name */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_unlink)
+
+ /* Sanity check */
+ HDassert(loc);
+ HDassert(name && *name);
+
+ /* Get normalized copy of the name */
+ if((norm_name = H5G_normalize(name)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name")
+
+ /* Set up user data for unlink operation */
+ udata.dxpl_id = dxpl_id;
+
+ if(H5G_traverse(loc, norm_name, H5G_TARGET_SLINK|H5G_TARGET_MOUNT, H5L_unlink_cb, &udata, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist")
+
+done:
+ /* Free the normalized path name */
+ if(norm_name)
+ H5MM_xfree(norm_name);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_unlink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_move_rename_dest_cb
+ *
+ * Purpose: Second callback for moving and renaming an object. This routine
+ * inserts a new link into the group returned by the traversal.
+ * It is called by H5L_move_rename_cb.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Monday, April 3, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_move_rename_dest_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk,
+ H5G_loc_t *obj_loc, void *_udata/*in,out*/)
+{
+ H5L_trav_ud10_t *udata = (H5L_trav_ud10_t *)_udata; /* User data passed in */
+ H5RS_str_t *dst_name_r = NULL; /* Ref-counted version of dest name */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_move_rename_dest_cb)
+
+ /* Make sure an object with this name doesn't already exist */
+ if(obj_loc != NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "an object with that name already exists")
+
+ /* Check for crossing file boundaries with a new hard link */
+ if(udata->lnk->type == H5L_LINK_HARD) {
+ /* Check that both objects are in same file */
+ if(grp_loc->oloc->file->shared != udata->file->shared)
+ HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "moving a link across files is not allowed")
+ } /* end if */
+
+ /* Give the object its new name */
+ /* Casting away const okay -JML */
+ udata->lnk->name = H5MM_xfree(udata->lnk->name);
+ udata->lnk->name=name;
+
+ /* Insert the link into the group */
+ if(H5G_obj_insert(grp_loc->oloc, name, udata->lnk, (hbool_t)(udata->lnk->type == H5L_LINK_HARD ? TRUE : FALSE), udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create new name/link for object")
+
+done:
+ /* Release the group location for the object */
+ /* (Group traversal callbacks are responsible for either taking ownership
+ * of the group location for the object, or freeing it. - QAK)
+ */
+ if(obj_loc)
+ H5G_loc_free(obj_loc);
+ if(dst_name_r)
+ H5RS_decr(dst_name_r);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_move_dest_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_move_rename_cb
+ *
+ * Purpose: Callback for moving and renaming an object. This routine
+ * replaces the names of open objects with the moved object
+ * in the path
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Friday, April 3, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_move_rename_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk,
+ H5G_loc_t *obj_loc, void *_udata/*in,out*/)
+{
+ H5L_trav_ud4_t *udata = (H5L_trav_ud4_t *)_udata; /* User data passed in */
+ H5L_trav_ud10_t udata_out; /* User data for H5L_move_dest_cb traversal */
+ H5G_obj_t type; /* Type of object being moved */
+ H5RS_str_t *dst_name_r = NULL; /* Ref-counted version of dest name */
+ char * orig_name = NULL; /* The name of the link in this group */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_move_rename_cb)
+
+ /* Check if the name in this group resolved to a valid link */
+ if(obj_loc == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
+
+ /* Check for operations on '.' */
+ if(lnk == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "the name of a link must be supplied to move or rename")
+
+ /* Get object type */
+ switch(lnk->type) {
+ case H5L_LINK_HARD:
+ if(H5G_UNKNOWN == (type = H5O_obj_type(obj_loc->oloc, udata->dxpl_id)))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get object type to move")
+ break;
+
+ case H5L_LINK_SOFT:
+ type = H5G_LINK;
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unrecognized link type")
+ } /* end switch */
+
+ /* Set up user data for move_dest_cb */
+ if((udata_out.lnk = H5O_link_copy(lnk, NULL, 0)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, FAIL, "unable to copy link to be moved");
+ udata_out.lnk->cset = udata->cset;
+ udata_out.file = grp_loc->oloc->file;
+ udata_out.dxpl_id = udata->dxpl_id;
+
+ /* Remember the link's original name (in case it's changed by H5G_name_replace) */
+ orig_name = H5MM_xstrdup(name);
+
+ /* Insert the link into its new location */
+ if(H5G_traverse(udata->dst_loc, udata->dst_name, H5G_TARGET_NORMAL, H5L_move_rename_dest_cb, &udata_out, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to follow symbolic link")
+
+ /* If this is a move and not a copy operation, change the object's name and remove the old link */
+ if(!udata->copy)
+ {
+ /* Fix names up */
+ dst_name_r = H5RS_wrap(udata->dst_name);
+ HDassert(dst_name_r);
+ if(H5G_name_replace(type, obj_loc, dst_name_r, udata->dst_loc, H5G_NAME_MOVE) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name ")
+
+ /* Remove the old link */
+ if(H5G_obj_remove(grp_loc->oloc, orig_name, &type, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to remove old name")
+ }
+
+done:
+ /* Cleanup */
+ if(orig_name)
+ H5MM_xfree(orig_name);
+
+ /* Release the group location for the object */
+ /* (Group traversal callbacks are responsible for either taking ownership
+ * of the group location for the object, or freeing it. - QAK)
+ */
+ if(obj_loc)
+ H5G_loc_free(obj_loc);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_move_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_move
+ *
+ * Purpose: Atomically move and rename or copy a link.
+ *
+ * Creates a copy of a link in a new destination with a new name.
+ * SRC_LOC and SRC_NAME together define the link's original
+ * location, while DST_LOC and DST_NAME together define its
+ * final location.
+ *
+ * If copy_flag is FALSE, the original link is removed
+ * (effectively moving the link).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Monday, May 1, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static 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 dxpl_id)
+{
+ unsigned target_flags = H5G_TARGET_MOUNT|H5G_TARGET_SLINK; /* Flags to pass to group traversal function */
+ H5T_cset_t char_encoding = H5F_CRT_DEFAULT_CSET; /* Character encoding for link */
+ H5P_genplist_t* lc_plist; /* Link creation property list */
+ H5L_trav_ud4_t udata; /* User data for traversal */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_move)
+
+ /* Sanity check */
+ HDassert(src_loc);
+ HDassert(dst_loc);
+ HDassert(src_name && *src_name);
+ HDassert(dst_name && *dst_name);
+
+ /* Check for flags present in creation property list */
+ if(lcpl_id != H5P_DEFAULT)
+ {
+ unsigned crt_intmd_group;
+
+ if(NULL == (lc_plist = H5I_object(lcpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* Get intermediate group creation property */
+ if(H5P_get(lc_plist, H5L_CRT_INTERMEDIATE_GROUP_NAME, &crt_intmd_group) <
+0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for creating missing groups")
+
+ if (crt_intmd_group > 0)
+ target_flags |= H5G_CRT_INTMD_GROUP;
+
+ /* Get character encoding property */
+ if(H5P_get(lc_plist, H5P_CHAR_ENCODING_NAME, &char_encoding) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for character encoding")
+ } /* end if */
+
+ /* Set up user data */
+ udata.dst_loc = dst_loc;
+ udata.dst_name= dst_name;
+ udata.cset = char_encoding;
+ udata.copy = copy_flag;
+ udata.dxpl_id = dxpl_id;
+
+ /* Do the move */
+ if(H5G_traverse(src_loc, src_name, H5G_TARGET_MOUNT|H5G_TARGET_SLINK, H5L_move_rename_cb, &udata, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to find link")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_move() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_get_lcpl_cb
+ *
+ * Purpose: Callback for getting a link's creation property list. This
+ * routine gets properties from the link and sets them on the
+ * copy of the default property list passed in.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Friday, January 27, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_get_lcpl_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t *lnk,
+ H5G_loc_t UNUSED *obj_loc, void *_udata/*in,out*/)
+{
+ H5L_trav_ud8_t *udata = (H5L_trav_ud8_t *)_udata; /* User data passed in */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_get_lcpl_cb)
+
+ /* Check if the name in this group resolved to a valid link */
+ if(lnk == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
+
+ /* Set appropriate character encoding */
+ if(H5P_set(udata->lcpl, H5P_CHAR_ENCODING_NAME, &(lnk->cset)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set property value for character encoding")
+
+done:
+ /* Release the group location for the object */
+ /* (Group traversal callbacks are responsible for either taking ownership
+ * of the group location for the object, or freeing it. - QAK)
+ */
+ if(obj_loc)
+ H5G_loc_free(obj_loc);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_get_lcpl_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_get_create_plist
+ *
+ * Purpose: Returns a copy of the link's creation property list given
+ * given a link's location and name.
+ *
+ * Return: Success: ID of the property list
+ *
+ * Failure: Negative
+ *
+ * Programmer: James Laird
+ * Friday, January 27, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t H5L_get_create_plist(H5G_loc_t *loc, const char* name)
+{
+ H5P_genplist_t *plist; /* Default property list */
+ H5P_genplist_t *plist_copy; /* Copy of list to be modified */
+ hid_t lcpl_id=-1;
+ H5L_trav_ud8_t udata; /* User data for traversal */
+ char *norm_name = NULL; /* Pointer to normalized name */
+ hid_t ret_value;
+
+ FUNC_ENTER_NOAPI(H5L_get_create_plist, FAIL)
+
+ /* Check arguments */
+ HDassert(loc);
+ HDassert(name && *name);
+
+ /* Get normalized copy of the name */
+ if((norm_name = H5G_normalize(name)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name")
+
+ /* Get copy of default lcpl */
+ if (NULL==(plist=H5I_object(H5P_LST_LINK_CREATE_g)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get default LCPL")
+ if((lcpl_id=H5P_copy_plist(plist)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties")
+ if (NULL==(plist_copy=H5I_object(lcpl_id)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get copy of LCPL")
+
+ /* Set up user data */
+ udata.lcpl = plist_copy;
+
+ if(H5G_traverse(loc, norm_name, H5G_TARGET_SLINK|H5G_TARGET_MOUNT, H5L_get_lcpl_cb, &udata, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist")
+
+ ret_value = lcpl_id;
+
+done:
+ /* Free the normalized path name */
+ if(norm_name)
+ H5MM_xfree(norm_name);
+ /* If we've created a new lcpl, close it */
+ if(ret_value <0 && lcpl_id >= 0)
+ H5P_close(H5I_object(lcpl_id));
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_get_create_plist */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_get_linfo_cb
+ *
+ * Purpose: Callback for retrieving a link's metadata
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Monday, April 17 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_get_linfo_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t *lnk,
+ H5G_loc_t UNUSED *obj_loc, void *_udata/*in,out*/)
+{
+ H5L_trav_ud1_t *udata = (H5L_trav_ud1_t *)_udata; /* User data passed in */
+ H5L_linkinfo_t *linfo = udata->linfo;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_get_linfo_cb)
+
+ /* Check if the name in this group resolved to a valid link */
+ if(lnk == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
+
+ /* Get information from the link */
+ linfo->cset = lnk->cset;
+ linfo->ctime = lnk->ctime;
+ linfo->linkclass = lnk->type;
+
+ switch(lnk->type)
+ {
+ case H5L_LINK_HARD:
+ linfo->u.objno = lnk->u.hard.addr;
+ break;
+
+ case H5L_LINK_SOFT:
+ linfo->u.link_size = HDstrlen(lnk->u.soft.name) + 1; /*count the null terminator*/
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "unknown link type");
+ }
+
+done:
+ /* Release the group location for the object */
+ /* (Group traversal callbacks are responsible for either taking ownership
+ * of the group location for the object, or freeing it. - QAK)
+ */
+ if(obj_loc)
+ H5G_loc_free(obj_loc);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_get_linfo_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L_get_linkinfo
+ *
+ * Purpose: Returns metadata about a link.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: James Laird
+ * Monday, April 17 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5L_get_linkinfo(H5G_loc_t *loc, const char *name, H5L_linkinfo_t *linkbuf/*out*/, hid_t dxpl_id)
+{
+ H5L_trav_ud1_t udata;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_get_linkinfo)
+
+ udata.linfo = linkbuf;
+ udata.dxpl_id = dxpl_id;
+
+ /* Traverse the group hierarchy to locate the object to get info about */
+ if(H5G_traverse(loc, name, H5G_TARGET_SLINK, H5L_get_linfo_cb, &udata, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5L_get_linkinfo() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5L get_default_lcpl
+ *
+ * Purpose: Accessor for the default Link Creation Property List
+ *
+ * Return: Success: ID of the deafult lcpl
+ *
+ * Failure: Negative
+ *
+ * Programmer: James Laird
+ * Tuesday, July 4, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5L_get_default_lcpl()
+{
+ hid_t ret_value = FAIL; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5L_get_default_lcpl, FAIL)
+
+ ret_value = H5P_LINK_CREATE_DEFAULT;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5L_get_default_lcpl */
+