summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5Glink.c48
-rw-r--r--src/H5Gloc.c166
-rw-r--r--src/H5Gpkg.h4
-rw-r--r--src/H5Gprivate.h3
-rw-r--r--src/H5Gtraverse.c171
-rw-r--r--src/H5L.c16
-rw-r--r--src/H5O.c87
-rw-r--r--src/H5Opublic.h27
8 files changed, 418 insertions, 104 deletions
diff --git a/src/H5Glink.c b/src/H5Glink.c
index b0966d7..e984a91 100644
--- a/src/H5Glink.c
+++ b/src/H5Glink.c
@@ -415,6 +415,54 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5G_link_to_loc
+ *
+ * Purpose: Build group location from group and link object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, November 20 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_link_to_loc(const H5G_loc_t *grp_loc, const H5O_link_t *lnk,
+ H5G_loc_t *obj_loc)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_link_to_loc, FAIL)
+
+ /* Sanity check */
+ HDassert(grp_loc);
+ HDassert(lnk);
+ HDassert(obj_loc);
+
+ /*
+ * Build location from the link
+ */
+
+ /* Check for unknown library-internal link */
+ if(lnk->type > H5L_TYPE_BUILTIN_MAX && lnk->type < H5L_TYPE_UD_MIN)
+ HGOTO_ERROR(H5E_SYM, H5E_UNSUPPORTED, FAIL, "unknown link type")
+
+ /* Build object's group hier. location */
+ if(H5G_name_set(grp_loc->path, obj_loc->path, lnk->name) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name")
+
+ /* Set the object location, if it's a hard link set the address also */
+ obj_loc->oloc->file = grp_loc->oloc->file;
+ obj_loc->oloc->holding_file = FALSE;
+ if(lnk->type == H5L_TYPE_HARD)
+ obj_loc->oloc->addr = lnk->u.hard.addr;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_link_to_loc() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_link_copy_file
*
* Purpose: Copy a link and the object it points to from one file to
diff --git a/src/H5Gloc.c b/src/H5Gloc.c
index 3a94a79..ca488cf 100644
--- a/src/H5Gloc.c
+++ b/src/H5Gloc.c
@@ -22,10 +22,17 @@
*
*-------------------------------------------------------------------------
*/
+
+/****************/
+/* Module Setup */
+/****************/
+
#define H5G_PACKAGE /*suppress error about including H5Gpkg */
-/* Packages needed by this file... */
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Aprivate.h" /* Attributes */
#include "H5Dprivate.h" /* Datasets */
@@ -33,21 +40,61 @@
#include "H5Gpkg.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
-/* Private typedefs */
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
/* User data for looking up an object in a group */
typedef struct {
+ /* upward */
H5G_loc_t *loc; /* Group location to set */
-} H5G_loc_ud1_t;
+} H5G_loc_fnd_t;
-/* Private macros */
+/* User data for looking up an object in a group by index */
+typedef struct {
+ /* downward */
+ hid_t dxpl_id; /* DXPL to use for operation */
+ H5L_index_t idx_type; /* Index to use */
+ H5_iter_order_t order; /* Iteration order within index */
+ hsize_t n; /* Offset within index */
+
+ /* upward */
+ H5G_loc_t *loc; /* Group location to set */
+} H5G_loc_fbi_t;
-/* Local variables */
-/* PRIVATE PROTOTYPES */
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Group traversal callbacks */
static herr_t H5G_loc_find_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/*out*/);
+static herr_t H5G_loc_find_by_idx_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/*out*/);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
/*-------------------------------------------------------------------------
@@ -184,7 +231,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5G_loc_copy(H5G_loc_t *dst, H5G_loc_t *src, H5_copy_depth_t depth)
+H5G_loc_copy(H5G_loc_t *dst, const H5G_loc_t *src, H5_copy_depth_t depth)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -261,10 +308,6 @@ H5G_loc_free(H5G_loc_t *loc)
HDassert(loc);
/* Reset components of the location */
-#ifdef NOT_YET
- if(H5G_ent_free(loc->ent) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to free entry")
-#endif /* NOT_YET */
if(H5G_name_free(loc->path) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to free path")
if(H5O_loc_free(loc->oloc) < 0)
@@ -291,8 +334,8 @@ static herr_t
H5G_loc_find_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t UNUSED *lnk,
H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/)
{
- H5G_loc_ud1_t *udata = (H5G_loc_ud1_t *)_udata; /* User data passed in */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5G_loc_fnd_t *udata = (H5G_loc_fnd_t *)_udata; /* User data passed in */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5G_loc_find_cb)
@@ -328,8 +371,8 @@ herr_t
H5G_loc_find(H5G_loc_t *loc, const char *name, H5G_loc_t *obj_loc/*out*/,
hid_t lapl_id, hid_t dxpl_id)
{
- H5G_loc_ud1_t udata; /* User data for traversal callback */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5G_loc_fnd_t udata; /* User data for traversal callback */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5G_loc_find, FAIL)
@@ -351,6 +394,99 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5G_loc_find_by_idx_cb
+ *
+ * Purpose: Callback for retrieving object location for an object in a group
+ * according to the order within an index
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, November 20, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_loc_find_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name,
+ const H5O_link_t UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
+ H5G_own_loc_t *own_loc/*out*/)
+{
+ H5G_loc_fbi_t *udata = (H5G_loc_fbi_t *)_udata; /* User data passed in */
+ H5O_link_t fnd_lnk; /* Link within group */
+ hbool_t lnk_copied = FALSE; /* Whether the link was copied */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_loc_find_by_idx_cb)
+
+ /* Check if the name in this group resolved to a valid link */
+ if(obj_loc == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist")
+
+ /* Query link */
+ if(H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order,
+ udata->n, &fnd_lnk, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found")
+ lnk_copied = TRUE;
+
+ /* Build the object location for the link */
+
+done:
+ /* Reset the link information, if we have a copy */
+ if(lnk_copied)
+ H5O_reset(H5O_LINK_ID, &fnd_lnk);
+
+ /* Indicate that this callback didn't take ownership of the group *
+ * location for the object */
+ *own_loc = H5G_OWN_NONE;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_loc_find_by_idx_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_loc_find_by_idx
+ *
+ * Purpose: Find a symbol from a location, according to the order in an index
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, November 20, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_loc_find_by_idx(H5G_loc_t *loc, const char *group_name, H5L_index_t idx_type,
+ H5_iter_order_t order, hsize_t n, H5G_loc_t *obj_loc/*out*/, hid_t lapl_id,
+ hid_t dxpl_id)
+{
+ H5G_loc_fbi_t udata; /* User data for traversal callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_loc_find_by_idx, FAIL)
+
+ /* Check args. */
+ HDassert(loc);
+ HDassert(group_name && *group_name);
+ HDassert(obj_loc);
+
+ /* Set up user data for locating object */
+ udata.dxpl_id = dxpl_id;
+ udata.idx_type = idx_type;
+ udata.order = order;
+ udata.n = n;
+ udata.loc = obj_loc;
+
+ /* Traverse group hierarchy to locate object */
+ if(H5G_traverse(loc, group_name, H5G_TARGET_NORMAL, H5G_loc_find_by_idx_cb, &udata, lapl_id, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_loc_find_by_idx() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_loc_insert
*
* Purpose: Insert an object at a location
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index b240fb0..411a8e7 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -434,6 +434,8 @@ H5_DLL herr_t H5G_ent_to_link(H5F_t *f, hid_t dxpl_id, H5O_link_t *lnk,
H5_DLL herr_t H5G_ent_to_info(H5F_t *f, hid_t dxpl_id, H5L_info_t *info,
haddr_t lheap_addr, const H5G_entry_t *ent);
H5_DLL herr_t H5G_link_to_info(const H5O_link_t *lnk, H5L_info_t *linfo);
+H5_DLL herr_t H5G_link_to_loc(const H5G_loc_t *grp_loc, const H5O_link_t *lnk,
+ H5G_loc_t *obj_loc);
H5_DLL herr_t H5G_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);
@@ -529,7 +531,7 @@ H5_DLL H5RS_str_t *H5G_build_fullpath_refstr_str(H5RS_str_t *path_r, const char
/*
* These functions operate on group "locations"
*/
-H5_DLL herr_t H5G_loc_copy(H5G_loc_t *dst, H5G_loc_t *src, H5_copy_depth_t depth);
+H5_DLL herr_t H5G_loc_copy(H5G_loc_t *dst, const H5G_loc_t *src, H5_copy_depth_t depth);
H5_DLL herr_t H5G_loc_insert(H5G_loc_t *grp_loc, const char *name,
H5G_loc_t *obj_loc, hid_t dxpl_id);
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 69a448a..786b6a6 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -193,6 +193,9 @@ H5_DLL ssize_t H5G_get_refobj_name(hid_t fid, hid_t dxpl_id,
H5_DLL herr_t H5G_loc(hid_t loc_id, H5G_loc_t *loc);
H5_DLL herr_t H5G_loc_find(H5G_loc_t *loc, const char *name,
H5G_loc_t *obj_loc/*out*/, hid_t lapl_id, hid_t dxpl_id);
+H5_DLL herr_t H5G_loc_find_by_idx(H5G_loc_t *loc, const char *group_name,
+ H5L_index_t idx_type, H5_iter_order_t order, hsize_t n,
+ H5G_loc_t *obj_loc/*out*/, hid_t lapl_id, hid_t dxpl_id);
H5_DLL herr_t H5G_loc_reset(H5G_loc_t *loc);
H5_DLL herr_t H5G_loc_free(H5G_loc_t *loc);
diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c
index 4c92bc4..3cb66cc 100644
--- a/src/H5Gtraverse.c
+++ b/src/H5Gtraverse.c
@@ -52,13 +52,13 @@ static char *H5G_comp_g = NULL; /*component buffer */
static size_t H5G_comp_alloc_g = 0; /*sizeof component buffer */
/* PRIVATE PROTOTYPES */
-static herr_t H5G_traverse_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
+static herr_t H5G_traverse_link_cb(H5G_loc_t *grp_loc, const char *name,
const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
H5G_own_loc_t *own_loc/*out*/);
-static herr_t H5G_traverse_ud(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk,
+static herr_t H5G_traverse_ud(const H5G_loc_t *grp_loc, const H5O_link_t *lnk,
H5G_loc_t *obj_loc/*in,out*/, size_t *nlinks/*in,out*/, hid_t lapl_id,
hid_t dxpl_id);
-static herr_t H5G_traverse_slink(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk,
+static herr_t H5G_traverse_slink(const H5G_loc_t *grp_loc, const H5O_link_t *lnk,
H5G_loc_t *obj_loc/*in,out*/, size_t *nlinks/*in,out*/, hid_t lapl_id,
hid_t dxpl_id);
static herr_t H5G_traverse_mount(H5G_loc_t *loc/*in,out*/);
@@ -147,7 +147,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_traverse_ud(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk,
+H5G_traverse_ud(const H5G_loc_t *grp_loc/*in,out*/, const H5O_link_t *lnk,
H5G_loc_t *obj_loc/*in,out*/, size_t *nlinks/*in,out*/, hid_t _lapl_id,
hid_t dxpl_id)
{
@@ -291,9 +291,7 @@ done:
* whose entry is GRP_LOC and the link tail entry is OBJ_LOC.
*
* Return: Success: Non-negative, OBJ_LOC will contain information
- * about the object to which the link points and
- * GRP_LOC will contain the information about
- * the group in which the link tail appears.
+ * about the object to which the link points
*
* Failure: Negative
*
@@ -303,7 +301,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_traverse_slink(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk,
+H5G_traverse_slink(const H5G_loc_t *grp_loc, const H5O_link_t *lnk,
H5G_loc_t *obj_loc/*in,out*/, size_t *nlinks/*in,out*/, hid_t lapl_id,
hid_t dxpl_id)
{
@@ -435,6 +433,90 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5G_traverse_special
+ *
+ * Purpose: Handle traversing special link situations
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_traverse_special(const H5G_loc_t *grp_loc, const H5O_link_t *lnk,
+ unsigned target, size_t *nlinks, hbool_t last_comp,
+ H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_traverse_special)
+
+ /* Sanity check */
+ HDassert(grp_loc);
+ HDassert(lnk);
+ HDassert(obj_loc);
+ HDassert(nlinks);
+
+ /*
+ * If we found a symbolic link then we should follow it. But if this
+ * is the last component of the name and the H5G_TARGET_SLINK bit of
+ * TARGET is set then we don't follow it.
+ */
+ if(H5L_TYPE_SOFT == lnk->type &&
+ (0 == (target & H5G_TARGET_SLINK) || !last_comp)) {
+ if((*nlinks)-- <= 0)
+ HGOTO_ERROR(H5E_LINK, H5E_NLINKS, FAIL, "too many links")
+ if(H5G_traverse_slink(grp_loc, lnk, obj_loc, nlinks, lapl_id, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "symbolic link traversal failed")
+ } /* end if */
+
+ /*
+ * If we found a user-defined link then we should follow it. But if this
+ * is the last component of the name and the H5G_TARGET_UDLINK bit of
+ * TARGET is set then we don't follow it.
+ */
+ if(lnk->type >= H5L_TYPE_UD_MIN &&
+ (0 == (target & H5G_TARGET_UDLINK) || !last_comp) ) {
+ if((*nlinks)-- <= 0)
+ HGOTO_ERROR(H5E_LINK, H5E_NLINKS, FAIL, "too many links")
+ if(H5G_traverse_ud(grp_loc, lnk, obj_loc, nlinks, lapl_id, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "user-defined link traversal failed")
+ } /* end if */
+
+ /*
+ * Resolve mount points to the mounted group. Do not do this step if
+ * the H5G_TARGET_MOUNT bit of TARGET is set and this is the last
+ * component of the name.
+ *
+ * (If this link is a hard link, try to perform mount point traversal)
+ *
+ * (Note that the soft and external link traversal above can change
+ * the status of the object (into a hard link), so don't use an 'else'
+ * statement here. -QAK)
+ */
+ if(H5F_addr_defined(obj_loc->oloc->addr) &&
+ (0 == (target & H5G_TARGET_MOUNT) || !last_comp)) {
+ if(H5G_traverse_mount(obj_loc/*in,out*/) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "mount point traversal failed")
+ } /* end if */
+
+ /* If the grp_loc is the only thing holding an external file open
+ * and obj_loc is in the same file, obj_loc should also hold the
+ * file open so that closing the grp_loc doesn't close the file.
+ */
+ if(grp_loc->oloc->holding_file && grp_loc->oloc->file == obj_loc->oloc->file)
+ if(H5O_loc_hold_file(obj_loc->oloc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to hold file open")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_traverse_special() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_traverse_real
*
* Purpose: Internal version of path traversal routine
@@ -564,75 +646,22 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
/* (Defer issuing error for bad lookup until later) */
lookup_status = H5G_obj_lookup(grp_loc.oloc, H5G_comp_g, &lnk/*out*/, dxpl_id);
- /* If the lookup was OK, try traversing soft links and mount points, if allowed */
+ /* If the lookup was OK, build object location and traverse special links, etc. */
if(lookup_status >= 0) {
- /* Indicate that the link info is valid */
+ /* Sanity check link and indicate it's valid */
HDassert(lnk.type >= H5L_TYPE_HARD);
- if(lnk.type >H5L_TYPE_BUILTIN_MAX && lnk.type < H5L_TYPE_UD_MIN)
- HGOTO_ERROR(H5E_SYM, H5E_UNSUPPORTED, FAIL, "unknown link type")
+ HDassert(!HDstrcmp(H5G_comp_g, lnk.name));
link_valid = TRUE;
- /* Build object's group hier. location */
- if(H5G_name_set(grp_loc.path, obj_loc.path, H5G_comp_g) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name")
-
- /* Set the object location, if it's a hard link set the address also */
- obj_loc.oloc->file = grp_loc.oloc->file;
- obj_loc.oloc->holding_file = FALSE;
- if(lnk.type == H5L_TYPE_HARD)
- obj_loc.oloc->addr = lnk.u.hard.addr;
+ /* Build object location from the link */
+ if(H5G_link_to_loc(&grp_loc, &lnk, &obj_loc) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot initialize object location")
obj_loc_valid = TRUE;
- /*
- * If we found a symbolic link then we should follow it. But if this
- * is the last component of the name and the H5G_TARGET_SLINK bit of
- * TARGET is set then we don't follow it.
- */
- if(H5L_TYPE_SOFT == lnk.type &&
- (0 == (target & H5G_TARGET_SLINK) || !last_comp)) {
- if((*nlinks)-- <= 0)
- HGOTO_ERROR(H5E_LINK, H5E_NLINKS, FAIL, "too many links")
- if(H5G_traverse_slink(&grp_loc/*in,out*/, &lnk/*in*/, &obj_loc, nlinks, lapl_id, dxpl_id) < 0)
- HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "symbolic link traversal failed")
- } /* end if */
-
- /*
- * If we found a user-defined link then we should follow it. But if this
- * is the last component of the name and the H5G_TARGET_UDLINK bit of
- * TARGET is set then we don't follow it.
- */
- if(lnk.type >= H5L_TYPE_UD_MIN &&
- (0 == (target & H5G_TARGET_UDLINK) || !last_comp) ) {
- if((*nlinks)-- <= 0)
- HGOTO_ERROR(H5E_LINK, H5E_NLINKS, FAIL, "too many links")
- if(H5G_traverse_ud(&grp_loc/*in,out*/, &lnk/*in*/, &obj_loc, nlinks, lapl_id, dxpl_id) < 0)
- HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "user-defined link traversal failed")
- } /* end if */
-
- /*
- * Resolve mount points to the mounted group. Do not do this step if
- * the H5G_TARGET_MOUNT bit of TARGET is set and this is the last
- * component of the name.
- *
- * (If this link is a hard link, try to perform mount point traversal)
- *
- * (Note that the soft and external link traversal above can change
- * the status of the object (into a hard link), so don't use an 'else'
- * statement here. -QAK)
- */
- if(H5F_addr_defined(obj_loc.oloc->addr) &&
- (0 == (target & H5G_TARGET_MOUNT) || !last_comp)) {
- if(H5G_traverse_mount(&obj_loc/*in,out*/) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "mount point traversal failed")
- } /* end if */
-
- /* If the grp_loc is the only thing holding an external file open
- * and obj_loc is in the same file, obj_loc should also hold the
- * file open so that closing the grp_loc doesn't close the file.
- */
- if(grp_loc.oloc->holding_file && grp_loc.oloc->file == obj_loc.oloc->file)
- if(H5O_loc_hold_file(obj_loc.oloc) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to hold file open")
+ /* Perform any special traversals that the link needs */
+ /* (soft links, user-defined links, file mounting, etc.) */
+ if(H5G_traverse_special(&grp_loc, &lnk, target, nlinks, last_comp, &obj_loc, lapl_id, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "special link traversal failed")
} /* end if */
/* Check for last component in name provided */
diff --git a/src/H5L.c b/src/H5L.c
index d6a9fa7..6ef6338 100644
--- a/src/H5L.c
+++ b/src/H5L.c
@@ -1935,7 +1935,7 @@ H5L_get_val_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name,
H5G_own_loc_t *own_loc/*out*/)
{
H5L_trav_gvbi_t *udata = (H5L_trav_gvbi_t *)_udata; /* User data passed in */
- H5O_link_t grp_lnk; /* Link within group */
+ H5O_link_t fnd_lnk; /* Link within group */
hbool_t lnk_copied = FALSE; /* Whether the link was copied */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1947,18 +1947,18 @@ H5L_get_val_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name,
/* Query link */
if(H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order,
- udata->n, &grp_lnk, udata->dxpl_id) < 0)
+ udata->n, &fnd_lnk, udata->dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found")
lnk_copied = TRUE;
/* Retrieve the value for the link */
- if(H5L_get_val_real(&grp_lnk, udata->buf, udata->size) < 0)
+ if(H5L_get_val_real(&fnd_lnk, udata->buf, udata->size) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't retrieve link value")
done:
/* Reset the link information, if we have a copy */
if(lnk_copied)
- H5O_reset(H5O_LINK_ID, &grp_lnk);
+ H5O_reset(H5O_LINK_ID, &fnd_lnk);
/* Indicate that this callback didn't take ownership of the group *
* location for the object */
@@ -2610,7 +2610,7 @@ H5L_get_info_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name,
H5G_own_loc_t *own_loc/*out*/)
{
H5L_trav_gibi_t *udata = (H5L_trav_gibi_t *)_udata; /* User data passed in */
- H5O_link_t grp_lnk; /* Link within group */
+ H5O_link_t fnd_lnk; /* Link within group */
hbool_t lnk_copied = FALSE; /* Whether the link was copied */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2622,18 +2622,18 @@ H5L_get_info_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name,
/* Query link */
if(H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order,
- udata->n, &grp_lnk, udata->dxpl_id) < 0)
+ udata->n, &fnd_lnk, udata->dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found")
lnk_copied = TRUE;
/* Get information from the link */
- if(H5G_link_to_info(&grp_lnk, udata->linfo) < 0)
+ if(H5G_link_to_info(&fnd_lnk, udata->linfo) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get link info")
done:
/* Reset the link information, if we have a copy */
if(lnk_copied)
- H5O_reset(H5O_LINK_ID, &grp_lnk);
+ H5O_reset(H5O_LINK_ID, &fnd_lnk);
/* Indicate that this callback didn't take ownership of the group *
* location for the object */
diff --git a/src/H5O.c b/src/H5O.c
index b1b373a..ff18111 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -268,6 +268,7 @@ H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found")
loc_found = TRUE;
+ /* Open the object */
if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
@@ -282,6 +283,81 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5Oopen_by_idx
+ *
+ * Purpose: Opens an object within an HDF5 file, according to the offset
+ * within an index.
+ *
+ * This function opens an object in the same way that H5Gopen,
+ * H5Topen, and H5Dopen do. However, H5Oopen doesn't require
+ * the type of object to be known beforehand. This can be
+ * useful in user-defined links, for instance, when only a
+ * path is known.
+ *
+ * The opened object should be closed again with H5Oclose
+ * or H5Gclose, H5Tclose, or H5Dclose.
+ *
+ * Return: Success: An open object identifier
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * November 20 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Oopen_by_idx(hid_t loc_id, const char *group_name, H5L_index_t idx_type,
+ H5_iter_order_t order, hsize_t n, hid_t lapl_id)
+{
+ H5G_loc_t loc;
+ H5G_loc_t obj_loc; /* Location used to open group */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+ hbool_t loc_found = FALSE; /* Entry at 'name' found */
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER_API(H5Oopen_by_idx, FAIL)
+
+ /* Check args */
+ if(H5G_loc(loc_id, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(!group_name || !*group_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
+ if(idx_type <= H5L_INDEX_UNKNOWN || idx_type >= H5L_INDEX_N)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
+ if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
+ if(H5P_DEFAULT == lapl_id)
+ lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID")
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object's location, according to the order in the index */
+ if(H5G_loc_find_by_idx(&loc, group_name, idx_type, order, n, &obj_loc/*out*/, lapl_id, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found")
+ loc_found = TRUE;
+
+ /* Open the object */
+ if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
+
+done:
+ if(ret_value < 0)
+ if(loc_found)
+ if(H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location")
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Oopen_by_idx() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Oopen_by_addr
*
* Purpose: Warning! This function is EXTREMELY DANGEROUS!
@@ -332,7 +408,7 @@ H5Oopen_by_addr(hid_t loc_id, haddr_t addr)
/* Check args */
if(H5G_loc(loc_id, &loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(addr == 0)
+ if(!H5F_addr_defined(addr))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no address supplied")
/* Set up opened group location to fill in */
@@ -341,18 +417,17 @@ H5Oopen_by_addr(hid_t loc_id, haddr_t addr)
H5G_loc_reset(&obj_loc);
obj_loc.oloc->addr = addr;
obj_loc.oloc->file = loc.oloc->file;
- H5G_name_reset(obj_loc.path);
+ H5G_name_reset(obj_loc.path); /* objects opened through this routine don't have a path name */
+ /* Open the object */
if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
done:
- if(ret_value < 0) {
- if(loc_found) {
+ if(ret_value < 0)
+ if(loc_found)
if(H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location")
- }
- } /* end if */
FUNC_LEAVE_API(ret_value)
} /* end H5Oopen_by_addr() */
diff --git a/src/H5Opublic.h b/src/H5Opublic.h
index 9576ff1..258f701 100644
--- a/src/H5Opublic.h
+++ b/src/H5Opublic.h
@@ -29,8 +29,13 @@
#define _H5Opublic_H
/* Public headers needed by this file */
-#include "H5public.h"
-#include "H5Ipublic.h"
+#include "H5public.h" /* Generic Functions */
+#include "H5Ipublic.h" /* IDs */
+#include "H5Lpublic.h" /* Links */
+
+/*****************/
+/* Public Macros */
+/*****************/
/* Flags for object copy (H5Ocopy) */
#define H5O_COPY_SHALLOW_HIERARCHY_FLAG (0x0001u) /* Copy only immediate members */
@@ -57,6 +62,10 @@
#define H5O_MESG_ALL_FLAG (H5O_MESG_SDSPACE_FLAG | H5O_MESG_DTYPE_FLAG | H5O_MESG_FILL_FLAG | H5O_MESG_PLINE_FLAG | H5O_MESG_ATTR_FLAG)
+/*******************/
+/* Public Typedefs */
+/*******************/
+
typedef struct H5O_stat_t {
hsize_t size; /* Total size of object header in file */
hsize_t free; /* Free space within object header */
@@ -64,12 +73,23 @@ typedef struct H5O_stat_t {
unsigned nchunks; /* Number of object header chunks */
} H5O_stat_t;
+
+/********************/
+/* Public Variables */
+/********************/
+
+
#ifdef __cplusplus
extern "C" {
#endif
+/*********************/
+/* Public Prototypes */
+/*********************/
H5_DLL hid_t H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id);
H5_DLL hid_t H5Oopen_by_addr(hid_t loc_id, haddr_t addr);
+H5_DLL hid_t H5Oopen_by_idx(hid_t loc_id, const char *group_name,
+ H5L_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id);
H5_DLL herr_t H5Oincr_refcount(hid_t object_id);
H5_DLL herr_t H5Odecr_refcount(hid_t object_id);
H5_DLL herr_t H5Ocopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
@@ -79,4 +99,5 @@ H5_DLL herr_t H5Oclose(hid_t object_id);
#ifdef __cplusplus
}
#endif
-#endif
+#endif /* _H5Opublic_H */
+