summaryrefslogtreecommitdiffstats
path: root/src/H5Gtraverse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Gtraverse.c')
-rw-r--r--src/H5Gtraverse.c171
1 files changed, 100 insertions, 71 deletions
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 */