summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--src/H5F.c12
-rw-r--r--src/H5FD.c10
-rw-r--r--src/H5Fprivate.h2
-rw-r--r--src/H5G.c461
-rw-r--r--src/H5Gcompact.c8
-rw-r--r--src/H5Gdense.c47
-rw-r--r--src/H5Gdeprec.c4
-rw-r--r--src/H5Glink.c33
-rw-r--r--src/H5Gname.c282
-rw-r--r--src/H5Gnode.c52
-rw-r--r--src/H5Gobj.c45
-rw-r--r--src/H5Gpkg.h43
-rw-r--r--src/H5Gprivate.h2
-rw-r--r--src/H5Gstab.c10
-rw-r--r--src/H5L.c72
-rw-r--r--src/H5Lpublic.h3
-rw-r--r--src/H5O.c48
-rw-r--r--src/H5Olinfo.c7
-rw-r--r--src/H5Oprivate.h1
-rw-r--r--src/H5R.c2
-rw-r--r--src/H5SL.c42
-rw-r--r--src/H5SLprivate.h3
-rw-r--r--src/H5private.h6
-rw-r--r--test/getname.c91
-rw-r--r--test/mount.c26
-rw-r--r--tools/h5copy/h5copy.c4
-rw-r--r--tools/h5dump/h5dump.c10
-rw-r--r--tools/h5ls/h5ls.c524
-rwxr-xr-xtools/h5ls/testh5ls.sh1
-rw-r--r--tools/h5stat/h5stat.c327
-rw-r--r--tools/h5stat/testfiles/h5stat_filters-file.ddl1
-rw-r--r--tools/h5stat/testfiles/h5stat_filters.ddl1
-rw-r--r--tools/h5stat/testfiles/h5stat_newgrat.ddl1
-rw-r--r--tools/h5stat/testfiles/h5stat_tsohm.ddl1
-rw-r--r--tools/lib/h5tools_ref.c192
-rw-r--r--tools/lib/h5tools_utils.c186
-rw-r--r--tools/lib/h5tools_utils.h2
-rw-r--r--tools/lib/h5trav.c276
-rw-r--r--tools/lib/h5trav.h14
-rw-r--r--tools/testfiles/h5copytst.out.ls3
-rw-r--r--tools/testfiles/h5mkgrp_nested.ls3
-rw-r--r--tools/testfiles/h5mkgrp_nested_latest.ls4
-rw-r--r--tools/testfiles/h5mkgrp_nested_mult.ls3
-rw-r--r--tools/testfiles/h5mkgrp_nested_mult_latest.ls4
-rw-r--r--tools/testfiles/h5mkgrp_several.ls3
-rw-r--r--tools/testfiles/h5mkgrp_several_latest.ls4
-rw-r--r--tools/testfiles/h5mkgrp_single.ls3
-rw-r--r--tools/testfiles/h5mkgrp_single_latest.ls4
-rw-r--r--tools/testfiles/tall-2.ls1
-rw-r--r--tools/testfiles/tarray1.ls1
-rw-r--r--tools/testfiles/tattr2.ls143
-rw-r--r--tools/testfiles/tcomp-1.ls1
-rw-r--r--tools/testfiles/tdset-1.ls1
-rw-r--r--tools/testfiles/textlink-1.ls1
-rw-r--r--tools/testfiles/tgroup-1.ls40
-rw-r--r--tools/testfiles/tgroup-2.ls4
-rw-r--r--tools/testfiles/tloop-1.ls1
-rw-r--r--tools/testfiles/tnestcomp-1.ls1
-rw-r--r--tools/testfiles/tsaf.ls1
-rw-r--r--tools/testfiles/tslink-1.ls1
-rw-r--r--tools/testfiles/tstr-1.ls1
-rw-r--r--tools/testfiles/tudlink-1.ls1
-rw-r--r--tools/testfiles/tvldtypes1.ls1
64 files changed, 1541 insertions, 1542 deletions
diff --git a/MANIFEST b/MANIFEST
index bc6ef0a..00afbc9 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1238,6 +1238,7 @@
./tools/testfiles/tcomp-1.ls
./tools/testfiles/tdset-1.ls
./tools/testfiles/tgroup-1.ls
+./tools/testfiles/tgroup-2.ls
./tools/testfiles/tgroup.ls
./tools/testfiles/thlink-1.ls
./tools/testfiles/tloop-1.ls
diff --git a/src/H5F.c b/src/H5F.c
index 8844b8d..045705f 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -2444,8 +2444,6 @@ H5F_get_driver_id(const H5F_t *f)
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* March 27, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -2455,13 +2453,13 @@ H5F_get_fileno(const H5F_t *f, unsigned long *filenum)
FUNC_ENTER_NOAPI(H5F_get_fileno, FAIL)
- assert(f);
- assert(f->shared);
- assert(f->shared->lf);
- assert(filenum);
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+ HDassert(filenum);
/* Retrieve the file's serial number */
- if(H5FD_get_fileno(f->shared->lf,filenum) < 0)
+ if(H5FD_get_fileno(f->shared->lf, filenum) < 0)
HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno")
done:
diff --git a/src/H5FD.c b/src/H5FD.c
index 096509e..0cf70ca 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -3795,22 +3795,20 @@ done:
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* March 27, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
H5FD_get_fileno(const H5FD_t *file, unsigned long *filenum)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_get_fileno, FAIL)
- assert(file);
- assert(filenum);
+ HDassert(file);
+ HDassert(filenum);
/* Retrieve the file's serial number */
- HDmemcpy(filenum,&file->fileno,sizeof(file->fileno));
+ *filenum = file->fileno;
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index f9a1f57..1044b14 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -267,6 +267,7 @@ typedef struct H5F_t H5F_t;
#define H5F_INTENT(F) ((F)->intent)
#define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree)
#define H5F_STORE_MSG_CRT_IDX(F) ((F)->shared->store_msg_crt_idx)
+#define H5F_GET_FILENO(F,FILENUM) ((FILENUM) = (F)->shared->lf->fileno)
#else /* H5F_PACKAGE */
#define H5F_FCPL(F) (H5F_get_fcpl(F))
#define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F))
@@ -285,6 +286,7 @@ typedef struct H5F_t H5F_t;
#define H5F_INTENT(F) (H5F_get_intent(F))
#define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F))
#define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F))
+#define H5F_GET_FILENO(F,FILENUM) (H5F_get_filenum((F), &(FILENUM)))
#endif /* H5F_PACKAGE */
diff --git a/src/H5G.c b/src/H5G.c
index bca0332..116cdf8 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -88,6 +88,7 @@
#include "H5Gpkg.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
#include "H5Lprivate.h" /* Links */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
/* Local macros */
@@ -100,14 +101,43 @@ typedef struct {
H5G_loc_t *loc; /* Pointer to the location for insertion */
} H5G_trav_ins_t;
+/* User data for application-style iteration over links in a group */
+typedef struct {
+ hid_t gid; /* The group ID for the application callback */
+ H5G_link_iterate_t lnk_op; /* Application callback */
+ void *op_data; /* Application's op data */
+} H5G_iter_appcall_ud_t;
+
+/* User data for recursive traversal over links from a group */
+typedef struct {
+ hid_t gid; /* The group ID for the starting group */
+ H5G_loc_t *curr_loc; /* Location of starting group */
+ hid_t lapl_id; /* LAPL for walking across links */
+ hid_t dxpl_id; /* DXPL for operations */
+ H5_index_t idx_type; /* Index to use */
+ H5_iter_order_t order; /* Iteration order within index */
+ H5SL_t *visited; /* Skip list for tracking visited nodes */
+ char *path; /* Path name of the link */
+ size_t curr_path_len; /* Current length of the path in the buffer */
+ size_t path_buf_size; /* Size of path buffer */
+ H5L_iterate_t op; /* Application callback */
+ void *op_data; /* Application's op data */
+} H5G_iter_visit_ud_t;
+
+
/* Package variables */
+
/* Local variables */
/* Declare a free list to manage the H5G_t struct */
H5FL_DEFINE(H5G_t);
H5FL_DEFINE(H5G_shared_t);
+/* Declare the free list to manage H5_obj_t's */
+H5FL_DEFINE_STATIC(H5_obj_t);
+
+
/* Private prototypes */
static herr_t H5G_open_oid(H5G_t *grp, hid_t dxpl_id);
@@ -366,7 +396,7 @@ H5Gopen2(hid_t loc_id, const char *name, hid_t gapl_id)
if((grp = H5G_open_name(&loc, name, gapl_id, H5AC_dxpl_id)) == NULL)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- /* Register an atom for the group */
+ /* Register an ID for the group */
if((ret_value = H5I_register(H5I_GROUP, grp)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
@@ -1019,8 +1049,8 @@ H5G_open_name(const H5G_loc_t *loc, const char *name, hid_t gapl_id,
H5G_loc_t grp_loc; /* Location used to open group */
H5G_name_t grp_path; /* Opened object group hier. path */
H5O_loc_t grp_oloc; /* Opened object object location */
- H5O_type_t obj_type; /* Type of object at location */
hbool_t loc_found = FALSE; /* Location at 'name' found */
+ H5O_type_t obj_type; /* Type of object at location */
H5G_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_open_name, NULL)
@@ -1145,7 +1175,7 @@ H5G_open(const H5G_loc_t *loc, hid_t dxpl_id)
ret_value = grp;
done:
- if (!ret_value && grp) {
+ if(!ret_value && grp) {
H5O_loc_free(&(grp->oloc));
H5G_name_free(&(grp->path));
H5FL_FREE(H5G_t,grp);
@@ -1522,3 +1552,428 @@ H5G_unmount(H5G_t *grp)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5G_unmount() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_iterate_cb
+ *
+ * Purpose: Callback function for iterating over links in a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Oct 3, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_iterate_cb(const H5O_link_t *lnk, void *_udata)
+{
+ H5G_iter_appcall_ud_t *udata = (H5G_iter_appcall_ud_t *)_udata; /* User data for callback */
+ herr_t ret_value = H5_ITER_ERROR; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_iterate_cb)
+
+ /* Sanity check */
+ HDassert(lnk);
+ HDassert(udata);
+
+ switch(udata->lnk_op.op_type) {
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ case H5G_LINK_OP_OLD:
+ /* Make the old-type application callback */
+ ret_value = (udata->lnk_op.op_func.op_old)(udata->gid, lnk->name, udata->op_data);
+ break;
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
+ case H5G_LINK_OP_NEW:
+ {
+ H5L_info_t info; /* Link info */
+
+ /* Retrieve the info for the link */
+ if(H5G_link_to_info(lnk, &info) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link")
+
+ /* Make the application callback */
+ ret_value = (udata->lnk_op.op_func.op_new)(udata->gid, lnk->name, &info, udata->op_data);
+ }
+ break;
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_iterate_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_iterate
+ *
+ * Purpose: Private function for iterating over links in a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Oct 3, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_iterate(hid_t loc_id, const char *group_name,
+ H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
+ const H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id)
+{
+ H5G_loc_t loc; /* Location of parent for group */
+ hid_t gid = -1; /* ID of group to iterate over */
+ H5G_t *grp; /* Pointer to group data structure to iterate over */
+ H5G_iter_appcall_ud_t udata; /* User data for callback */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_iterate, FAIL)
+
+ /* Sanity check */
+ HDassert(group_name);
+ HDassert(last_lnk);
+ HDassert(lnk_op && lnk_op->op_func.op_new);
+
+ /*
+ * Open the group on which to operate. We also create a group ID which
+ * we can pass to the application-defined operator.
+ */
+ if(H5G_loc(loc_id, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(NULL == (grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id)))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
+ if((gid = H5I_register(H5I_GROUP, grp)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
+
+ /* Set up user data for callback */
+ udata.gid = gid;
+ udata.lnk_op = *lnk_op;
+ udata.op_data = op_data;
+
+ /* Call the real group iteration routine */
+ if((ret_value = H5G_obj_iterate(&(grp->oloc), idx_type, order, skip, last_lnk, H5G_iterate_cb, &udata, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "error iterating over links")
+
+done:
+ /* Release the group opened */
+ if(gid > 0) {
+ if(H5I_dec_ref(gid) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group")
+ } /* end if */
+ else if(grp && H5G_close(grp) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_iterate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_free_visit_visited
+ *
+ * Purpose: Free the key for an object visited during a group traversal
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Nov 4, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_free_visit_visited(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_free_visit_visited)
+
+ H5FL_FREE(H5_obj_t, item);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5G_free_visit_visited() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_visit_cb
+ *
+ * Purpose: Callback function for recursively visiting links from a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Nov 4, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_visit_cb(const H5O_link_t *lnk, void *_udata)
+{
+ H5G_iter_visit_ud_t *udata = (H5G_iter_visit_ud_t *)_udata; /* User data for callback */
+ H5L_info_t info; /* Link info */
+ H5G_loc_t obj_loc; /* Location of object */
+ H5G_name_t obj_path; /* Object's group hier. path */
+ H5O_loc_t obj_oloc; /* Object's object location */
+ hbool_t obj_found = FALSE; /* Object at 'name' found */
+ size_t old_path_len = udata->curr_path_len; /* Length of path before appending this link's name */
+ size_t link_name_len; /* Length of link's name */
+ size_t len_needed; /* Length of path string needed */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_visit_cb)
+
+ /* Sanity check */
+ HDassert(lnk);
+ HDassert(udata);
+
+ /* Check if we will need more space to store this link's relative path */
+ /* ("+2" is for string terminator and possible '/' for group separator later) */
+ link_name_len = HDstrlen(lnk->name);
+ len_needed = udata->curr_path_len + link_name_len + 2;
+ if(len_needed > udata->path_buf_size) {
+ void *new_path; /* Pointer to new path buffer */
+
+ /* Attempt to allocate larger buffer for path */
+ if(NULL == (new_path = H5MM_realloc(udata->path, len_needed)))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string")
+ udata->path = new_path;
+ udata->path_buf_size = len_needed;
+ } /* end if */
+
+ /* Build the link's relative path name */
+ HDassert(udata->path[old_path_len] == '\0');
+ HDstrcpy(&(udata->path[old_path_len]), lnk->name);
+ udata->curr_path_len += link_name_len;
+
+ /* Construct the link info from the link message */
+ if(H5G_link_to_info(lnk, &info) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link")
+
+ /* Make the application callback */
+ ret_value = (udata->op)(udata->gid, udata->path, &info, udata->op_data);
+
+ /* Check for doing more work */
+ if(ret_value == H5_ITER_CONT && lnk->type == H5L_TYPE_HARD) {
+ H5O_type_t otype; /* Basic object type (group, dataset, etc.) */
+ H5_obj_t obj_pos; /* Object "position" for this object */
+ unsigned rc; /* Reference count of object */
+
+ /* 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 using the LAPL passed in */
+ /* (Correctly handles mounted files) */
+ if(H5G_loc_find(udata->curr_loc, lnk->name, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "object not found")
+ obj_found = TRUE;
+
+ /* Construct unique "position" for this object */
+ H5F_GET_FILENO(obj_oloc.file, obj_pos.fileno);
+ obj_pos.addr = obj_oloc.addr;
+
+ /* Check if we've seen the object the link references before */
+ if(NULL == H5SL_search(udata->visited, &obj_pos)) {
+ /* Get the object's reference count and type */
+ if(H5O_get_rc_and_type(&obj_oloc, udata->dxpl_id, &rc, &otype) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info")
+
+ /* If its ref count is > 1, we add it to the list of visited objects */
+ /* (because it could come up again during traversal) */
+ if(rc > 1) {
+ H5_obj_t *new_node; /* New object node for visited list */
+
+ /* Allocate new object "position" node */
+ if((new_node = H5FL_MALLOC(H5_obj_t)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate object node")
+
+ /* Set node information */
+ *new_node = obj_pos;
+
+ /* Add to list of visited objects */
+ if(H5SL_insert(udata->visited, new_node, new_node) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert object node into visited list")
+ } /* end if */
+
+ /* If it's a group, we recurse into it */
+ if(otype == H5O_TYPE_GROUP) {
+ H5G_loc_t *old_loc = udata->curr_loc; /* Pointer to previous group location info */
+ H5_index_t idx_type = udata->idx_type; /* Type of index to use */
+ H5O_linfo_t linfo; /* Link info message */
+
+ /* Add the path separator to the current path */
+ HDassert(udata->path[udata->curr_path_len] == '\0');
+ HDstrcpy(&(udata->path[udata->curr_path_len]), "/");
+ udata->curr_path_len++;
+
+ /* Attempt to get the link info for this group */
+ if(H5G_obj_get_linfo(&obj_oloc, &linfo, udata->dxpl_id)) {
+ /* Check for creation order tracking, if creation order index lookup requested */
+ if(idx_type == H5_INDEX_CRT_ORDER) {
+ /* Check if creation order is tracked */
+ if(!linfo.track_corder)
+ /* Switch to name order for this group */
+ idx_type = H5_INDEX_NAME;
+ } /* end if */
+ else
+ HDassert(idx_type == H5_INDEX_NAME);
+ } /* end if */
+ else {
+ /* Clear error stack from not finding the link info message */
+ H5E_clear_stack(NULL);
+
+ /* Can only perform name lookups on groups with symbol tables */
+ if(idx_type != H5_INDEX_NAME)
+ /* Switch to name order for this group */
+ idx_type = H5_INDEX_NAME;
+ } /* end if */
+
+ /* Point to this group's location info */
+ udata->curr_loc = &obj_loc;
+
+ /* Iterate over links in group */
+ ret_value = H5G_obj_iterate(&obj_oloc, idx_type, udata->order, (hsize_t)0, NULL, H5G_visit_cb, udata, udata->dxpl_id);
+
+ /* Restore location */
+ udata->curr_loc = old_loc;
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
+done:
+ /* Reset path back to incoming path */
+ udata->path[old_path_len] = '\0';
+ udata->curr_path_len = old_path_len;
+
+ /* Release resources */
+ if(obj_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_visit_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_visit
+ *
+ * Purpose: Recursively visit all the links in a group and all
+ * the groups that are linked to from that group. Links within
+ * each group are visited according to the order within the
+ * specified index (unless the specified index does not exist for
+ * a particular group, then the "name" index is used).
+ *
+ * NOTE: Each _link_ reachable from the initial group will only be
+ * visited once. However, because an object may be reached from
+ * more than one link, the visitation may call the application's
+ * callback with more than one link that points to a particular
+ * _object_.
+ *
+ * Return: Success: The return value of the first operator that
+ * returns non-zero, or zero if all members were
+ * processed with no operator returning non-zero.
+ *
+ * Failure: Negative if something goes wrong within the
+ * library, or the negative value returned by one
+ * of the operators.
+ *
+ *
+ *
+ * Programmer: Quincey Koziol
+ * November 4 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type,
+ H5_iter_order_t order, H5L_iterate_t op, void *op_data, hid_t lapl_id,
+ hid_t dxpl_id)
+{
+ H5G_iter_visit_ud_t udata; /* User data for callback */
+ H5O_linfo_t linfo; /* Link info message */
+ hid_t gid = (-1); /* Group ID */
+ H5G_t *grp = NULL; /* Group opened */
+ H5G_loc_t loc; /* Location of group passed in */
+ H5G_loc_t start_loc; /* Location of starting group */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_visit, FAIL)
+
+ /* Check args */
+ if(H5G_loc(loc_id, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* Open the group to begin visiting within */
+ if((grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
+
+ /* Register an ID for the starting group */
+ if((gid = H5I_register(H5I_GROUP, grp)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
+
+ /* Get the location of the starting group */
+ if(H5G_loc(gid, &start_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* Set up user data */
+ udata.gid = gid;
+ udata.curr_loc = &start_loc;
+ udata.lapl_id = lapl_id;
+ udata.dxpl_id = dxpl_id;
+ udata.idx_type = idx_type;
+ udata.order = order;
+ udata.op = op;
+ udata.op_data = op_data;
+
+ /* Allocate space for the path name */
+ if(NULL == (udata.path = H5MM_strdup("")))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate path name buffer")
+ udata.path_buf_size = 1;
+ udata.curr_path_len = 0;
+
+ /* Create skip list to store reference path information */
+ if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, 0.5, (size_t)16)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects")
+
+ /* Attempt to get the link info for this group */
+ if(H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) {
+ /* Check for creation order tracking, if creation order index lookup requested */
+ if(idx_type == H5_INDEX_CRT_ORDER) {
+ /* Check if creation order is tracked */
+ if(!linfo.track_corder)
+ /* Switch to name order for this group */
+ idx_type = H5_INDEX_NAME;
+ } /* end if */
+ else
+ HDassert(idx_type == H5_INDEX_NAME);
+ } /* end if */
+ else {
+ /* Clear error stack from not finding the link info message */
+ H5E_clear_stack(NULL);
+
+ /* Can only perform name lookups on groups with symbol tables */
+ if(idx_type != H5_INDEX_NAME)
+ /* Switch to name order for this group */
+ idx_type = H5_INDEX_NAME;
+ } /* end if */
+
+ /* Call the link iteration routine */
+ if((ret_value = H5G_obj_iterate(&(grp->oloc), idx_type, order, (hsize_t)0, NULL, H5G_visit_cb, &udata, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't visit links")
+
+done:
+ /* Release user data resources */
+ H5MM_xfree(udata.path);
+ if(udata.visited)
+ H5SL_destroy(udata.visited, H5G_free_visit_visited, NULL);
+
+ /* Release the group opened */
+ if(gid > 0) {
+ if(H5I_dec_ref(gid) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group")
+ } /* end if */
+ else if(grp && H5G_close(grp) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_visit() */
+
diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c
index 042d29a..b0340a7 100644
--- a/src/H5Gcompact.c
+++ b/src/H5Gcompact.c
@@ -406,9 +406,9 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo,
+H5G_compact_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo,
H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
- hid_t gid, H5G_link_iterate_t *lnk_op, void *op_data)
+ H5G_lib_iterate_t op, void *op_data)
{
H5G_link_table_t ltable = {0, NULL}; /* Link table */
herr_t ret_value; /* Return value */
@@ -418,14 +418,14 @@ H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo,
/* Sanity check */
HDassert(oloc);
HDassert(linfo);
- HDassert(lnk_op && lnk_op->u.lib_op);
+ HDassert(op);
/* Build table of all link messages */
if(H5G_compact_build_table(oloc, dxpl_id, linfo, idx_type, order, &ltable) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table")
/* Iterate over links in table */
- if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, gid, lnk_op, op_data)) < 0)
+ if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, op, op_data)) < 0)
HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
done:
diff --git a/src/H5Gdense.c b/src/H5Gdense.c
index 2b7493b..ed53a47 100644
--- a/src/H5Gdense.c
+++ b/src/H5Gdense.c
@@ -90,9 +90,8 @@ typedef struct {
hsize_t count; /* # of links examined */
/* downward (from application) */
- hid_t gid; /* Group ID for application callback */
hsize_t skip; /* Number of links to skip */
- const H5G_link_iterate_t *lnk_op; /* Callback for each link */
+ H5G_lib_iterate_t op; /* Callback for each link */
void *op_data; /* Callback data for each link */
/* upward */
@@ -799,7 +798,6 @@ H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
/* Allocate space for the table entries */
if(ltable->nlinks > 0) {
H5G_dense_bt_ud_t udata; /* User data for iteration callback */
- H5G_link_iterate_t lnk_op; /* Link operator */
/* Allocate the table to store the links */
if((ltable->lnks = H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL)
@@ -809,12 +807,8 @@ H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
udata.ltable = ltable;
udata.curr_lnk = 0;
- /* Build iterator operator */
- lnk_op.op_type = H5G_LINK_OP_LIB;
- lnk_op.u.lib_op = H5G_dense_build_table_cb;
-
/* Iterate over the links in the group, building a table of the link messages */
- if(H5G_dense_iterate(f, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0)
+ if(H5G_dense_iterate(f, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, H5G_dense_build_table_cb, &udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links")
/* Sort link table in correct iteration order */
@@ -904,32 +898,8 @@ H5G_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
H5G_dense_iterate_fh_cb, &fh_udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed")
- /* Check which type of callback to make */
- switch(bt2_udata->lnk_op->op_type) {
-#ifndef H5_NO_DEPRECATED_SYMBOLS
- case H5G_LINK_OP_OLD:
- /* Make the old-type application callback */
- ret_value = (bt2_udata->lnk_op->u.old_op)(bt2_udata->gid, fh_udata.lnk->name, bt2_udata->op_data);
- break;
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
-
- case H5G_LINK_OP_APP:
- {
- H5L_info_t info; /* Link info */
-
- /* Retrieve the info for the link */
- if(H5G_link_to_info(fh_udata.lnk, &info) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link")
-
- /* Make the application callback */
- ret_value = (bt2_udata->lnk_op->u.app_op)(bt2_udata->gid, fh_udata.lnk->name, &info, bt2_udata->op_data);
- }
- break;
-
- case H5G_LINK_OP_LIB:
- /* Call the library's callback */
- ret_value = (bt2_udata->lnk_op->u.lib_op)(fh_udata.lnk, bt2_udata->op_data);
- } /* end switch */
+ /* Make the callback */
+ ret_value = (bt2_udata->op)(fh_udata.lnk, bt2_udata->op_data);
/* Release the space allocated for the link */
H5O_msg_free(H5O_LINK_ID, fh_udata.lnk);
@@ -964,7 +934,7 @@ done:
herr_t
H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
- hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data)
+ H5G_lib_iterate_t op, void *op_data)
{
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5G_link_table_t ltable = {0, NULL}; /* Table of links */
@@ -979,7 +949,7 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
*/
HDassert(f);
HDassert(linfo);
- HDassert(lnk_op && lnk_op->u.lib_op);
+ HDassert(op);
/* Determine the address of the index to use */
if(idx_type == H5_INDEX_NAME) {
@@ -1018,10 +988,9 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
udata.f = f;
udata.dxpl_id = dxpl_id;
udata.fheap = fheap;
- udata.gid = gid;
udata.skip = skip;
udata.count = 0;
- udata.lnk_op = lnk_op;
+ udata.op = op;
udata.op_data = op_data;
/* Iterate over the records in the v2 B-tree's "native" order */
@@ -1039,7 +1008,7 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "error building table of links")
/* Iterate over links in table */
- if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, gid, lnk_op, op_data)) < 0)
+ if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, op, op_data)) < 0)
HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
} /* end else */
diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c
index 52b607d..01c4edb 100644
--- a/src/H5Gdeprec.c
+++ b/src/H5Gdeprec.c
@@ -770,10 +770,10 @@ H5Giterate(hid_t loc_id, const char *name, int *idx_p, H5G_iterate_t op,
/* Build link operator info */
lnk_op.op_type = H5G_LINK_OP_OLD;
- lnk_op.u.old_op = op;
+ lnk_op.op_func.op_old = op;
/* Call private function. */
- if((ret_value = H5G_obj_iterate(loc_id, name, H5_INDEX_NAME, H5_ITER_INC, idx, &last_obj, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0)
+ if((ret_value = H5G_iterate(loc_id, name, H5_INDEX_NAME, H5_ITER_INC, idx, &last_obj, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed")
/* Set the index we stopped at */
diff --git a/src/H5Glink.c b/src/H5Glink.c
index 7292245..75a3e83 100644
--- a/src/H5Glink.c
+++ b/src/H5Glink.c
@@ -603,7 +603,7 @@ H5G_link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type,
*/
herr_t
H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip,
- hsize_t *last_lnk, hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data)
+ hsize_t *last_lnk, const H5G_lib_iterate_t op, void *op_data)
{
size_t u; /* Local index variable */
herr_t ret_value = H5_ITER_CONT; /* Return value */
@@ -612,7 +612,7 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip,
/* Sanity check */
HDassert(ltable);
- HDassert(lnk_op);
+ HDassert(op);
/* Skip over links, if requested */
if(last_lnk)
@@ -621,32 +621,8 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip,
/* Iterate over link messages */
H5_ASSIGN_OVERFLOW(/* To: */ u, /* From: */ skip, /* From: */ hsize_t, /* To: */ size_t)
for(; u < ltable->nlinks && !ret_value; u++) {
- /* Check which kind of callback to make */
- switch(lnk_op->op_type) {
-#ifndef H5_NO_DEPRECATED_SYMBOLS
- case H5G_LINK_OP_OLD:
- /* Make the old-type application callback */
- ret_value = (lnk_op->u.old_op)(gid, ltable->lnks[u].name, op_data);
- break;
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
-
- case H5G_LINK_OP_APP:
- {
- H5L_info_t info; /* Link info */
-
- /* Retrieve the info for the link */
- if(H5G_link_to_info(&(ltable->lnks[u]), &info) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link")
-
- /* Make the application callback */
- ret_value = (lnk_op->u.app_op)(gid, ltable->lnks[u].name, &info, op_data);
- }
- break;
-
- case H5G_LINK_OP_LIB:
- /* Call the library's callback */
- ret_value = (lnk_op->u.lib_op)(&(ltable->lnks[u]), op_data);
- } /* end switch */
+ /* Make the callback */
+ ret_value = (op)(&(ltable->lnks[u]), op_data);
/* Increment the number of entries passed through */
if(last_lnk)
@@ -657,7 +633,6 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip,
if(ret_value < 0)
HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
-done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_link_iterate_table() */
diff --git a/src/H5Gname.c b/src/H5Gname.c
index e341ee7..bde9e23 100644
--- a/src/H5Gname.c
+++ b/src/H5Gname.c
@@ -50,21 +50,15 @@ typedef struct H5G_names_t {
} H5G_names_t;
/* Info to pass to the iteration function when building name */
-typedef struct H5G_ref_path_iter_t {
+typedef struct H5G_gnba_iter_t {
/* In */
- hid_t file; /* File id where it came from */
+ const H5O_loc_t *loc; /* The location of the object we're looking for */
hid_t lapl_id; /* LAPL for operations */
hid_t dxpl_id; /* DXPL for operations */
- hbool_t is_root_group; /* Flag to indicate that the root group is being looked at */
- const H5O_loc_t *loc; /* The location of the object we're looking for */
-
- /* In/Out */
- H5SL_t *ref_path_table; /* Skip list for tracking visited nodes */
- size_t max_container_len; /* Maximum size of container */
/* Out */
- char *container; /* full name of the container object */
-} H5G_ref_path_iter_t;
+ char *path; /* Name of the object */
+} H5G_gnba_iter_t;
/* Private macros */
@@ -85,9 +79,6 @@ static H5RS_str_t *H5G_build_fullpath_refstr_refstr(const H5RS_str_t *prefix_r,
static herr_t H5G_name_move_path(H5RS_str_t **path_r_ptr,
const char *full_suffix, const char *src_path, const char *dst_path);
static int H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key);
-static herr_t H5G_refname_iterator(hid_t group, const char *name,
- const H5L_info_t *link_info, void *_udata);
-static herr_t H5G_free_ref_path_node(void *item, void *key, void *operator_data/*in,out*/);
/*-------------------------------------------------------------------------
@@ -468,7 +459,7 @@ H5G_get_name(hid_t id, char *name/*out*/, size_t size, hid_t lapl_id,
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve file ID")
/* Search for name of object */
- if((len = H5G_get_refobj_name(file, lapl_id, dxpl_id, loc.oloc, name, size)) < 0) {
+ if((len = H5G_get_name_by_addr(file, lapl_id, dxpl_id, loc.oloc, name, size)) < 0) {
H5I_dec_ref(file);
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't determine name")
} /* end if */
@@ -1039,222 +1030,139 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5G_refname_iterator
+ * Function: H5G_get_name_by_addr_cb
*
- * Purpose: The iterator which traverses all objects in a file looking for
- * one that matches the object that is being looked for.
+ * Purpose: Callback for retrieving object's name by address
*
- * Return: 1 on success, 0 to continue searching, negative on failure.
- *
- * Programmer: Leon Arber, Nov 1, 2006.
+ * Return: Positive if path is for object desired
+ * 0 if not correct object
+ * negative on failure.
*
- * Modifications:
- * Quincey Koziol, Nov. 3, 2006
- * Cleaned up code.
+ * Programmer: Quincey Koziol
+ * November 4 2007
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_refname_iterator(hid_t group, const char *name, const H5L_info_t *link_info,
+H5G_get_name_by_addr_cb(hid_t gid, const char *path, const H5L_info_t *linfo,
void *_udata)
{
- H5G_ref_path_iter_t *udata = (H5G_ref_path_iter_t*)_udata;
- herr_t ret_value = H5_ITER_CONT; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_refname_iterator)
-
- /* We only care about hard links */
- if(link_info->type == H5L_TYPE_HARD) {
- H5G_loc_t loc; /* Group location of parent */
-
- /* Look up group's location */
- if(H5G_loc(group, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "not a location")
-
- /* Check for finding the object */
- /* (checks against the file in the location as well, to make certain that
- * the correct object is found in a mounted file hierarchy)
- */
- if(udata->loc->addr == link_info->u.address && udata->loc->file == loc.oloc->file) {
- size_t len_needed; /* Length of container string needed */
-
- /* Build the object's full name */
- len_needed = HDstrlen(udata->container) + HDstrlen(name) + 2;
- if(len_needed > udata->max_container_len) {
- void *new_container; /* Pointer to new container */
-
- if(NULL == (new_container = H5MM_realloc(udata->container, len_needed)))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string")
- udata->container = new_container;
- udata->max_container_len = len_needed;
- } /* end if */
- HDstrcat(udata->container, name);
+ H5G_gnba_iter_t *udata = (H5G_gnba_iter_t *)_udata; /* User data for iteration */
+ H5G_loc_t obj_loc; /* Location of object */
+ H5G_name_t obj_path; /* Object's group hier. path */
+ H5O_loc_t obj_oloc; /* Object's object location */
+ hbool_t obj_found = FALSE; /* Object at 'path' found */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
- /* We found a match so we return immediately */
- HGOTO_DONE(H5_ITER_STOP)
- } /* end if */
- else {
- H5O_info_t oinfo; /* Object information */
- H5O_loc_t tmp_oloc; /* Temporary object location */
+ FUNC_ENTER_NOAPI_NOINIT(H5G_get_name_by_addr_cb)
- /* Check if we've seen this object before */
- if(H5SL_search(udata->ref_path_table, &link_info->u.address))
- HGOTO_DONE(H5_ITER_CONT)
+ /* Sanity check */
+ HDassert(path);
+ HDassert(linfo);
+ HDassert(udata->loc);
+ HDassert(udata->path == NULL);
- /* Go retrieve the object information */
- tmp_oloc.file = loc.oloc->file;
- tmp_oloc.addr = link_info->u.address;
- if(H5O_get_info(&tmp_oloc, udata->dxpl_id, FALSE, &oinfo) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info")
+ /* Check for hard link with correct address */
+ if(linfo->type == H5L_TYPE_HARD && udata->loc->addr == linfo->u.address) {
+ H5G_loc_t grp_loc; /* Location of group */
- /* If its ref count is > 1, we add it to the list of visited objects */
- if(oinfo.rc > 1) {
- haddr_t *new_node; /* New path node for table */
+ /* Get group's location */
+ if(H5G_loc(gid, &grp_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "bad group location")
- /* Allocate new path node */
- if((new_node = H5FL_MALLOC(haddr_t)) == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path node")
+ /* Set up opened object location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
- /* Set node information */
- *new_node = link_info->u.address;
+ /* Find the object */
+ if(H5G_loc_find(&grp_loc, path, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "object not found")
+ obj_found = TRUE;
- /* Insert into skip list */
- if(H5SL_insert(udata->ref_path_table, new_node, new_node) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert path node into table")
- } /* end if */
+ /* Check for object in same file (handles mounted files) */
+ /* (re-verify address, in case we traversed a file mount) */
+ if(udata->loc->addr == obj_loc.oloc->addr && udata->loc->file == obj_loc.oloc->file) {
+ udata->path = H5MM_strdup(path);
- /* If it's a group, we recurse into it */
- if(oinfo.type == H5O_TYPE_GROUP) {
- H5G_link_iterate_t lnk_op; /* Link operator */
- hsize_t last_obj;
- size_t len_needed; /* Length of container string needed */
- size_t len;
-
- /* Build full path name of group to recurse into */
- len = HDstrlen(udata->container);
- len_needed = len + HDstrlen(name) + 2;
- if(len_needed > udata->max_container_len) {
- void *new_container; /* Pointer to new container */
-
- if(NULL == (new_container = H5MM_realloc(udata->container, len_needed)))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string")
- udata->container = new_container;
- udata->max_container_len = len_needed;
- } /* end if */
- if(!udata->is_root_group)
- HDstrcat(udata->container, name);
- else
- udata->is_root_group = FALSE;
- HDstrcat(udata->container, "/");
-
- /* Build iterator operator */
- lnk_op.op_type = H5G_LINK_OP_APP;
- lnk_op.u.app_op = H5G_refname_iterator;
-
- ret_value = H5G_obj_iterate(udata->file, udata->container, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, &last_obj, &lnk_op, udata, udata->lapl_id, udata->dxpl_id);
-
- /* If we didn't find the object, truncate the name to not include group name anymore */
- if(!ret_value)
- udata->container[len] = '\0';
- } /* end if */
- } /* end else */
+ /* We found a match so we return immediately */
+ HGOTO_DONE(H5_ITER_STOP)
+ } /* end if */
} /* end if */
+
+done:
+ if(obj_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location")
-done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_refname_iterator() */
+} /* end H5G_get_name_by_addr_cb() */
/*-------------------------------------------------------------------------
- * Function: H5G_free_ref_path_node
- *
- * Purpose: Free the key for a reference path table node
- *
- * Return: Non-negative on success, negative on failure
+ * Function: H5G_get_name_by_addr
*
- * Programmer: Quincey Koziol
- *
- * Modifications:
- * Leon Arber, Oct. 25, 2006. Moved into H5G from h5ls
- * tools lib for looking up path to reference.
- *
- * Quincey Koziol, Nov. 3, 2006
- * Cleaned up code.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_free_ref_path_node(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_free_ref_path_node)
-
- H5FL_FREE(haddr_t, item);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5G_free_ref_path_node() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_get_refobj_name
- *
- * Purpose: Tries to figure out the path to a reference.
+ * Purpose: Tries to figure out the path to an object from it's address
*
* Return: returns size of path name, and copies it into buffer
* pointed to by name if that buffer is big enough.
* 0 if it cannot find the path
* negative on failure.
*
- * Programmer: Leon Arber, Nov 1, 2006.
- *
- * Modifications:
- * Quincey Koziol, Nov. 3, 2006
- * Cleaned up code.
+ * Programmer: Quincey Koziol
+ * November 4 2007
*
*-------------------------------------------------------------------------
*/
ssize_t
-H5G_get_refobj_name(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *loc,
+H5G_get_name_by_addr(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *loc,
char *name, size_t size)
{
- H5G_ref_path_iter_t udata; /* User data for iteration */
- H5G_loc_t root_loc; /* Root location */
- H5L_info_t root_info; /* Link info for root group */
+ H5G_gnba_iter_t udata; /* User data for iteration */
+ H5G_loc_t root_loc; /* Root group's location */
+ hbool_t found_obj = FALSE; /* If we found the object */
herr_t status; /* Status from iteration */
ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5G_get_refobj_name, FAIL)
+ FUNC_ENTER_NOAPI(H5G_get_name_by_addr, FAIL)
- /* Construct the link info for the root group */
+ /* Construct the link info for the file's root group */
if(H5G_loc(file, &root_loc) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get root group's location")
- HDmemset(&root_info, 0, sizeof(root_info));
- root_info.type = H5L_TYPE_HARD;
- root_info.u.address = root_loc.oloc->addr;
-
- /* Set up user data for iterator */
- udata.file = file;
- udata.lapl_id = lapl_id;
- udata.dxpl_id = dxpl_id;
- udata.is_root_group = TRUE;
- if(NULL == (udata.container = H5MM_strdup("")))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate root group name")
- udata.max_container_len = 1;
- udata.loc = loc;
-
- /* Create skip list to store reference path information */
- if((udata.ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16)) == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for path nodes")
-
- /* Iterate over all the objects in the file */
- if((status = H5G_refname_iterator(file, "/", &root_info, &udata)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed while looking for object name")
- else if(status > 0) {
+
+ /* Check for root group being the object looked for */
+ if(root_loc.oloc->addr == loc->addr && root_loc.oloc->file == loc->file) {
+ udata.path = H5MM_strdup("");
+ found_obj = TRUE;
+ } /* end if */
+ else {
+ /* Set up user data for iterator */
+ udata.loc = loc;
+ udata.lapl_id = lapl_id;
+ udata.dxpl_id = dxpl_id;
+ udata.path = NULL;
+
+ /* Visit all the links in the file */
+ if((status = H5G_visit(file, "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5G_get_name_by_addr_cb, &udata, lapl_id, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group traversal failed while looking for object name")
+ else if(status > 0)
+ found_obj = TRUE;
+ } /* end else */
+
+ /* Check for finding the object */
+ if(found_obj) {
+ size_t full_path_len = HDstrlen(udata.path) + 1; /* Length of path + 1 (for "/") */
+
/* Set the length of the full path */
- ret_value = HDstrlen(udata.container);
+ ret_value = full_path_len;
/* If there's a buffer provided, copy into it, up to the limit of its size */
if(name) {
- HDstrncpy(name, udata.container, size);
+ /* Copy the initial path separator */
+ HDstrcpy(name, "/");
+
+ /* Append the rest of the path */
+ /* (less one character, for the initial path separator) */
+ HDstrncat(name, udata.path, (size - 1));
if((size_t)ret_value >= size)
name[size - 1] = '\0';
} /* end if */
@@ -1264,10 +1172,8 @@ H5G_get_refobj_name(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *l
done:
/* Release resources */
- H5MM_xfree(udata.container);
- if(udata.ref_path_table)
- H5SL_destroy(udata.ref_path_table, H5G_free_ref_path_node, NULL);
+ H5MM_xfree(udata.path);
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_get_refobj_name() */
+} /* end H5G_get_name_by_addr() */
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index 6cff5a0..92d5717 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -1431,51 +1431,23 @@ H5G_node_iterate(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t ad
if(udata->skip > 0)
--udata->skip;
else {
- const char *name; /* Pointer to link name in heap */
+ H5O_link_t lnk; /* Link for entry */
+ const char *name; /* Pointer to link name in heap */
/* Get the pointer to the name of the link in the heap */
name = H5HL_offset_into(f, udata->heap, ents[u].name_off);
HDassert(name);
- /* Check which type of callback to make */
- switch(udata->lnk_op->op_type) {
-#ifndef H5_NO_DEPRECATED_SYMBOLS
- case H5G_LINK_OP_OLD:
- /* Make the old-type application callback */
- ret_value = (udata->lnk_op->u.old_op)(udata->group_id, name, udata->op_data);
- break;
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
-
- case H5G_LINK_OP_APP:
- {
- H5L_info_t info; /* Link info for entry */
-
- /* Make a link info for an entry */
- if(H5G_ent_to_info(f, &info, udata->heap, &ents[u]) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for symbol table entry")
-
- /* Make the application callback */
- ret_value = (udata->lnk_op->u.app_op)(udata->group_id, name, &info, udata->op_data);
- }
- break;
-
- case H5G_LINK_OP_LIB:
- /* Call the library's callback */
- {
- H5O_link_t lnk; /* Link for entry */
-
- /* Convert the entry to a link */
- if(H5G_ent_to_link(f, &lnk, udata->heap, &ents[u], name) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link")
-
- /* Call the library's callback */
- ret_value = (udata->lnk_op->u.lib_op)(&lnk, udata->op_data);
-
- /* Release memory for link object */
- if(H5O_msg_reset(H5O_LINK_ID, &lnk) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, H5_ITER_ERROR, "unable to release link message")
- }
- } /* end switch */
+ /* Convert the entry to a link */
+ if(H5G_ent_to_link(f, &lnk, udata->heap, &ents[u], name) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link")
+
+ /* Make the callback */
+ ret_value = (udata->op)(&lnk, udata->op_data);
+
+ /* Release memory for link object */
+ if(H5O_msg_reset(H5O_LINK_ID, &lnk) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, H5_ITER_ERROR, "unable to release link message")
} /* end else */
/* Increment the number of entries passed through */
diff --git a/src/H5Gobj.c b/src/H5Gobj.c
index 00bac73..af8f6df 100644
--- a/src/H5Gobj.c
+++ b/src/H5Gobj.c
@@ -533,7 +533,6 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk,
H5O_linfo_t new_linfo = H5G_CRT_LINK_INFO_DEF; /* Link information */
H5O_ginfo_t new_ginfo = H5G_CRT_GROUP_INFO_DEF; /* Group information */
H5G_obj_stab_it_ud1_t udata; /* User data for iteration */
- H5G_link_iterate_t lnk_op; /* Link operator */
/* Convert group to "new format" group, in order to hold the information */
@@ -549,12 +548,8 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk,
udata.grp_oloc = grp_oloc;
udata.dxpl_id = dxpl_id;
- /* Build iterator operator */
- lnk_op.op_type = H5G_LINK_OP_LIB;
- lnk_op.u.lib_op = H5G_obj_stab_to_new_cb;
-
/* Iterate through all links in "old format" group and insert them into new format */
- if(H5G_stab_iterate(grp_oloc, dxpl_id, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0)
+ if(H5G_stab_iterate(grp_oloc, dxpl_id, H5_ITER_NATIVE, (hsize_t)0, NULL, H5G_obj_stab_to_new_cb, &udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over old format links")
/* Remove the symbol table message from the group */
@@ -636,36 +631,21 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5G_obj_iterate(hid_t loc_id, const char *group_name,
+H5G_obj_iterate(const H5O_loc_t *grp_oloc,
H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
- H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id)
+ H5G_lib_iterate_t op, void *op_data, hid_t dxpl_id)
{
- H5G_loc_t loc; /* Location of parent for group */
H5O_linfo_t linfo; /* Link info message */
- hid_t gid = -1; /* ID of group to iterate over */
- H5G_t *grp; /* Pointer to group data structure to iterate over */
herr_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_iterate, FAIL)
/* Sanity check */
- HDassert(group_name);
- HDassert(last_lnk);
- HDassert(lnk_op && lnk_op->u.lib_op);
-
- /*
- * Open the group on which to operate. We also create a group ID which
- * we can pass to the application-defined operator.
- */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(NULL == (grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id)))
- HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- if((gid = H5I_register(H5I_GROUP, grp)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
+ HDassert(grp_oloc);
+ HDassert(op);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) {
+ if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) {
/* Check for going out of bounds */
if(skip > 0 && (size_t)skip >= linfo.nlinks)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound")
@@ -679,13 +659,13 @@ H5G_obj_iterate(hid_t loc_id, const char *group_name,
if(H5F_addr_defined(linfo.fheap_addr)) {
/* Iterate over the links in the group, building a table of the link messages */
- if((ret_value = H5G_dense_iterate(grp->oloc.file, dxpl_id, &linfo, idx_type, order, skip, last_lnk, gid, lnk_op, op_data)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links")
+ if((ret_value = H5G_dense_iterate(grp_oloc->file, dxpl_id, &linfo, idx_type, order, skip, last_lnk, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over dense links")
} /* end if */
else {
/* Get the object's name from the link messages */
- if((ret_value = H5G_compact_iterate(&(grp->oloc), dxpl_id, &linfo, idx_type, order, skip, last_lnk, gid, lnk_op, op_data)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over links")
+ if((ret_value = H5G_compact_iterate(grp_oloc, dxpl_id, &linfo, idx_type, order, skip, last_lnk, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over compact links")
} /* end else */
} /* end if */
else {
@@ -697,14 +677,11 @@ H5G_obj_iterate(hid_t loc_id, const char *group_name,
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query")
/* Iterate over symbol table */
- if((ret_value = H5G_stab_iterate(&(grp->oloc), dxpl_id, order, skip, last_lnk, gid, lnk_op, op_data)) < 0)
+ if((ret_value = H5G_stab_iterate(grp_oloc, dxpl_id, order, skip, last_lnk, op, op_data)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over symbol table")
} /* end else */
done:
- if(gid > 0)
- H5I_dec_ref(gid); /*also closes 'grp'*/
-
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_obj_iterate() */
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index f5b2582..2d936a9 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -134,18 +134,16 @@ typedef herr_t (*H5G_lib_iterate_t)(const H5O_link_t *lnk, void *op_data);
typedef struct {
enum {
#ifndef H5_NO_DEPRECATED_SYMBOLS
- H5G_LINK_OP_OLD, /* Old application callback */
+ H5G_LINK_OP_OLD, /* "Old" application callback */
#endif /* H5_NO_DEPRECATED_SYMBOLS */
- H5G_LINK_OP_APP, /* Application callback */
- H5G_LINK_OP_LIB /* Library internal callback */
+ H5G_LINK_OP_NEW /* "New" application callback */
} op_type;
union {
#ifndef H5_NO_DEPRECATED_SYMBOLS
- H5G_iterate_t old_op; /* Old application callback for each link */
+ H5G_iterate_t op_old; /* "Old" application callback for each link */
#endif /* H5_NO_DEPRECATED_SYMBOLS */
- H5L_iterate_t app_op; /* Application callback for each link */
- H5G_lib_iterate_t lib_op; /* Library internal callback for each link */
- } u;
+ H5L_iterate_t op_new; /* "New" application callback for each link */
+ } op_func;
} H5G_link_iterate_t;
/* Data structure to hold table of links for a group */
@@ -210,10 +208,9 @@ typedef struct H5G_bt_lkp_t {
*/
typedef struct H5G_bt_it_it_t {
/* downward */
- hid_t group_id; /*group id to pass to iteration operator */
H5HL_t *heap; /*symbol table heap */
hsize_t skip; /*initial entries to skip */
- H5G_link_iterate_t *lnk_op; /*iteration operator */
+ H5G_lib_iterate_t op; /*iteration operator */
void *op_data; /*user-defined operator data */
/* upward */
@@ -342,6 +339,12 @@ H5_DLL H5G_t *H5G_create_named(const H5G_loc_t *loc, const char *name,
hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id);
H5_DLL H5G_t *H5G_open_name(const H5G_loc_t *loc, const char *name,
hid_t gapl_id, hid_t dxpl_id);
+H5_DLL herr_t H5G_iterate(hid_t loc_id, const char *group_name,
+ H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
+ const H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id);
+H5_DLL herr_t H5G_visit(hid_t loc_id, const char *group_name,
+ H5_index_t idx_type, H5_iter_order_t order, H5L_iterate_t op, void *op_data,
+ hid_t lapl_id, hid_t dxpl_id);
/*
* Group hierarchy traversal routines
@@ -374,9 +377,8 @@ H5_DLL herr_t H5G_stab_insert(const H5O_loc_t *grp_oloc, const char *name,
H5_DLL herr_t H5G_stab_insert_real(H5F_t *f, H5O_stab_t *stab, const char *name,
H5O_link_t *obj_lnk, hid_t dxpl_id);
H5_DLL herr_t H5G_stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab);
-H5_DLL herr_t H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id,
- H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, hid_t gid,
- H5G_link_iterate_t *lnk_op, void *op_data);
+H5_DLL herr_t H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
+ hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data);
H5_DLL herr_t H5G_stab_count(struct H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id);
H5_DLL herr_t H5G_stab_bh_size(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab,
H5_ih_info_t *bh_info);
@@ -444,8 +446,7 @@ H5_DLL herr_t H5G_link_copy_file(H5F_t *dst_file, hid_t dxpl_id,
H5_DLL herr_t H5G_link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type,
H5_iter_order_t order);
H5_DLL herr_t H5G_link_iterate_table(const H5G_link_table_t *ltable,
- hsize_t skip, hsize_t *last_lnk, hid_t gid, const H5G_link_iterate_t *lnk_op,
- void *op_data);
+ hsize_t skip, hsize_t *last_lnk, const H5G_lib_iterate_t op, void *op_data);
H5_DLL herr_t H5G_link_release_table(H5G_link_table_t *ltable);
H5_DLL herr_t H5G_link_name_replace(H5F_t *file, hid_t dxpl_id,
H5RS_str_t *grp_full_path_r, const H5O_link_t *lnk);
@@ -461,9 +462,9 @@ H5_DLL herr_t H5G_compact_remove(const H5O_loc_t *oloc, hid_t dxpl_id,
H5_DLL herr_t H5G_compact_remove_by_idx(const H5O_loc_t *oloc, hid_t dxpl_id,
const H5O_linfo_t *linfo, H5RS_str_t *grp_full_path_r, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n);
-H5_DLL herr_t H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo,
- H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
- hid_t gid, H5G_link_iterate_t *lnk_op, void *op_data);
+H5_DLL herr_t H5G_compact_iterate(const H5O_loc_t *oloc, hid_t dxpl_id,
+ const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order,
+ hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data);
H5_DLL herr_t H5G_compact_lookup(H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *lnk, hid_t dxpl_id);
H5_DLL herr_t H5G_compact_lookup_by_idx(H5O_loc_t *oloc, hid_t dxpl_id,
@@ -487,7 +488,7 @@ H5_DLL herr_t H5G_dense_lookup_by_idx(H5F_t *f, hid_t dxpl_id,
hsize_t n, H5O_link_t *lnk);
H5_DLL herr_t H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
- hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data);
+ H5G_lib_iterate_t op, void *op_data);
H5_DLL ssize_t H5G_dense_get_name_by_idx(H5F_t *f, hid_t dxpl_id,
H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
char *name, size_t size);
@@ -510,9 +511,9 @@ H5_DLL H5O_linfo_t * H5G_obj_get_linfo(const H5O_loc_t *grp_oloc,
H5O_linfo_t *linfo, hid_t dxpl_id);
H5_DLL herr_t H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *obj_lnk, hbool_t adj_link, hid_t dxpl_id);
-H5_DLL herr_t H5G_obj_iterate(hid_t loc_id, const char *group_name,
- H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_obj,
- H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id);
+H5_DLL herr_t H5G_obj_iterate(const H5O_loc_t *grp_oloc,
+ H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
+ H5G_lib_iterate_t op, void *op_data, hid_t dxpl_id);
H5_DLL herr_t H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id);
H5_DLL ssize_t H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, char* name, size_t size, hid_t dxpl_id);
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 9717b77..0ddb3e9 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -189,7 +189,7 @@ H5_DLL herr_t H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5_copy_dept
H5_DLL herr_t H5G_name_free(H5G_name_t *name);
H5_DLL ssize_t H5G_get_name(hid_t id, char *name/*out*/, size_t size,
hid_t lapl_id, hid_t dxpl_id);
-H5_DLL ssize_t H5G_get_refobj_name(hid_t fid, hid_t lapl_id, hid_t dxpl_id,
+H5_DLL ssize_t H5G_get_name_by_addr(hid_t fid, hid_t lapl_id, hid_t dxpl_id,
const struct H5O_loc_t *loc, char* name, size_t size);
/*
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index 1887943..61af068 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -484,8 +484,7 @@ done:
*/
herr_t
H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
- hsize_t skip, hsize_t *last_lnk, hid_t gid,
- H5G_link_iterate_t *lnk_op, void *op_data)
+ hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data)
{
H5HL_t *heap = NULL; /* Local heap for group */
H5O_stab_t stab; /* Info about symbol table */
@@ -496,7 +495,7 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
/* Sanity check */
HDassert(oloc);
- HDassert(lnk_op && lnk_op->u.app_op);
+ HDassert(op);
/* Get the B-tree info */
if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id))
@@ -512,11 +511,10 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
H5G_bt_it_it_t udata; /* User data to pass to B-tree callback */
/* Build udata to pass through H5B_iterate() to H5G_node_iterate() */
- udata.group_id = gid;
udata.heap = heap;
udata.skip = skip;
udata.final_ent = last_lnk;
- udata.lnk_op = lnk_op;
+ udata.op = op;
udata.op_data = op_data;
/* Iterate over the group members */
@@ -550,7 +548,7 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
HGOTO_ERROR(H5E_SYM, H5E_CANTSORT, FAIL, "error sorting link messages")
/* Iterate over links in table */
- if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, gid, lnk_op, op_data)) < 0)
+ if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, op, op_data)) < 0)
HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
} /* end else */
diff --git a/src/H5L.c b/src/H5L.c
index 020f7c2..9917fe7 100644
--- a/src/H5L.c
+++ b/src/H5L.c
@@ -1170,11 +1170,11 @@ H5Literate(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order,
last_lnk = 0;
/* Build link operator info */
- lnk_op.op_type = H5G_LINK_OP_APP;
- lnk_op.u.app_op = op;
+ lnk_op.op_type = H5G_LINK_OP_NEW;
+ lnk_op.op_func.op_new = op;
/* Iterate over the links */
- if((ret_value = H5G_obj_iterate(grp_id, ".", idx_type, order, idx, &last_lnk, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0)
+ if((ret_value = H5G_iterate(grp_id, ".", idx_type, order, idx, &last_lnk, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link iteration failed")
/* Set the index we stopped at */
@@ -1242,11 +1242,11 @@ H5Literate_by_name(hid_t loc_id, const char *group_name,
last_lnk = 0;
/* Build link operator info */
- lnk_op.op_type = H5G_LINK_OP_APP;
- lnk_op.u.app_op = op;
+ lnk_op.op_type = H5G_LINK_OP_NEW;
+ lnk_op.op_func.op_new = op;
/* Iterate over the links */
- if((ret_value = H5G_obj_iterate(loc_id, group_name, idx_type, order, idx, &last_lnk, &lnk_op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0)
+ if((ret_value = H5G_iterate(loc_id, group_name, idx_type, order, idx, &last_lnk, &lnk_op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link iteration failed")
/* Set the index we stopped at */
@@ -1257,6 +1257,66 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Literate_by_name() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Lvisit_by_name
+ *
+ * Purpose: Recursively visit all the links in a group and all
+ * the groups that are linked to from that group. Links within
+ * each group are visited according to the order within the
+ * specified index (unless the specified index does not exist for
+ * a particular group, then the "name" index is used).
+ *
+ * NOTE: Each _link_ reachable from the initial group will only be
+ * visited once. However, because an object may be reached from
+ * more than one link, the visitation may call the application's
+ * callback with more than one link that points to a particular
+ * _object_.
+ *
+ * Return: Success: The return value of the first operator that
+ * returns non-zero, or zero if all members were
+ * processed with no operator returning non-zero.
+ *
+ * Failure: Negative if something goes wrong within the
+ * library, or the negative value returned by one
+ * of the operators.
+ *
+ * Programmer: Quincey Koziol
+ * November 3 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Lvisit_by_name(hid_t loc_id, const char *group_name, H5_index_t idx_type,
+ H5_iter_order_t order, H5L_iterate_t op, void *op_data, hid_t lapl_id)
+{
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5Lvisit_by_name, FAIL)
+
+ /* Check args */
+ if(!group_name || !*group_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
+ if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_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(!op)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator 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")
+
+ /* Call internal group visitation routine */
+ if((ret_value = H5G_visit(loc_id, group_name, idx_type, order, op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link visitation failed")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Lvisit_by_name() */
+
/*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h
index 1645e4b..0dc3f65 100644
--- a/src/H5Lpublic.h
+++ b/src/H5Lpublic.h
@@ -170,6 +170,9 @@ H5_DLL herr_t H5Literate(hid_t grp_id, H5_index_t idx_type,
H5_DLL herr_t H5Literate_by_name(hid_t loc_id, const char *group_name,
H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx,
H5L_iterate_t op, void *op_data, hid_t lapl_id);
+H5_DLL herr_t H5Lvisit_by_name(hid_t loc_id, const char *group_name,
+ H5_index_t idx_type, H5_iter_order_t order, H5L_iterate_t op,
+ void *op_data, hid_t lapl_id);
/* UD link functions */
H5_DLL herr_t H5Lcreate_ud(hid_t link_loc_id, const char *link_name,
diff --git a/src/H5O.c b/src/H5O.c
index 94435f5..67aa960 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -2121,8 +2121,7 @@ H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *o
HDmemset(oinfo, 0, sizeof(*oinfo));
/* Retrieve the file's fileno */
- if(H5F_get_fileno(oloc->file, &oinfo->fileno) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to read fileno")
+ H5F_GET_FILENO(oloc->file, oinfo->fileno);
/* Set the object's address */
oinfo->addr = oloc->addr;
@@ -2412,3 +2411,48 @@ H5O_get_oh_addr(const H5O_t *oh)
FUNC_LEAVE_NOAPI(oh->chunk[0].addr)
} /* end H5O_get_oh_addr() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_get_rc_and_type
+ *
+ * Purpose: Retrieve an object's reference count and type
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * November 4 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype)
+{
+ H5O_t *oh = NULL; /* Object header */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_get_rc_and_type, FAIL)
+
+ /* Check args */
+ HDassert(oloc);
+ HDassert(rc);
+ HDassert(otype);
+
+ /* Get the object header */
+ if(NULL == (oh = H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+
+ /* Set the object's reference count */
+ *rc = oh->nlink;
+
+ /* Retrieve the type of the object */
+ if(H5O_obj_type_real(oh, otype) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
+
+done:
+ if(oh && H5AC_unprotect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_get_rc_and_type() */
+
diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c
index 660b0e1..384353c 100644
--- a/src/H5Olinfo.c
+++ b/src/H5Olinfo.c
@@ -513,7 +513,6 @@ H5O_linfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
/* Check for copying dense link storage */
if(H5F_addr_defined(linfo_src->fheap_addr)) {
H5O_linfo_postcopy_ud_t udata; /* User data for iteration callback */
- H5G_link_iterate_t lnk_op; /* Link operator */
/* Set up dense link iteration user data */
udata.src_oloc = src_oloc;
@@ -522,12 +521,8 @@ H5O_linfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
udata.dxpl_id = dxpl_id;
udata.cpy_info = cpy_info;
- /* Build iterator operator */
- lnk_op.op_type = H5G_LINK_OP_LIB;
- lnk_op.u.lib_op = H5O_linfo_post_copy_file_cb;
-
/* Iterate over the links in the group, building a table of the link messages */
- if(H5G_dense_iterate(src_oloc->file, dxpl_id, linfo_src, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0)
+ if(H5G_dense_iterate(src_oloc->file, dxpl_id, linfo_src, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, H5O_linfo_post_copy_file_cb, &udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links")
} /* end if */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 31738a9..ce7aba0 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -553,6 +553,7 @@ H5_DLL hid_t H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id);
H5_DLL herr_t H5O_get_nlinks(const H5O_loc_t *loc, hid_t dxpl_id, hsize_t *nlinks);
H5_DLL void *H5O_obj_create(H5F_t *f, H5O_type_t obj_type, void *crt_info, H5G_loc_t *obj_loc, hid_t dxpl_id);
H5_DLL haddr_t H5O_get_oh_addr(const H5O_t *oh);
+H5_DLL herr_t H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype);
/* Object header message routines */
H5_DLL herr_t H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
diff --git a/src/H5R.c b/src/H5R.c
index 627626b..ae8720e 100644
--- a/src/H5R.c
+++ b/src/H5R.c
@@ -885,7 +885,7 @@ H5R_get_name(H5F_t *f, hid_t lapl_id, hid_t dxpl_id, hid_t id, H5R_type_t ref_ty
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't retrieve file ID")
/* Get name, length, etc. */
- if((ret_value = H5G_get_refobj_name(file_id, lapl_id, dxpl_id, &oloc, name, size)) < 0)
+ if((ret_value = H5G_get_name_by_addr(file_id, lapl_id, dxpl_id, &oloc, name, size)) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't determine name")
done:
diff --git a/src/H5SL.c b/src/H5SL.c
index 53c0f2d..94f0d23 100644
--- a/src/H5SL.c
+++ b/src/H5SL.c
@@ -99,19 +99,27 @@
/* Define a code template for comparing scalar keys for the "CMP" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_SCALAR_CMP(TYPE,PKEY1,PKEY2) \
- (*(TYPE *)PKEY1<*(TYPE *)PKEY2)
+ (*(TYPE *)PKEY1 < *(TYPE *)PKEY2)
/* Define a code template for comparing string keys for the "CMP" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_STRING_CMP(TYPE,PKEY1,PKEY2) \
- (HDstrcmp(PKEY1,PKEY2)<0)
+ (HDstrcmp(PKEY1, PKEY2) < 0)
+
+/* Define a code template for comparing H5_obj_t keys for the "CMP" in the H5SL_LOCATE macro */
+#define H5SL_LOCATE_OBJ_CMP(TYPE,PKEY1,PKEY2) \
+ ((((TYPE *)PKEY1)->fileno < ((TYPE *)PKEY2)->fileno) ? TRUE : (((TYPE *)PKEY1)->addr < ((TYPE *)PKEY2)->addr))
/* Define a code template for comparing scalar keys for the "EQ" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_SCALAR_EQ(TYPE,PKEY1,PKEY2) \
- (*(TYPE *)PKEY1==*(TYPE *)PKEY2)
+ (*(TYPE *)PKEY1 == *(TYPE *)PKEY2)
/* Define a code template for comparing string keys for the "EQ" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_STRING_EQ(TYPE,PKEY1,PKEY2) \
- (HDstrcmp(PKEY1,PKEY2)==0)
+ (HDstrcmp(PKEY1, PKEY2) == 0)
+
+/* Define a code template for comparing H5_obj_ keys for the "EQ" in the H5SL_LOCATE macro */
+#define H5SL_LOCATE_OBJ_EQ(TYPE,PKEY1,PKEY2) \
+ ((((TYPE *)PKEY1)->fileno == ((TYPE *)PKEY2)->fileno) && (((TYPE *)PKEY1)->addr == ((TYPE *)PKEY2)->addr))
/* Macro used to find node for operation */
#define H5SL_LOCATE(OP,DOUPDATE,CMP,SLIST,X,UPDATE,I,TYPE,KEY,CHECKED) \
@@ -378,6 +386,10 @@ H5SL_insert_common(H5SL_t *slist, void *item, const void *key)
case H5SL_TYPE_SIZE:
H5SL_INSERT(SCALAR, slist, x, update, i, const size_t, key, checked)
break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_INSERT(OBJ, slist, x, update, i, const H5_obj_t, key, checked)
+ break;
} /* end switch */
/* 'key' must not have been found in existing list, if we get here */
@@ -571,7 +583,7 @@ H5SL_create(H5SL_type_t type, double p, size_t max_level)
/* Check args */
HDassert(p>0.0 && p<1.0);
HDassert(max_level>0 && max_level<=H5SL_LEVEL_MAX);
- HDassert(type>=H5SL_TYPE_INT && type<=H5SL_TYPE_SIZE);
+ HDassert(type>=H5SL_TYPE_INT && type<=H5SL_TYPE_OBJ);
/* Allocate skip list structure */
if((new_slist=H5FL_MALLOC(H5SL_t))==NULL)
@@ -808,6 +820,10 @@ H5SL_remove(H5SL_t *slist, const void *key)
case H5SL_TYPE_SIZE:
H5SL_REMOVE(SCALAR, slist, x, update, i, const size_t, key, checked)
break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_REMOVE(OBJ, slist, x, update, i, const H5_obj_t, key, checked)
+ break;
} /* end switch */
done:
@@ -955,6 +971,10 @@ H5SL_search(H5SL_t *slist, const void *key)
case H5SL_TYPE_SIZE:
H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked)
break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_SEARCH(OBJ, slist, x, -, i, const H5_obj_t, key, checked)
+ break;
} /* end switch */
/* 'key' must not have been found in list, if we get here */
@@ -1034,6 +1054,10 @@ H5SL_less(H5SL_t *slist, const void *key)
case H5SL_TYPE_SIZE:
H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked)
break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_SEARCH(OBJ, slist, x, -, i, const H5_obj_t, key, checked)
+ break;
} /* end switch */
/* An exact match for 'key' must not have been found in list, if we get here */
@@ -1126,6 +1150,10 @@ H5SL_greater(H5SL_t *slist, const void *key)
case H5SL_TYPE_SIZE:
H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked)
break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_SEARCH(OBJ, slist, x, -, i, const H5_obj_t, key, checked)
+ break;
} /* end switch */
/* An exact match for 'key' must not have been found in list, if we get here */
@@ -1208,6 +1236,10 @@ H5SL_find(H5SL_t *slist, const void *key)
case H5SL_TYPE_SIZE:
H5SL_FIND(SCALAR, slist, x, -, i, const size_t, key, checked)
break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_FIND(OBJ, slist, x, -, i, const H5_obj_t, key, checked)
+ break;
} /* end switch */
/* 'key' must not have been found in list, if we get here */
diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h
index 98c1b84..9f73893 100644
--- a/src/H5SLprivate.h
+++ b/src/H5SLprivate.h
@@ -46,7 +46,8 @@ typedef enum {
H5SL_TYPE_STR, /* Skip list keys are 'char *'s (ie. strings) */
H5SL_TYPE_HSIZE, /* Skip list keys are 'hsize_t's */
H5SL_TYPE_UNSIGNED, /* Skip list keys are 'unsigned's */
- H5SL_TYPE_SIZE /* Skip list keys are 'size_t's */
+ H5SL_TYPE_SIZE, /* Skip list keys are 'size_t's */
+ H5SL_TYPE_OBJ /* Skip list keys are 'H5_obj_t's */
} H5SL_type_t;
/**********/
diff --git a/src/H5private.h b/src/H5private.h
index dad4e13..3ac4da3 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -485,6 +485,12 @@ typedef enum {
H5_COPY_DEEP /* Deep copy from source to destination, including duplicating fields pointed to */
} H5_copy_depth_t;
+/* Unique object "position" */
+typedef struct {
+ unsigned long fileno; /* The unique identifier for the file of the object */
+ haddr_t addr; /* The unique address of the object's header in that file */
+} H5_obj_t;
+
/*
* Redefine all the POSIX functions. We should never see a POSIX
* function (or any other non-HDF5 function) in the source!
diff --git a/test/getname.c b/test/getname.c
index 685bfbf..22abb79 100644
--- a/test/getname.c
+++ b/test/getname.c
@@ -65,11 +65,11 @@ check_name(hid_t id, const char *chk_name, const char *chk_user_path)
/* Get name */
*name = '\0';
- if(H5Iget_name(id, name, NAME_BUF_SIZE) < 0) goto error;
+ if(H5Iget_name(id, name, NAME_BUF_SIZE) < 0) TEST_ERROR
/* Get user path */
*user_path = '\0';
- if(H5G_user_path_test(id, user_path, &user_path_len, &user_path_hidden) < 0) goto error;
+ if(H5G_user_path_test(id, user_path, &user_path_len, &user_path_hidden) < 0) TEST_ERROR
/* Check on name from H5Iget_name() */
if(HDstrcmp(name, chk_name)) goto error;
@@ -78,7 +78,7 @@ check_name(hid_t id, const char *chk_name, const char *chk_user_path)
if(HDstrcmp(user_path, chk_user_path)) goto error;
/* Check that if user path is hidden, the name from H5Iget_name() and the user path should be different */
- if(user_path_hidden && !HDstrcmp(chk_name, chk_user_path)) goto error;
+ if(user_path_hidden && !HDstrcmp(chk_name, chk_user_path)) TEST_ERROR
/* Everything matches */
return 0;
@@ -713,10 +713,10 @@ test_main(hid_t file_id, hid_t fapl)
PASSED();
-/*-------------------------------------------------------------------------
- * Test H5Iget_name with H5Fmount; long name
- *-------------------------------------------------------------------------
- */
+ /*-------------------------------------------------------------------------
+ * Test H5Iget_name with H5Fmount; long name
+ *-------------------------------------------------------------------------
+ */
TESTING("H5Iget_name with H5Fmount; long name");
@@ -726,9 +726,9 @@ test_main(hid_t file_id, hid_t fapl)
if((group3_id = H5Gcreate2(file_id, "/g13/g1/g2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* Close */
- H5Gclose(group_id);
- H5Gclose(group2_id);
- H5Gclose(group3_id);
+ if(H5Gclose(group_id) < 0) FAIL_STACK_ERROR
+ if(H5Gclose(group2_id) < 0) FAIL_STACK_ERROR
+ if(H5Gclose(group3_id) < 0) FAIL_STACK_ERROR
/* Create second file and group "g" in it */
file1_id = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
@@ -1144,6 +1144,7 @@ test_main(hid_t file_id, hid_t fapl)
char name2[SMALL_NAME_BUF_SIZE];
/* Get name */
+ *name2 = '\0';
name_len=H5Iget_name(group_id, name2, SMALL_NAME_BUF_SIZE);
/* Check that name is longer */
@@ -1182,6 +1183,7 @@ test_main(hid_t file_id, hid_t fapl)
if(!name3) TEST_ERROR
/* Get name with dynamic buffer */
+ *name3 = '\0';
if(H5Iget_name(group_id, name3, name_len + 1) < 0) TEST_ERROR
/* Verify */
@@ -1189,6 +1191,7 @@ test_main(hid_t file_id, hid_t fapl)
*name3 = '\0';
/* Get name with smaller buffer */
+ *name3 = '\0';
if(H5Iget_name(group_id, name3, 3) < 0) TEST_ERROR
/* Verify */
@@ -2513,80 +2516,96 @@ test_obj_ref(hid_t fapl)
TESTING("getting path to normal dataset in root group");
if((dataset2 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[0])) < 0) FAIL_STACK_ERROR
- i = H5Iget_name(dataset2,(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Iget_name(dataset2, (char*)buf, sizeof(buf));
if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR
if(!((HDstrcmp(buf, "/Dataset3") == 0) &&(i == 9))) TEST_ERROR
- i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[0],(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[0], (char*)buf, sizeof(buf));
if(!((HDstrcmp(buf, "/Dataset3") == 0) &&(i == 9))) TEST_ERROR
PASSED()
HDmemset(buf, 0, sizeof(buf));
TESTING("getting path to dataset in /Group1");
if((dataset2 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[1])) < 0) FAIL_STACK_ERROR
- i = H5Iget_name(dataset2,(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Iget_name(dataset2, (char*)buf, sizeof(buf));
if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR
if(!((HDstrcmp(buf, "/Group1/Dataset2") == 0) &&(i == 16))) TEST_ERROR
- i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[1],(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[1], (char*)buf, sizeof(buf));
if(!((HDstrcmp(buf, "/Group1/Dataset2") == 0) &&(i == 16))) TEST_ERROR
PASSED()
HDmemset(buf, 0, sizeof(buf));
TESTING("getting path to /Group1");
if((group = H5Rdereference(dataset, H5R_OBJECT, &wbuf[2])) < 0) FAIL_STACK_ERROR
- i = H5Iget_name(group,(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Iget_name(group, (char*)buf, sizeof(buf));
if(H5Gclose(group) < 0) FAIL_STACK_ERROR
if(!((HDstrcmp(buf, "/Group1") == 0) &&(i == 7))) TEST_ERROR
- i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[2],(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[2], (char*)buf, sizeof(buf));
if(!((HDstrcmp(buf, "/Group1") == 0) &&(i == 7))) TEST_ERROR
PASSED()
HDmemset(buf, 0, sizeof(buf));
TESTING("getting path to datatype in /Group1");
if((tid1 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[3])) < 0) FAIL_STACK_ERROR
- i = H5Iget_name(tid1,(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Iget_name(tid1, (char*)buf, sizeof(buf));
if(H5Tclose(tid1) < 0) FAIL_STACK_ERROR
if(!((HDstrcmp(buf, "/Group1/Datatype1") == 0) &&(i == 17))) TEST_ERROR
- i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[3],(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[3], (char*)buf, sizeof(buf));
if(!((HDstrcmp(buf, "/Group1/Datatype1") == 0) &&(i == 17))) TEST_ERROR
PASSED()
HDmemset(buf, 0, sizeof(buf));
TESTING("getting path to dataset in nested group");
if((dataset2 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[4])) < 0) FAIL_STACK_ERROR
- i = H5Iget_name(dataset2,(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Iget_name(dataset2, (char*)buf, sizeof(buf));
if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR
if(!((HDstrcmp(buf, "/Group1/Group2/Dataset4") == 0) &&(i == 23))) TEST_ERROR
- i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[4],(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[4], (char*)buf, sizeof(buf));
if(!((HDstrcmp(buf, "/Group1/Group2/Dataset4") == 0) &&(i == 23))) TEST_ERROR
PASSED()
HDmemset(buf, 0, sizeof(buf));
TESTING("getting path to nested group");
if((group = H5Rdereference(dataset, H5R_OBJECT, &wbuf[5])) < 0) FAIL_STACK_ERROR
- i = H5Iget_name(group,(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Iget_name(group, (char*)buf, sizeof(buf));
if(H5Gclose(group) < 0) FAIL_STACK_ERROR
if(!((HDstrcmp(buf, "/Group1/Group2") == 0) &&(i == 14))) TEST_ERROR
- i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[5],(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[5], (char*)buf, sizeof(buf));
if(!((HDstrcmp(buf, "/Group1/Group2") == 0) &&(i == 14))) TEST_ERROR
PASSED()
HDmemset(buf, 0, sizeof(buf));
TESTING("getting path to dataset created via hard link");
if((dataset2 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[6])) < 0) FAIL_STACK_ERROR
- i = H5Iget_name(dataset2,(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Iget_name(dataset2, (char*)buf, sizeof(buf));
if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR
if(!((HDstrcmp(buf, "/Group1/Dataset5") == 0) &&(i == 16))) TEST_ERROR
- i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[6],(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[6], (char*)buf, sizeof(buf));
if(!((HDstrcmp(buf, "/Group1/Dataset5") == 0) &&(i == 16))) TEST_ERROR
PASSED()
HDmemset(buf, 0, sizeof(buf));
TESTING("getting path to root group");
if((group = H5Rdereference(dataset, H5R_OBJECT, &wbuf[7])) < 0) FAIL_STACK_ERROR
- i = H5Iget_name(group,(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Iget_name(group, (char*)buf, sizeof(buf));
if(H5Gclose(group) < 0) FAIL_STACK_ERROR
if(!((HDstrcmp(buf, "/") == 0) &&(i == 1))) TEST_ERROR
- i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[7],(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[7], (char*)buf, sizeof(buf));
if(!((HDstrcmp(buf, "/") == 0) &&(i == 1))) TEST_ERROR
PASSED()
@@ -2596,10 +2615,12 @@ test_obj_ref(hid_t fapl)
TESTING("getting path to dataset hidden by a mounted file");
if((dataset2 = H5Rdereference(dataset, H5R_OBJECT, &wbuf[4])) < 0) FAIL_STACK_ERROR
+ *buf = '\0';
i = H5Iget_name(dataset2, (char*)buf, sizeof(buf));
if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR
if(i != 0) TEST_ERROR
- i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[4],(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[4], (char*)buf, sizeof(buf));
if(i != 0) TEST_ERROR
PASSED()
@@ -2610,10 +2631,12 @@ test_obj_ref(hid_t fapl)
FAIL_STACK_ERROR
TESTING("getting path to dataset that has been unlinked");
+ *buf = '\0';
i = H5Iget_name(dataset2, (char*)buf, sizeof(buf));
if(H5Dclose(dataset2) < 0) FAIL_STACK_ERROR
if(i != 0) TEST_ERROR
- i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[1],(char*)buf, sizeof(buf));
+ *buf = '\0';
+ i = H5Rget_name(dataset, H5R_OBJECT, &wbuf[1], (char*)buf, sizeof(buf));
if(i != 0) TEST_ERROR
PASSED()
@@ -2735,7 +2758,8 @@ test_reg_ref(hid_t fapl)
/* Get name of the dataset the first region reference points to using H5Rget_name */
TESTING("H5Rget_name to get name from region reference(hyperslab)");
- name_size1 = H5Rget_name(dsetr_id, H5R_DATASET_REGION, &ref_out[0],(char*)buf1, NAME_BUF_SIZE);
+ *buf1 = '\0';
+ name_size1 = H5Rget_name(dsetr_id, H5R_DATASET_REGION, &ref_out[0], (char*)buf1, NAME_BUF_SIZE);
if(!((HDstrcmp(buf1, "/MATRIX") == 0) &&(name_size1 == 7))) TEST_ERROR
PASSED()
@@ -2745,7 +2769,8 @@ test_reg_ref(hid_t fapl)
dsetv_id = H5Rdereference(dsetr_id, H5R_DATASET_REGION, &ref_out[0]);
/* Get name of the dataset the first region reference points using H5Iget_name */
- name_size2 = H5Iget_name(dsetv_id,(char*)buf2, NAME_BUF_SIZE);
+ *buf2 = '\0';
+ name_size2 = H5Iget_name(dsetv_id, (char*)buf2, NAME_BUF_SIZE);
if(!((HDstrcmp(buf2, "/MATRIX") == 0) &&(name_size2 == 7))) TEST_ERROR
if((status = H5Dclose(dsetv_id)) < 0) TEST_ERROR
@@ -2754,7 +2779,8 @@ test_reg_ref(hid_t fapl)
/* Get name of the dataset the second region reference points to using H5Rget_name */
TESTING("H5Rget_name to get name from region reference(pnt selec)");
- name_size1 = H5Rget_name(dsetr_id, H5R_DATASET_REGION, &ref_out[1],(char*)buf1, NAME_BUF_SIZE);
+ *buf1 = '\0';
+ name_size1 = H5Rget_name(dsetr_id, H5R_DATASET_REGION, &ref_out[1], (char*)buf1, NAME_BUF_SIZE);
if(!((HDstrcmp(buf1, "/MATRIX") == 0) &&(name_size1 == 7))) TEST_ERROR
PASSED()
@@ -2764,7 +2790,8 @@ test_reg_ref(hid_t fapl)
if((dsetv_id = H5Rdereference(dsetr_id, H5R_DATASET_REGION, &ref_out[1])) < 0) TEST_ERROR
/* Get name of the dataset the first region reference points using H5Iget_name */
- name_size2 = H5Iget_name(dsetv_id,(char*)buf2, NAME_BUF_SIZE);
+ *buf2 = '\0';
+ name_size2 = H5Iget_name(dsetv_id, (char*)buf2, NAME_BUF_SIZE);
if(!((HDstrcmp(buf2, "/MATRIX") == 0) &&(name_size2 == 7))) TEST_ERROR
if((status = H5Dclose(dsetv_id)) < 0) TEST_ERROR
diff --git a/test/mount.c b/test/mount.c
index 2ce9a2a..e6aa881 100644
--- a/test/mount.c
+++ b/test/mount.c
@@ -1170,6 +1170,7 @@ test_mount_after_close(hid_t fapl)
if((gidABMX = H5Gopen2(gidAB, "M/X", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* Check name */
+ *objname = '\0';
if(H5Iget_name(gidABMX, objname, (size_t)NAME_BUF_SIZE) < 0) FAIL_STACK_ERROR
if(HDstrcmp(objname, "/A/B/M/X")) TEST_ERROR
@@ -1180,6 +1181,7 @@ test_mount_after_close(hid_t fapl)
if((gidABC = H5Gopen2(gidAB, "C", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* Check name */
+ *objname = '\0';
if(H5Iget_name(gidABC, objname, (size_t)NAME_BUF_SIZE) < 0) FAIL_STACK_ERROR
if(HDstrcmp(objname, "/A/B/C")) TEST_ERROR
@@ -1190,6 +1192,7 @@ test_mount_after_close(hid_t fapl)
if((gidABT = H5Gopen2(gidAB, "T", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* Check name */
+ *objname = '\0';
if(H5Iget_name(gidABT, objname, (size_t)NAME_BUF_SIZE) < 0) FAIL_STACK_ERROR
if(HDstrcmp(objname, "/A/B/T")) TEST_ERROR
@@ -1200,6 +1203,7 @@ test_mount_after_close(hid_t fapl)
if((didABMXYD = H5Dopen2(gidAB, "M/X/Y/D", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
/* Check name */
+ *objname = '\0';
if(H5Iget_name(didABMXYD, objname, (size_t)NAME_BUF_SIZE) < 0) FAIL_STACK_ERROR
if(HDstrcmp(objname, "/A/B/M/X/Y/D")) TEST_ERROR
@@ -1370,6 +1374,7 @@ test_mount_after_unmount(hid_t fapl)
TEST_ERROR
/* Check name */
+ *objname = '\0';
if(H5Iget_name( gidAMXX, objname, (size_t)NAME_BUF_SIZE ) < 0)
TEST_ERROR
if(HDstrcmp(objname, "/A/M/X/X"))
@@ -1389,6 +1394,7 @@ test_mount_after_unmount(hid_t fapl)
TEST_ERROR
/* Check name */
+ *objname = '\0';
if(H5Iget_name( gidAMXMY, objname, (size_t)NAME_BUF_SIZE ) < 0)
TEST_ERROR
if(HDstrcmp(objname, "/A/M/X/M/Y"))
@@ -1435,6 +1441,7 @@ test_mount_after_unmount(hid_t fapl)
TEST_ERROR
/* Check name */
+ *objname = '\0';
if(H5Iget_name( gidBMZ, objname, (size_t)NAME_BUF_SIZE ) < 0)
TEST_ERROR
if(HDstrcmp(objname, "/B/M/Z"))
@@ -2721,6 +2728,7 @@ test_mult_mount(hid_t fapl)
TEST_ERROR
/* Check name */
+ *name = '\0';
if(H5Iget_name(gidAMT, name, (size_t)NAME_BUF_SIZE ) < 0)
TEST_ERROR
if(HDstrcmp(name, "/A/M/T"))
@@ -2738,6 +2746,7 @@ test_mult_mount(hid_t fapl)
TEST_ERROR
/* Check name */
+ *name = '\0';
if(H5Iget_name(gidBS, name, (size_t)NAME_BUF_SIZE ) < 0)
TEST_ERROR
if(HDstrcmp(name, "/B/S"))
@@ -2924,6 +2933,7 @@ test_nested_survive(hid_t fapl)
TEST_ERROR
/* Check name */
+ *name = '\0';
if((name_len = H5Iget_name(gidAM, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/A/M"))
@@ -2934,9 +2944,10 @@ test_nested_survive(hid_t fapl)
TEST_ERROR
/* Check name */
+ *name = '\0';
if((name_len = H5Iget_name(gidAM, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
- if(name_len == 0 || HDstrcmp(name, "/M"))
+ if(name_len != 0 || HDstrcmp(name, ""))
TEST_ERROR
/* Open object in file #3 through file #1 mount path (should fail) */
@@ -2951,6 +2962,7 @@ test_nested_survive(hid_t fapl)
TEST_ERROR
/* Check name */
+ *name = '\0';
if(H5Iget_name(gidMS, name, (size_t)NAME_BUF_SIZE ) < 0)
TEST_ERROR
if(HDstrcmp(name, "/M/S"))
@@ -2969,6 +2981,7 @@ test_nested_survive(hid_t fapl)
TEST_ERROR
/* Check name */
+ *name = '\0';
if(H5Iget_name(gidAMS, name, (size_t)NAME_BUF_SIZE ) < 0)
TEST_ERROR
if(HDstrcmp(name, "/A/M/S"))
@@ -3122,6 +3135,7 @@ test_close_parent(hid_t fapl)
TEST_ERROR
/* Check the name of "M" is still defined */
+ *name = '\0';
if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/A/M"))
@@ -3132,6 +3146,7 @@ test_close_parent(hid_t fapl)
TEST_ERROR
/* Check the name of "M" is defined in its file */
+ *name = '\0';
if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/M"))
@@ -3407,6 +3422,7 @@ test_cut_graph(hid_t fapl)
TEST_ERROR
/* Check name */
+ *name = '\0';
if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/A/E/M"))
@@ -3417,6 +3433,7 @@ test_cut_graph(hid_t fapl)
TEST_ERROR
/* Check name */
+ *name = '\0';
if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/B/I/Q"))
@@ -3477,6 +3494,7 @@ test_cut_graph(hid_t fapl)
TEST_ERROR
/* Check the name of "K" is correct */
+ *name = '\0';
if((name_len = H5Iget_name(gidK, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/D/K"))
@@ -3497,6 +3515,7 @@ test_cut_graph(hid_t fapl)
TEST_ERROR
/* Check the name of "O" is correct */
+ *name = '\0';
if((name_len = H5Iget_name(gidO, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/B/H/O"))
@@ -3506,12 +3525,14 @@ test_cut_graph(hid_t fapl)
TEST_ERROR
/* Check the name of "M" is defined in its file */
+ *name = '\0';
if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/E/M"))
TEST_ERROR
/* Check the name of "Q" is still defined */
+ *name = '\0';
if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/B/I/Q"))
@@ -3539,6 +3560,7 @@ test_cut_graph(hid_t fapl)
TEST_ERROR
/* Check the name of "Q" is defined in its file */
+ *name = '\0';
if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/I/Q"))
@@ -3549,6 +3571,7 @@ test_cut_graph(hid_t fapl)
TEST_ERROR
/* Check the name of "O" is correct */
+ *name = '\0';
if((name_len = H5Iget_name(gidO, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/H/O"))
@@ -3719,6 +3742,7 @@ test_symlink(hid_t fapl)
TEST_ERROR
/* Check the name of "L" is correct */
+ *name = '\0';
if((name_len = H5Iget_name(gidL, name, (size_t)NAME_BUF_SIZE )) < 0)
TEST_ERROR
if(name_len == 0 || HDstrcmp(name, "/L"))
diff --git a/tools/h5copy/h5copy.c b/tools/h5copy/h5copy.c
index cadb0d0..216b2bb 100644
--- a/tools/h5copy/h5copy.c
+++ b/tools/h5copy/h5copy.c
@@ -199,8 +199,8 @@ main (int argc, const char *argv[])
unsigned flag=0;
unsigned verbose=0;
unsigned parents=0;
- hid_t ocpl_id; /* Object copy property list */
- hid_t lcpl_id; /* Link creation property list */
+ hid_t ocpl_id = (-1); /* Object copy property list */
+ hid_t lcpl_id = (-1); /* Link creation property list */
char str_flag[20];
int opt;
diff --git a/tools/h5dump/h5dump.c b/tools/h5dump/h5dump.c
index c69c5d70..28534bf 100644
--- a/tools/h5dump/h5dump.c
+++ b/tools/h5dump/h5dump.c
@@ -3952,7 +3952,7 @@ main(int argc, const char *argv[])
/* allocate and initialize internal data structure */
init_prefix(&prefix, prefix_len);
- /* find all objects that might be targets of a reference */
+ /* Prepare to find objects that might be targets of a reference */
fill_ref_path_table(fid);
if(doxml) {
@@ -4094,7 +4094,6 @@ done:
free_table(type_table);
HDfree(prefix);
- HDfree(info.prefix);
HDfree(fname);
/* To Do: clean up XML table */
@@ -5342,8 +5341,7 @@ xml_dump_group(hid_t gid, const char *name)
if(HDstrcmp(name, "/") == 0) {
isRoot = 1;
- tmp = HDmalloc(2);
- HDstrcpy(tmp, "/");
+ tmp = HDstrdup("/");
} else {
tmp = HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2);
HDstrcpy(tmp, prefix);
@@ -5401,8 +5399,8 @@ xml_dump_group(hid_t gid, const char *name)
ptrstr = malloc(100);
t_objname = xml_escape_the_name(found_obj->objname);
par_name = xml_escape_the_name(par);
- xml_name_to_XID(par,parentxid,100,1);
- xml_name_to_XID(found_obj->objname,ptrstr,100,1);
+ xml_name_to_XID(found_obj->objname, ptrstr, 100, 1);
+ xml_name_to_XID(par, parentxid, 100, 1);
printf("<%sGroupPtr OBJ-XID=\"%s\" H5Path=\"%s\" "
"Parents=\"%s\" H5ParentPaths=\"%s\" />\n",
xmlnsprefix,
diff --git a/tools/h5ls/h5ls.c b/tools/h5ls/h5ls.c
index 2c56cb5..80b45d8 100644
--- a/tools/h5ls/h5ls.c
+++ b/tools/h5ls/h5ls.c
@@ -27,6 +27,15 @@
#include "H5private.h"
#include "h5tools.h"
#include "h5tools_utils.h"
+#include "h5trav.h"
+
+#define NAME_BUF_SIZE 2048
+
+/* Struct to pass through to visitors */
+typedef struct {
+ hid_t fid; /* File ID */
+ const char *fname; /* Filename */
+}iter_t;
/* Command-line switches */
static int verbose_g = 0; /* lots of extra output */
@@ -43,21 +52,7 @@ static hbool_t show_errors_g = FALSE; /* print HDF5 error messages */
static hbool_t simple_output_g = FALSE; /* make output more machine-readable */
static hbool_t show_file_name_g = FALSE; /* show file name for full names */
static hbool_t no_line_wrap_g = FALSE; /* show data content without line wrap */
-
-/* Info to pass to the iteration functions */
-typedef struct iter_t {
- const char *container; /* full name of the container object */
-} iter_t;
-
-/* Table containing object id and object name */
-static struct {
- int nalloc; /* number of slots allocated */
- int nobjs; /* number of objects */
- struct {
- haddr_t id; /* object number */
- char *name; /* full object name */
- } *obj;
-} idtab_g;
+static hbool_t display_root_g = FALSE; /* show root group in output? */
/* Information about how to display each type of object */
static struct dispatch_t {
@@ -68,17 +63,13 @@ static struct dispatch_t {
herr_t (*list2)(hid_t obj, const char *name);
} dispatch_g[H5O_TYPE_NTYPES];
-#define DISPATCH(TYPE, NAME, OPEN, CLOSE, LIST1, LIST2) { \
+#define DISPATCH(TYPE, NAME, LIST1, LIST2) { \
dispatch_g[TYPE].name = (NAME); \
- dispatch_g[TYPE].open = (OPEN); \
- dispatch_g[TYPE].close = (CLOSE); \
dispatch_g[TYPE].list1 = (LIST1); \
dispatch_g[TYPE].list2 = (LIST2); \
}
-static herr_t list(hid_t group, const char *name, const H5L_info_t *linfo, void *cd);
static void display_type(hid_t type, int ind);
-static char *fix_name(const char *path, const char *base);
const char *progname="h5ls";
int d_status;
@@ -131,76 +122,6 @@ usage: %s [OPTIONS] [OBJECTS...]\n\
/*-------------------------------------------------------------------------
- * Function: sym_insert
- *
- * Purpose: Add a symbol to the table.
- *
- * Return: void
- *
- * Programmer: Robb Matzke
- * Thursday, January 21, 1999
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static void
-sym_insert(const H5O_info_t *oi, const char *name)
-{
- int n;
-
- /* Don't add it if the link count is 1 because such an object can only
- * have one name. */
- if(oi->rc < 2)
- return;
-
- /* Extend the table */
- if(idtab_g.nobjs >= idtab_g.nalloc) {
- idtab_g.nalloc = MAX(256, 2*idtab_g.nalloc);
- idtab_g.obj = realloc(idtab_g.obj, idtab_g.nalloc*sizeof(idtab_g.obj[0]));
- } /* end if */
-
- /* Insert the entry */
- n = idtab_g.nobjs++;
- idtab_g.obj[n].id = oi->addr;
- idtab_g.obj[n].name = HDstrdup(name);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: sym_lookup
- *
- * Purpose: Find another name for the specified object.
- *
- * Return: Success: Ptr to another name.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Thursday, January 21, 1999
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static char *
-sym_lookup(const H5O_info_t *oi)
-{
- int n;
-
- /*only one name possible*/
- if(oi->rc < 2)
- return NULL;
-
- for(n = 0; n < idtab_g.nobjs; n++)
- if(idtab_g.obj[n].id == oi->addr)
- return idtab_g.obj[n].name;
-
- return NULL;
-}
-
-
-/*-------------------------------------------------------------------------
* Function: display_string
*
* Purpose: Print a string value by escaping unusual characters. If
@@ -278,6 +199,55 @@ display_string(FILE *stream, const char *s, hbool_t escape_spaces)
/*-------------------------------------------------------------------------
+ * Function: display_obj_name
+ *
+ * Purpose: Print an object name and another string.
+ *
+ * Return: Success: TRUE
+ *
+ * Failure: FALSE, nothing printed
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, November 6, 2007
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+display_obj_name(FILE *stream, const iter_t *iter, const char *oname,
+ const char *s)
+{
+ static char fullname[NAME_BUF_SIZE]; /* Buffer for file and/or object name */
+ const char *name = fullname; /* Pointer to buffer for printing */
+ int n;
+
+ if(show_file_name_g)
+ sprintf(fullname, "%s/%s", iter->fname, oname);
+ else
+ name = oname;
+
+ /* Print the object name, either full name or base name */
+ if(fullname_g)
+ n = display_string(stream, name, TRUE);
+ else {
+ const char *last_sep; /* The location of the last group separator */
+
+ /* Find the last component of the path name */
+ if(NULL == (last_sep = HDstrrchr(name, '/')))
+ last_sep = name;
+ else {
+ last_sep++;
+ } /* end else */
+ n = display_string(stream, last_sep, TRUE);
+ } /* end else */
+ printf("%*s ", MAX(0, (24 - n)), s);
+
+ return TRUE;
+}
+
+
+/*-------------------------------------------------------------------------
* Function: display_native_type
*
* Purpose: Prints the name of a native C data type.
@@ -1326,7 +1296,7 @@ list_attr(hid_t obj, const char *attr_name, const H5A_info_t UNUSED *ainfo,
void UNUSED *op_data)
{
hid_t attr, space, type, p_type;
- hsize_t size[64], nelmts = 1;
+ hsize_t size[H5S_MAX_RANK], nelmts = 1;
int ndims, i, n;
size_t need;
hsize_t temp_need;
@@ -1460,8 +1430,8 @@ list_attr(hid_t obj, const char *attr_name, const H5A_info_t UNUSED *ainfo,
static herr_t
dataset_list1(hid_t dset)
{
- hsize_t cur_size[64]; /* current dataset dimensions */
- hsize_t max_size[64]; /* maximum dataset dimensions */
+ hsize_t cur_size[H5S_MAX_RANK]; /* current dataset dimensions */
+ hsize_t max_size[H5S_MAX_RANK]; /* maximum dataset dimensions */
hid_t space; /* data space */
int ndims; /* dimensionality */
H5S_class_t space_type; /* type of dataspace */
@@ -1524,7 +1494,6 @@ dataset_list2(hid_t dset, const char UNUSED *name)
off_t f_offset; /* offset in external file */
hsize_t f_size; /* bytes used in external file */
hsize_t total, used; /* total size or offset */
- hsize_t chsize[64]; /* chunk size in elements */
int ndims; /* dimensionality */
int n, max_len; /* max extern file name length */
double utilization; /* percent utilization of storage */
@@ -1537,6 +1506,8 @@ dataset_list2(hid_t dset, const char UNUSED *name)
/* Print information about chunked storage */
if (H5D_CHUNKED==H5Pget_layout(dcpl)) {
+ hsize_t chsize[64]; /* chunk size in elements */
+
ndims = H5Pget_chunk(dcpl, NELMTS(chsize), chsize/*out*/);
printf(" %-10s {", "Chunks:");
total = H5Tget_size(type);
@@ -1645,39 +1616,9 @@ dataset_list2(hid_t dset, const char UNUSED *name)
/*-------------------------------------------------------------------------
- * Function: group_list2
- *
- * Purpose: List information about a group which should appear after
- * information which is general to all objects.
- *
- * Return: Success: 0
- *
- * Failure: -1
- *
- * Programmer: Robb Matzke
- * Thursday, January 21, 1999
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-group_list2(hid_t grp, const char *name)
-{
- iter_t iter;
-
- if (recursive_g) {
- iter.container = name;
- H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, NULL, list, &iter);
- }
- return 0;
-}
-
-
-/*-------------------------------------------------------------------------
* Function: datatype_list2
*
- * Purpose: List information about a data type which should appear after
+ * Purpose: List information about a datatype which should appear after
* information which is general to all objects.
*
* Return: Success: 0
@@ -1704,80 +1645,56 @@ datatype_list2(hid_t type, const char UNUSED *name)
/*-------------------------------------------------------------------------
- * Function: list
+ * Function: list_obj
*
- * Purpose: Prints the group member name.
+ * Purpose: Prints information about an object
*
* Return: Success: 0
*
* Failure: -1
*
- * Programmer: Robb Matzke
- * Monday, March 23, 1998
+ * Programmer: Quincey Koziol
+ * Tuesday, November 6, 2007
*
- * Modifications:
- * Robb Matzke, LLNL, 2003-06-06
- * If simple_output_g (set by `--simple') is turned on then
- * the modification time is printed as UTC instead of the
- * local timezone.
*-------------------------------------------------------------------------
*/
static herr_t
-list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter)
+list_obj(const char *name, const H5O_info_t *oinfo, const char *first_seen, void *_iter)
{
+ H5O_type_t obj_type = oinfo->type; /* Type of the object */
iter_t *iter = (iter_t*)_iter;
- char *fullname = NULL;
- int n;
- /* Print the object name, either full name or base name */
- fullname = fix_name(iter->container, name);
- if(fullname_g)
- n = display_string(stdout, fullname, TRUE);
- else
- n = display_string(stdout, name, TRUE);
- printf("%*s ", MAX(0, (24 - n)), "");
-
- /* Actions on objects */
- if(linfo->type == H5L_TYPE_HARD) {
- H5O_info_t oi;
- char *s;
- hid_t obj;
-
- /* Get object information */
- if(H5Oget_info_by_name(group, name, &oi, H5P_DEFAULT) < 0) {
- puts("**NOT FOUND**");
- return 0;
- } else if(oi.type < 0 || oi.type >= H5O_TYPE_NTYPES) {
- printf("Unknown type(%d)", (int)oi.type);
- oi.type = H5O_TYPE_UNKNOWN;
- }
- if(oi.type >= 0 && dispatch_g[oi.type].name)
- fputs(dispatch_g[oi.type].name, stdout);
-
- /* If the object has already been printed then just show the object ID
- * and return. */
- if((s = sym_lookup(&oi))) {
- printf(", same as ");
- display_string(stdout, s, TRUE);
- printf("\n");
- goto done;
- } /* end if */
- else
- sym_insert(&oi, fullname);
+ /* Print the link's name, either full name or base name */
+ display_obj_name(stdout, iter, name, "");
+
+ /* Check object information */
+ if(oinfo->type < 0 || oinfo->type >= H5O_TYPE_NTYPES) {
+ printf("Unknown type(%d)", (int)oinfo->type);
+ obj_type = H5O_TYPE_UNKNOWN;
+ }
+ if(obj_type >= 0 && dispatch_g[obj_type].name)
+ fputs(dispatch_g[obj_type].name, stdout);
+
+ /* Check if we've seen this object before */
+ if(first_seen) {
+ printf(", same as ");
+ display_string(stdout, first_seen, TRUE);
+ printf("\n");
+ } /* end if */
+ else {
+ hid_t obj = (-1); /* ID of object opened */
/* Open the object. Not all objects can be opened. If this is the case
* then return right away.
*/
- if(oi.type >= 0 &&
- (NULL == dispatch_g[oi.type].open ||
- (obj = (dispatch_g[oi.type].open)(group, name, H5P_DEFAULT)) < 0)) {
+ if(obj_type >= 0 && (obj = H5Oopen(iter->fid, name, H5P_DEFAULT)) < 0) {
printf(" *ERROR*\n");
goto done;
} /* end if */
/* List the first line of information for the object. */
- if(oi.type >= 0 && dispatch_g[oi.type].list1)
- (dispatch_g[oi.type].list1)(obj);
+ if(obj_type >= 0 && dispatch_g[obj_type].list1)
+ (dispatch_g[obj_type].list1)(obj);
putchar('\n');
/* Show detailed information about the object, beginning with information
@@ -1786,22 +1703,22 @@ list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter)
char comment[50];
/* Display attributes */
- if(oi.type >= 0)
+ if(obj_type >= 0)
H5Aiterate2(obj, H5_INDEX_NAME, H5_ITER_INC, NULL, list_attr, NULL);
/* Object location & reference count */
- printf(" %-10s %lu:"H5_PRINTF_HADDR_FMT"\n", "Location:", oi.fileno, oi.addr);
- printf(" %-10s %u\n", "Links:", (unsigned)oi.rc);
+ printf(" %-10s %lu:"H5_PRINTF_HADDR_FMT"\n", "Location:", oinfo->fileno, oinfo->addr);
+ printf(" %-10s %u\n", "Links:", (unsigned)oinfo->rc);
/* Modification time */
- if(oi.mtime > 0) {
+ if(oinfo->mtime > 0) {
char buf[256];
struct tm *tm;
if(simple_output_g)
- tm = HDgmtime(&(oi.mtime));
+ tm = HDgmtime(&(oinfo->mtime));
else
- tm = HDlocaltime(&(oi.mtime));
+ tm = HDlocaltime(&(oinfo->mtime));
if(tm) {
HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
printf(" %-10s %s\n", "Modified:", buf);
@@ -1810,7 +1727,7 @@ list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter)
/* Object comment */
comment[0] = '\0';
- H5Oget_comment_by_name(group, name, comment, sizeof(comment), H5P_DEFAULT);
+ H5Oget_comment(obj, comment, sizeof(comment));
HDstrcpy(comment + sizeof(comment) - 4, "...");
if(comment[0]) {
printf(" %-10s \"", "Comment:");
@@ -1820,118 +1737,91 @@ list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter)
} /* end if */
/* Detailed list for object */
- if(oi.type >= 0 && dispatch_g[oi.type].list2)
- (dispatch_g[oi.type].list2)(obj, fullname);
+ if(obj_type >= 0 && dispatch_g[obj_type].list2)
+ (dispatch_g[obj_type].list2)(obj, name);
/* Close the object. */
- if(oi.type >= 0 && dispatch_g[oi.type].close)
- (dispatch_g[oi.type].close)(obj);
- } /* end if */
- /* Actions on links */
- else {
- char *buf;
-
- HDfputs("-> ", stdout);
- switch(linfo->type) {
- case H5L_TYPE_SOFT:
- if((buf = HDmalloc(linfo->u.val_size)) == NULL)
- goto done;
-
- if(H5Lget_val(group, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) {
- HDfree(buf);
- goto done;
- } /* end if */
-
- HDfputs(buf, stdout);
- HDfree(buf);
- break;
-
- case H5L_TYPE_EXTERNAL:
- {
- const char *filename;
- const char *path;
-
- if((buf = HDmalloc(linfo->u.val_size)) == NULL)
- goto done;
-
- if(H5Lget_val(group, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) {
- HDfree(buf);
- goto done;
- } /* end if */
- if(H5Lunpack_elink_val(buf, linfo->u.val_size, NULL, &filename, &path) < 0) {
- HDfree(buf);
- goto done;
- } /* end if */
-
- HDfputs("file: ", stdout);
- HDfputs(filename, stdout);
- HDfputs(" path: ", stdout);
- HDfputs(path, stdout);
- }
- break;
-
- default:
- HDfputs("cannot follow UD links", stdout);
- break;
- } /* end switch */
- HDfputc('\n', stdout);
+ if(obj_type >= 0)
+ H5Oclose(obj);
} /* end else */
done:
- if(fullname)
- free(fullname);
return 0;
-} /* end list() */
+} /* end list_obj() */
/*-------------------------------------------------------------------------
- * Function: fix_name
+ * Function: list_lnk
*
- * Purpose: Returns a malloc'd buffer that contains the PATH and BASE
- * names separated by a single slash. It also removes duplicate
- * and trailing slashes.
+ * Purpose: Prints information about a link
*
- * Return: Success: Ptr to fixed name from malloc()
- *
- * Failure: NULL
+ * Return: Success: 0
*
- * Programmer: Robb Matzke
- * Thursday, January 21, 1999
+ * Failure: -1
*
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Thursday, November 8, 2007
*
*-------------------------------------------------------------------------
*/
-static char *
-fix_name(const char *path, const char *base)
+static herr_t
+list_lnk(const char *name, const H5L_info_t *linfo, void *_iter)
{
- size_t n = (path ? HDstrlen(path) : 0) + (base ? HDstrlen(base) : 0) + 3;
- char *s = HDmalloc(n), prev='\0';
- size_t len = 0;
-
- if (path) {
- /* Path, followed by slash */
- for (/*void*/; *path; path++)
- if ('/'!=*path || '/'!=prev)
- prev = s[len++] = *path;
- if ('/' != prev)
- prev = s[len++] = '/';
- }
+ char *buf;
+ iter_t *iter = (iter_t*)_iter;
- if (base) {
- /* Base name w/o trailing slashes */
- const char *end = base + HDstrlen(base);
- while (end > base && '/' == end[-1])
- --end;
+ /* Print the link's name, either full name or base name */
+ display_obj_name(stdout, iter, name, "");
- for (/*void*/; base < end; base++)
- if ('/' != *base || '/' != prev)
- prev = s[len++] = *base;
- }
+ HDfputs("-> ", stdout);
+ switch(linfo->type) {
+ case H5L_TYPE_SOFT:
+ if((buf = HDmalloc(linfo->u.val_size)) == NULL)
+ goto done;
- s[len] = '\0';
- return s;
-}
+ if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) {
+ HDfree(buf);
+ goto done;
+ } /* end if */
+
+ HDfputs(buf, stdout);
+ HDfree(buf);
+ break;
+
+ case H5L_TYPE_EXTERNAL:
+ {
+ const char *filename;
+ const char *path;
+
+ if((buf = HDmalloc(linfo->u.val_size)) == NULL)
+ goto done;
+
+ if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) {
+ HDfree(buf);
+ goto done;
+ } /* end if */
+ if(H5Lunpack_elink_val(buf, linfo->u.val_size, NULL, &filename, &path) < 0) {
+ HDfree(buf);
+ goto done;
+ } /* end if */
+
+ HDfputs("file: ", stdout);
+ HDfputs(filename, stdout);
+ HDfputs(" path: ", stdout);
+ HDfputs(path, stdout);
+ HDfree(buf);
+ }
+ break;
+
+ default:
+ HDfputs("cannot follow UD links", stdout);
+ break;
+ } /* end switch */
+ HDfputc('\n', stdout);
+
+done:
+ return 0;
+} /* end list_lnk() */
/*-------------------------------------------------------------------------
@@ -2059,10 +1949,10 @@ leave(int ret)
int
main(int argc, const char *argv[])
{
- hid_t file = -1, root = -1;
+ hid_t file = -1;
char *fname = NULL, *oname = NULL, *x;
const char *s = NULL;
- char *rest, *container = NULL;
+ char *rest;
int argno;
static char root_name[] = "/";
char drivername[50];
@@ -2072,9 +1962,9 @@ main(int argc, const char *argv[])
h5tools_init();
/* Build object display table */
- DISPATCH(H5O_TYPE_GROUP, "Group", H5Gopen2, H5Gclose, NULL, group_list2);
- DISPATCH(H5O_TYPE_DATASET, "Dataset", H5Dopen2, H5Dclose, dataset_list1, dataset_list2);
- DISPATCH(H5O_TYPE_NAMED_DATATYPE, "Type", H5Topen2, H5Tclose, NULL, datatype_list2);
+ DISPATCH(H5O_TYPE_GROUP, "Group", NULL, NULL);
+ DISPATCH(H5O_TYPE_DATASET, "Dataset", dataset_list1, dataset_list2);
+ DISPATCH(H5O_TYPE_NAMED_DATATYPE, "Type", NULL, datatype_list2);
/* Default output width */
width_g = get_width();
@@ -2230,6 +2120,13 @@ main(int argc, const char *argv[])
leave(1);
} /* end if */
+ /* Check for conflicting arguments */
+ if(recursive_g && grp_literal_g) {
+ fprintf(stderr, "Error: 'recursive' option not compatible with 'group info' option!\n\n");
+ usage();
+ leave(1);
+ } /* end if */
+
/* Turn off HDF5's automatic error printing unless you're debugging h5ls */
if(!show_errors_g)
H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
@@ -2249,7 +2146,6 @@ main(int argc, const char *argv[])
* doesn't exist). */
show_file_name_g = (argc-argno > 1); /*show file names if more than one*/
while(argno < argc) {
- H5O_info_t oi;
H5L_info_t li;
iter_t iter;
@@ -2281,24 +2177,21 @@ main(int argc, const char *argv[])
} /* end if */
if(oname)
oname++;
- if(!oname || !*oname)
+ if(!oname || !*oname) {
oname = root_name;
+ if(recursive_g)
+ display_root_g = TRUE;
+ } /* end if */
+
+ /* Remember the file information for later */
+ iter.fname = fname;
+ iter.fid = file;
/* Check for root group as object name */
if(HDstrcmp(oname, root_name)) {
/* Check the type of link given */
if(H5Lget_info(file, oname, &li, H5P_DEFAULT) < 0) {
- char *fullname = NULL;
- int n;
-
- fullname = fix_name(oname, "/");
- if(fullname_g)
- n = display_string(stdout, fullname, TRUE);
- else
- n = display_string(stdout, oname, TRUE);
- printf("%*s \n", MAX(0, (24 - n)), "**NOT FOUND**");
-
- HDfree(fullname);
+ display_obj_name(stdout, &iter, oname, "**NOT FOUND**");
leave(1);
} /* end if */
} /* end if */
@@ -2306,34 +2199,25 @@ main(int argc, const char *argv[])
li.type = H5L_TYPE_HARD;
/* Open the object and display it's information */
- if(li.type == H5L_TYPE_HARD && H5Oget_info_by_name(file, oname, &oi, H5P_DEFAULT) >= 0 && H5O_TYPE_GROUP == oi.type && !grp_literal_g) {
- /* Specified name is a group. List the complete contents of the group. */
- sym_insert(&oi, oname);
- iter.container = container = fix_name((show_file_name_g ? fname : ""), oname);
-
- /* list root attributes */
- if(verbose_g > 0) {
- if((root = H5Gopen2(file, "/", H5P_DEFAULT)) < 0)
- leave(1);
- H5Aiterate2(root, H5_INDEX_NAME, H5_ITER_INC, NULL, list_attr, NULL);
- if(H5Gclose(root) < 0)
- leave(1);
- } /* end if */
+ if(li.type == H5L_TYPE_HARD) {
+ H5O_info_t oi; /* Information for object */
- /* list */
- H5Literate_by_name(file, oname, H5_INDEX_NAME, H5_ITER_INC, NULL, list, &iter, H5P_DEFAULT);
- free(container);
- } else if((root = H5Gopen2(file, "/", H5P_DEFAULT)) < 0) {
- leave(1); /*major problem!*/
- } else {
- /* Specified name is a non-group object -- list that object. The
- * container for the object is everything up to the base name.
- */
- iter.container = show_file_name_g ? fname : "/";
- list(root, oname, &li, &iter);
- if(H5Gclose(root) < 0)
+ /* Retrieve info for object to list */
+ if(H5Oget_info_by_name(file, oname, &oi, H5P_DEFAULT) < 0) {
+ display_obj_name(stdout, &iter, oname, "**NOT FOUND**");
leave(1);
- }
+ } /* end if */
+
+ /* Check for group iteration */
+ if(H5O_TYPE_GROUP == oi.type && !grp_literal_g)
+ /* Specified name is a group. List the complete contents of the group. */
+ h5trav_visit(file, oname, display_root_g, recursive_g, list_obj, list_lnk, &iter);
+ else
+ /* Specified name is a non-group object -- list that object */
+ list_obj(oname, &oi, NULL, &iter);
+ } else
+ /* Specified name is not for object -- list that link */
+ list_lnk(oname, &li, &iter);
H5Fclose(file);
free(fname);
} /* end while */
diff --git a/tools/h5ls/testh5ls.sh b/tools/h5ls/testh5ls.sh
index ab36eb4..f25db4e 100755
--- a/tools/h5ls/testh5ls.sh
+++ b/tools/h5ls/testh5ls.sh
@@ -112,6 +112,7 @@ TOOLTEST tgroup.ls -w80 tgroup.h5
# test for displaying groups
TOOLTEST tgroup-1.ls -w80 -r -g tgroup.h5
+TOOLTEST tgroup-2.ls -w80 -g tgroup.h5/g1
# test for displaying simple space datasets
TOOLTEST tdset-1.ls -w80 -r -d tdset.h5
diff --git a/tools/h5stat/h5stat.c b/tools/h5stat/h5stat.c
index c69d801..f03efd7 100644
--- a/tools/h5stat/h5stat.c
+++ b/tools/h5stat/h5stat.c
@@ -47,8 +47,7 @@ typedef struct ohdr_info_t {
/* Info to pass to the iteration functions */
typedef struct iter_t {
- const char *container; /* Full name of the container object */
- unsigned long curr_depth; /* Current depth of hierarchy */
+ hid_t fid; /* File ID */
unsigned long uniq_groups; /* Number of unique groups */
unsigned long uniq_dsets; /* Number of unique datasets */
@@ -56,7 +55,6 @@ typedef struct iter_t {
unsigned long uniq_links; /* Number of unique links */
unsigned long uniq_others; /* Number of other unique objects */
- unsigned long max_depth; /* Maximum depth of hierarchy */
unsigned long max_links; /* Maximum # of links to an object */
hsize_t max_fanout; /* Maximum fanout from a group */
unsigned long num_small_groups[SIZE_SMALL_GROUPS]; /* Size of small groups tracked */
@@ -95,16 +93,6 @@ typedef struct iter_t {
} iter_t;
-/* Table containing object id and object name */
-static struct {
- int nalloc; /* number of slots allocated */
- int nobjs; /* number of objects */
- struct {
- haddr_t id; /* object number */
- char *name; /* full object name */
- } *obj;
-} idtab_g;
-
const char *progname = "h5stat";
int d_status = EXIT_SUCCESS;
static int display_all = TRUE;
@@ -260,123 +248,6 @@ ceil_log10(unsigned long x)
/*-------------------------------------------------------------------------
- * Function: sym_insert
- *
- * Purpose: Add a symbol to the table.
- *
- * Return: void
- *
- * Programmer: Robb Matzke
- * Thursday, January 21, 1999
- *
- *-------------------------------------------------------------------------
- */
-static void
-sym_insert(H5O_info_t *oi, const char *name)
-{
- /* Don't add it if the link count is 1 because such an object can only
- * have one name. */
- if(oi->rc > 1) {
- int n;
-
- /* Extend the table */
- if(idtab_g.nobjs >= idtab_g.nalloc) {
- idtab_g.nalloc = MAX(256, 2 * idtab_g.nalloc);
- idtab_g.obj = realloc(idtab_g.obj, idtab_g.nalloc * sizeof(idtab_g.obj[0]));
- } /* end if */
-
- /* Insert the entry */
- n = idtab_g.nobjs++;
- idtab_g.obj[n].id = oi->addr;
- idtab_g.obj[n].name = strdup(name);
- } /* end if */
-} /* end sym_insert() */
-
-
-/*-------------------------------------------------------------------------
- * Function: sym_lookup
- *
- * Purpose: Find another name for the specified object.
- *
- * Return: Success: Ptr to another name.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Thursday, January 21, 1999
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static char *
-sym_lookup(H5O_info_t *oi)
-{
- int n;
-
- /*only one name possible*/
- if(oi->rc < 2)
- return NULL;
-
- for(n = 0; n < idtab_g.nobjs; n++)
- if(idtab_g.obj[n].id == oi->addr)
- return idtab_g.obj[n].name;
-
- return NULL;
-} /* end sym_lookup() */
-
-
-/*-------------------------------------------------------------------------
- * Function: fix_name
- *
- * Purpose: Returns a malloc'd buffer that contains the PATH and BASE
- * names separated by a single slash. It also removes duplicate
- * and trailing slashes.
- *
- * Return: Success: Ptr to fixed name from malloc()
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Thursday, January 21, 1999
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static char *
-fix_name(const char *path, const char *base)
-{
- size_t n = (path ? strlen(path) : 0) + (base ? strlen(base) : 0) + 3;
- char *s = malloc(n), prev='\0';
- size_t len = 0;
-
- if (path) {
- /* Path, followed by slash */
- for (/*void*/; *path; path++)
- if ('/'!=*path || '/'!=prev)
- prev = s[len++] = *path;
- if ('/' != prev)
- prev = s[len++] = '/';
- }
-
- if (base) {
- /* Base name w/o trailing slashes */
- const char *end = base + strlen(base);
- while (end > base && '/' == end[-1])
- --end;
-
- for (/*void*/; base < end; base++)
- if ('/' != *base || '/' != prev)
- prev = s[len++] = *base;
- }
-
- s[len] = '\0';
- return s;
-}
-
-
-/*-------------------------------------------------------------------------
* Function: attribute_stats
*
* Purpose: Gather statistics about attributes on an object
@@ -453,25 +324,21 @@ attribute_stats(iter_t *iter, const H5O_info_t *oi)
*-------------------------------------------------------------------------
*/
static herr_t
-group_stats(hid_t group, const char *name, const char *fullname,
- const H5O_info_t *oi, H5L_iterate_t walk, iter_t *iter)
+group_stats(iter_t *iter, const char *name, const H5O_info_t *oi)
{
- const char *last_container;
H5G_info_t ginfo; /* Group information */
unsigned bin; /* "bin" the number of objects falls in */
herr_t ret;
/* Gather statistics about this type of object */
iter->uniq_groups++;
- if(iter->curr_depth > iter->max_depth)
- iter->max_depth = iter->curr_depth;
/* Get object header information */
iter->group_ohdr_info.total_size += oi->hdr.space.total;
iter->group_ohdr_info.free_size += oi->hdr.space.free;
/* Get group information */
- ret = H5Gget_info_by_name(group, name, &ginfo, H5P_DEFAULT);
+ ret = H5Gget_info_by_name(iter->fid, name, &ginfo, H5P_DEFAULT);
assert(ret >= 0);
/* Update link stats */
@@ -506,18 +373,6 @@ group_stats(hid_t group, const char *name, const char *fullname,
ret = attribute_stats(iter, oi);
assert(ret >= 0);
- /* Update current container info */
- last_container = iter->container;
- iter->container = fullname;
- iter->curr_depth++;
-
- /* Recursively descend into current group's objects */
- H5Literate_by_name(group, name, H5_INDEX_NAME, H5_ITER_INC, NULL, walk, iter, H5P_DEFAULT);
-
- /* Revert current container info */
- iter->container = last_container;
- iter->curr_depth--;
-
return 0;
} /* end group_stats() */
@@ -549,7 +404,7 @@ group_stats(hid_t group, const char *name, const char *fullname,
*-------------------------------------------------------------------------
*/
static herr_t
-dataset_stats(hid_t group, const char *name, const H5O_info_t *oi, iter_t *iter)
+dataset_stats(iter_t *iter, const char *name, const H5O_info_t *oi)
{
unsigned bin; /* "bin" the number of objects falls in */
hid_t did; /* Dataset ID */
@@ -575,7 +430,7 @@ dataset_stats(hid_t group, const char *name, const H5O_info_t *oi, iter_t *iter)
iter->dset_ohdr_info.total_size += oi->hdr.space.total;
iter->dset_ohdr_info.free_size += oi->hdr.space.free;
- did = H5Dopen2(group, name, H5P_DEFAULT);
+ did = H5Dopen2(iter->fid, name, H5P_DEFAULT);
assert(did > 0);
/* Update dataset metadata info */
@@ -710,89 +565,90 @@ dataset_stats(hid_t group, const char *name, const H5O_info_t *oi, iter_t *iter)
/*-------------------------------------------------------------------------
- * Function: walk
+ * Function: obj_stats
*
- * Purpose: Gather statistics about the file
+ * Purpose: Gather statistics about an object
*
* Return: Success: 0
- * Failure: -1
*
- * Programmer: Quincey Koziol
- * Tuesday, August 16, 2005
+ * Failure: -1
*
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Tuesday, November 6, 2007
*
*-------------------------------------------------------------------------
*/
static herr_t
-walk(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter)
+obj_stats(const char *path, const H5O_info_t *oi, const char *already_visited,
+ void *_iter)
{
iter_t *iter = (iter_t *)_iter;
- char *fullname = NULL;
- herr_t ret; /* Generic return value */
-
- if(!linfo || linfo->type == H5L_TYPE_HARD) {
- H5O_info_t oi;
- char *s;
-
- /* Get object information */
- ret = H5Oget_info_by_name(group, name, &oi, H5P_DEFAULT);
- assert(ret >= 0);
-
- /* If the object has already been printed then just show the object ID
- * and return. */
- if((s = sym_lookup(&oi))) {
- printf("%s same as %s\n", name, s);
- } else {
- /* Get the full object name */
- fullname = fix_name(iter->container, name);
- sym_insert(&oi, fullname);
-
- /* Gather some statistics about the object */
- if(oi.rc > iter->max_links)
- iter->max_links = oi.rc;
-
- switch(oi.type) {
- case H5O_TYPE_GROUP:
- group_stats(group, name, fullname, &oi, walk, iter);
- break;
-
- case H5O_TYPE_DATASET:
- dataset_stats(group, name, &oi, iter);
- break;
-
- case H5O_TYPE_NAMED_DATATYPE:
- /* Gather statistics about this type of object */
- iter->uniq_types++;
- break;
-
- default:
- /* Gather statistics about this type of object */
- iter->uniq_others++;
- break;
- } /* end switch */
- }
- } /* end if */
- else {
- switch(linfo->type) {
- case H5L_TYPE_SOFT:
- case H5L_TYPE_EXTERNAL:
- /* Gather statistics about links and UD links */
- iter->uniq_links++;
+
+ /* If the object has already been seen then just return */
+ if(NULL == already_visited) {
+ /* Gather some general statistics about the object */
+ if(oi->rc > iter->max_links)
+ iter->max_links = oi->rc;
+
+ switch(oi->type) {
+ case H5O_TYPE_GROUP:
+ group_stats(iter, path, oi);
+ break;
+
+ case H5O_TYPE_DATASET:
+ dataset_stats(iter, path, oi);
+ break;
+
+ case H5O_TYPE_NAMED_DATATYPE:
+ /* Gather statistics about this type of object */
+ iter->uniq_types++;
break;
default:
/* Gather statistics about this type of object */
iter->uniq_others++;
break;
- } /* end switch() */
- } /* end else */
+ } /* end switch */
+ } /* end if */
- if(fullname)
- free(fullname);
+ return 0;
+} /* end obj_stats() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: lnk_stats
+ *
+ * Purpose: Gather statistics about a link
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, November 6, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+lnk_stats(const char UNUSED *path, const H5L_info_t *li, void *_iter)
+{
+ iter_t *iter = (iter_t *)_iter;
+
+ switch(li->type) {
+ case H5L_TYPE_SOFT:
+ case H5L_TYPE_EXTERNAL:
+ /* Gather statistics about links and UD links */
+ iter->uniq_links++;
+ break;
+
+ default:
+ /* Gather statistics about this type of object */
+ iter->uniq_others++;
+ break;
+ } /* end switch() */
return 0;
-}
+} /* end lnk_stats() */
/*-------------------------------------------------------------------------
@@ -915,13 +771,13 @@ parse_command_line(int argc, const char *argv[])
*-------------------------------------------------------------------------
*/
static herr_t
-iter_init(iter_t *iter)
+iter_init(iter_t *iter, hid_t fid)
{
/* Clear everything to zeros */
- memset(iter, 0, sizeof(*iter));
+ HDmemset(iter, 0, sizeof(*iter));
- /* Initialize non-zero information */
- iter->container = "/";
+ /* Set the file ID for later use in callbacks */
+ iter->fid = fid;
return 0;
}
@@ -953,7 +809,6 @@ print_file_info(const iter_t *iter)
printf("\t# of unique links: %lu\n", iter->uniq_links);
printf("\t# of unique other: %lu\n", iter->uniq_others);
printf("\tMax. # of links to object: %lu\n", iter->max_links);
- printf("\tMax. depth of hierarchy: %lu\n", iter->max_depth);
HDfprintf(stdout, "\tMax. # of objects in group: %Hu\n", iter->max_fanout);
return 0;
@@ -1318,8 +1173,6 @@ main(int argc, const char *argv[])
const char *fname = NULL;
hid_t fid;
struct handler_t *hand;
- char root[] = "/";
- int i;
H5F_info_t finfo;
@@ -1329,25 +1182,23 @@ main(int argc, const char *argv[])
/* Initialize h5tools lib */
h5tools_init();
hand = parse_command_line (argc, argv);
- if (!hand) {
+ if(!hand) {
error_msg(progname, "unable to parse command line arguments \n");
leave(EXIT_FAILURE);
- }
+ } /* end if */
fname = argv[opt_ind];
- if(!display_object)
- hand[0].obj = root;
printf("Filename: %s\n", fname);
fid = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT);
- if (fid < 0) {
+ if(fid < 0) {
error_msg(progname, "unable to open file \"%s\"\n", fname);
leave(EXIT_FAILURE);
- }
+ } /* end if */
/* Initialize iter structure */
- iter_init(&iter);
+ iter_init(&iter, fid);
/* Get storge info for SOHM's btree/list/heap and superblock extension */
if(H5Fget_info(fid, &finfo) < 0)
@@ -1357,15 +1208,23 @@ main(int argc, const char *argv[])
iter.SM_hdr_storage_size = finfo.sohm.hdr_size;
iter.SM_index_storage_size = finfo.sohm.msgs_info.index_size;
iter.SM_heap_storage_size = finfo.sohm.msgs_info.heap_size;
- }
+ } /* end else */
/* Walk the objects or all file */
- i = 0;
- while(hand[i].obj) {
- walk(fid, hand[i].obj, NULL, &iter);
- print_statistics(hand[i].obj, &iter);
- i++;
- } /* end while */
+ if(display_object) {
+ unsigned u;
+
+ u = 0;
+ while(hand[u].obj) {
+ h5trav_visit(fid, hand[u].obj, TRUE, TRUE, obj_stats, lnk_stats, &iter);
+ print_statistics(hand[u].obj, &iter);
+ u++;
+ } /* end while */
+ } /* end if */
+ else {
+ h5trav_visit(fid, "/", TRUE, TRUE, obj_stats, lnk_stats, &iter);
+ print_statistics("/", &iter);
+ } /* end else */
free(hand);
diff --git a/tools/h5stat/testfiles/h5stat_filters-file.ddl b/tools/h5stat/testfiles/h5stat_filters-file.ddl
index c6aeef0..7b8f47f 100644
--- a/tools/h5stat/testfiles/h5stat_filters-file.ddl
+++ b/tools/h5stat/testfiles/h5stat_filters-file.ddl
@@ -9,5 +9,4 @@ File information
# of unique links: 0
# of unique other: 0
Max. # of links to object: 1
- Max. depth of hierarchy: 0
Max. # of objects in group: 16
diff --git a/tools/h5stat/testfiles/h5stat_filters.ddl b/tools/h5stat/testfiles/h5stat_filters.ddl
index 4dd6aee..df2e304 100644
--- a/tools/h5stat/testfiles/h5stat_filters.ddl
+++ b/tools/h5stat/testfiles/h5stat_filters.ddl
@@ -9,7 +9,6 @@ File information
# of unique links: 0
# of unique other: 0
Max. # of links to object: 1
- Max. depth of hierarchy: 0
Max. # of objects in group: 16
Object header size: (total/unused)
Groups: 48/8
diff --git a/tools/h5stat/testfiles/h5stat_newgrat.ddl b/tools/h5stat/testfiles/h5stat_newgrat.ddl
index 228d565..6881ca9 100644
--- a/tools/h5stat/testfiles/h5stat_newgrat.ddl
+++ b/tools/h5stat/testfiles/h5stat_newgrat.ddl
@@ -9,7 +9,6 @@ File information
# of unique links: 0
# of unique other: 0
Max. # of links to object: 1
- Max. depth of hierarchy: 1
Max. # of objects in group: 351
Object header size: (total/unused)
Groups: 51597/32292
diff --git a/tools/h5stat/testfiles/h5stat_tsohm.ddl b/tools/h5stat/testfiles/h5stat_tsohm.ddl
index 572965e..15a058e 100644
--- a/tools/h5stat/testfiles/h5stat_tsohm.ddl
+++ b/tools/h5stat/testfiles/h5stat_tsohm.ddl
@@ -9,7 +9,6 @@ File information
# of unique links: 0
# of unique other: 0
Max. # of links to object: 1
- Max. depth of hierarchy: 0
Max. # of objects in group: 2
Object header size: (total/unused)
Groups: 51/2
diff --git a/tools/lib/h5tools_ref.c b/tools/lib/h5tools_ref.c
index 123065b..de1e2c3 100644
--- a/tools/lib/h5tools_ref.c
+++ b/tools/lib/h5tools_ref.c
@@ -20,6 +20,7 @@
#include "H5SLprivate.h"
#include "h5tools.h"
#include "h5tools_utils.h"
+#include "h5trav.h"
/*
@@ -42,15 +43,12 @@ typedef struct {
} ref_path_node_t;
static H5SL_t *ref_path_table = NULL; /* the "table" (implemented with a skip list) */
-static hid_t thefile;
+static hid_t thefile = (-1);
extern char *progname;
extern int d_status;
static int ref_path_table_put(const char *, haddr_t objno);
-static hbool_t ref_path_table_find(haddr_t objno);
-static herr_t fill_ref_path_table_cb(hid_t group, const char *obj_name,
- const H5L_info_t *linfo, void *op_data);
/*-------------------------------------------------------------------------
* Function: free_ref_path_info
@@ -77,6 +75,61 @@ free_ref_path_info(void *item, void UNUSED *key, void UNUSED *operator_data/*in,
}
/*-------------------------------------------------------------------------
+ * Function: init_ref_path_cb
+ *
+ * Purpose: Called by interator to create references for
+ * all objects and enter them in the table.
+ *
+ * Return: Error status.
+ *
+ * Programmer: REMcG
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+init_ref_path_cb(const char *obj_name, const H5O_info_t *oinfo,
+ const char *already_seen, void UNUSED *_udata)
+{
+ /* Check if the object is already in the path table */
+ if(NULL == already_seen) {
+ /* Insert the object into the path table */
+ ref_path_table_put(obj_name, oinfo->addr);
+ } /* end if */
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: init_ref_path_table
+ *
+ * Purpose: Initalize the reference path table
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+init_ref_path_table(void)
+{
+ /* Sanity check */
+ HDassert(thefile > 0);
+
+ /* Create skip list to store reference path information */
+ if((ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16))==NULL)
+ return (-1);
+
+ /* Iterate over objects in this file */
+ if(h5trav_visit(thefile, "/", TRUE, TRUE, init_ref_path_cb, NULL, NULL) < 0) {
+ error_msg(progname, "unable to construct reference path table\n");
+ d_status = EXIT_FAILURE;
+ } /* end if */
+
+ return(0);
+}
+
+/*-------------------------------------------------------------------------
* Function: term_ref_path_table
*
* Purpose: Terminate the reference path table
@@ -137,39 +190,11 @@ ref_path_table_lookup(const char *thepath)
if(H5Oget_info_by_name(thefile, thepath, &oi, H5P_DEFAULT) < 0)
return HADDR_UNDEF;
- /* All existing objects in the file had better be in the table */
- HDassert(ref_path_table_find(oi.addr));
-
/* Return OID */
return(oi.addr);
}
/*-------------------------------------------------------------------------
- * Function: ref_path_table_find
- *
- * Purpose: Looks up a table entry given a object number.
- * Used during construction of the table.
- *
- * Return: TRUE/FALSE on success, can't fail
- *
- * Programmer: Quincey Koziol
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hbool_t
-ref_path_table_find(haddr_t objno)
-{
- HDassert(ref_path_table);
-
- if(H5SL_search(ref_path_table, &objno) == NULL)
- return FALSE;
- else
- return TRUE;
-}
-
-/*-------------------------------------------------------------------------
* Function: ref_path_table_put
*
* Purpose: Enter the 'obj' with 'path' in the table (assumes its not
@@ -200,7 +225,7 @@ ref_path_table_put(const char *path, haddr_t objno)
return(-1);
new_node->objno = objno;
- new_node->path = path;
+ new_node->path = HDstrdup(path);
return(H5SL_insert(ref_path_table, new_node, &(new_node->objno)));
}
@@ -237,17 +262,17 @@ get_fake_xid (void) {
haddr_t
ref_path_table_gen_fake(const char *path)
{
- const char *dup_path;
haddr_t fake_objno;
- if((dup_path = HDstrdup(path)) == NULL)
- return HADDR_UNDEF;
-
/* Generate fake ID for string */
fake_objno = get_fake_xid();
- /* Insert "fake" object into table (takes ownership of path) */
- ref_path_table_put(dup_path, fake_objno);
+ /* Create ref path table, if it hasn't already been created */
+ if(ref_path_table == NULL)
+ init_ref_path_table();
+
+ /* Insert "fake" object into table */
+ ref_path_table_put(path, fake_objno);
return(fake_objno);
}
@@ -271,74 +296,19 @@ lookup_ref_path(haddr_t ref)
ref_path_node_t *node;
/* Be safer for h5ls */
- if(!ref_path_table)
+ if(thefile < 0)
return(NULL);
+ /* Create ref path table, if it hasn't already been created */
+ if(ref_path_table == NULL)
+ init_ref_path_table();
+
node = H5SL_search(ref_path_table, &ref);
return(node ? node->path : NULL);
}
/*-------------------------------------------------------------------------
- * Function: fill_ref_path_table_cb
- *
- * Purpose: Called by interator to create references for
- * all objects and enter them in the table.
- *
- * Return: Error status.
- *
- * Programmer: REMcG
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-fill_ref_path_table_cb(hid_t group, const char *obj_name, const H5L_info_t *linfo,
- void *op_data)
-{
- if(linfo->type == H5L_TYPE_HARD) {
- H5O_info_t oinfo;
-
- H5Oget_info_by_name(group, obj_name, &oinfo, H5P_DEFAULT);
-
- /* Check if the object is already in the path table */
- if(!ref_path_table_find(oinfo.addr)) {
- const char *obj_prefix = (const char *)op_data;
- size_t tmp_len;
- char *thepath;
-
- /* Compute length for this object's path */
- tmp_len = HDstrlen(obj_prefix) + HDstrlen(obj_name) + 2;
-
- /* Allocate room for the path for this object */
- if((thepath = (char *)HDmalloc(tmp_len)) == NULL)
- return FAIL;
-
- /* Build the name for this object */
- HDstrcpy(thepath, obj_prefix);
- HDstrcat(thepath, "/");
- HDstrcat(thepath, obj_name);
-
- /* Insert the object into the path table (takes ownership of the path) */
- ref_path_table_put(thepath, oinfo.addr);
-
- if(oinfo.type == H5O_TYPE_GROUP) {
- /* Iterate over objects in this group, using this group's
- * name as their prefix
- */
- if(H5Literate_by_name(group, obj_name, H5_INDEX_NAME, H5_ITER_INC, NULL, fill_ref_path_table_cb, thepath, H5P_DEFAULT) < 0) {
- error_msg(progname, "unable to dump group \"%s\"\n", thepath);
- d_status = EXIT_FAILURE;
- } /* end if */
- } /* end if */
- } /* end if */
- } /* end if */
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------
* Function: fill_ref_path_table
*
* Purpose: Called by interator to create references for
@@ -348,37 +318,15 @@ fill_ref_path_table_cb(hid_t group, const char *obj_name, const H5L_info_t *linf
*
* Programmer: REMcG
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
fill_ref_path_table(hid_t fid)
{
- H5O_info_t oinfo;
- char *root_path;
-
/* Set file ID for later queries (XXX: this should be fixed) */
thefile = fid;
- /* Create skip list to store reference path information */
- if((ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16))==NULL)
- return (-1);
-
- /* Build the name for root group */
- root_path = HDstrdup("/");
-
- /* Get info for root group */
- H5Oget_info_by_name(fid, root_path, &oinfo, H5P_DEFAULT);
-
- /* Insert the root group into the path table (takes ownership of path) */
- ref_path_table_put(root_path, oinfo.addr);
-
- /* Iterate over objects in this file */
- if(H5Literate(fid, H5_INDEX_NAME, H5_ITER_INC, NULL, fill_ref_path_table_cb, (void *)"") < 0) {
- error_msg(progname, "unable to dump root group\n");
- d_status = EXIT_FAILURE;
- } /* end if */
+ /* Defer creating the ref path table until it's needed */
return 0;
}
diff --git a/tools/lib/h5tools_utils.c b/tools/lib/h5tools_utils.c
index cb38e7a..512a3fb 100644
--- a/tools/lib/h5tools_utils.c
+++ b/tools/lib/h5tools_utils.c
@@ -30,6 +30,7 @@
#include "h5tools_utils.h"
#include "H5private.h"
+#include "h5trav.h"
/* global variables */
int nCols = 80;
@@ -44,10 +45,7 @@ static void init_table(table_t **tbl);
#ifdef H5DUMP_DEBUG
static void dump_table(char* tablename, table_t *table);
#endif /* H5DUMP_DEBUG */
-static void add_obj(table_t *table, haddr_t objno, char *objname, hbool_t recorded);
-static char * build_obj_path_name(const char *prefix, const char *name);
-static herr_t find_objs_cb(hid_t group, const char *name, const H5L_info_t *info,
- void *op_data);
+static void add_obj(table_t *table, haddr_t objno, const char *objname, hbool_t recorded);
/*-------------------------------------------------------------------------
@@ -428,44 +426,15 @@ search_obj(table_t *table, haddr_t objno)
{
unsigned u;
- for (u = 0; u < table->nobjs; u++)
- if (table->objs[u].objno == objno)
- return &(table->objs[u]);
+ for(u = 0; u < table->nobjs; u++)
+ if(table->objs[u].objno == objno)
+ return &(table->objs[u]);
return NULL;
}
/*-------------------------------------------------------------------------
- * Function: build_obj_path_name
- *
- * Purpose: Allocate space & build path name from prefix & name
- *
- * Return: Success: SUCCEED
- *
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static char *
-build_obj_path_name(const char *prefix, const char *name)
-{
- char *path;
-
- path = HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2);
- HDstrcpy(path, prefix);
- HDstrcat(path,"/");
- HDstrcat(path,name); /* absolute name of the data set */
-
- return(path);
-} /* end build_obj_path_name() */
-
-
-/*-------------------------------------------------------------------------
* Function: find_objs_cb
*
* Purpose: Callback to find objects, committed types and store them in tables
@@ -481,90 +450,65 @@ build_obj_path_name(const char *prefix, const char *name)
*-------------------------------------------------------------------------
*/
static herr_t
-find_objs_cb(hid_t group, const char *name, const H5L_info_t UNUSED *linfo, void *op_data)
+find_objs_cb(const char *name, const H5O_info_t *oinfo, const char *already_seen,
+ void *op_data)
{
- H5O_info_t oinfo;
find_objs_t *info = (find_objs_t*)op_data;
herr_t ret_value = 0;
- if(H5Oget_info_by_name(group, name, &oinfo, H5P_DEFAULT) < 0)
- ; /* keep going */
- else {
- switch(oinfo.type) {
- char *tmp;
- size_t tmp_len;
-
- case H5O_TYPE_GROUP:
- if(search_obj(info->group_table, oinfo.addr) == NULL) {
- char *old_prefix;
+ switch(oinfo->type) {
+ case H5O_TYPE_GROUP:
+ if(NULL == already_seen)
+ add_obj(info->group_table, oinfo->addr, name, TRUE);
+ break;
- tmp = build_obj_path_name(info->prefix, name);
- add_obj(info->group_table, oinfo.addr, tmp, TRUE);
+ case H5O_TYPE_DATASET:
+ if(NULL == already_seen) {
+ hid_t dset;
- old_prefix = info->prefix;
- tmp_len = HDstrlen(tmp);
- info->prefix = HDmalloc(tmp_len+1);
- HDstrcpy(info->prefix, tmp);
+ /* Add the dataset to the list of objects */
+ add_obj(info->dset_table, oinfo->addr, name, TRUE);
- if(H5Literate_by_name(group, name, H5_INDEX_NAME, H5_ITER_INC, NULL, find_objs_cb, (void *)info, H5P_DEFAULT) < 0)
- ret_value = FAIL;
+ /* Check for a dataset that uses a named datatype */
+ if((dset = H5Dopen2(info->fid, name, H5P_DEFAULT)) >= 0) {
+ hid_t type = H5Dget_type(dset);
- info->prefix = old_prefix;
- } /* end if */
- break;
-
- case H5O_TYPE_DATASET:
- if(search_obj(info->dset_table, oinfo.addr) == NULL) {
- hid_t dset;
-
- tmp = build_obj_path_name(info->prefix, name);
- add_obj(info->dset_table, oinfo.addr, tmp, TRUE);
-
- if((dset = H5Dopen2(group, name, H5P_DEFAULT)) >= 0) {
- hid_t type;
+ if(H5Tcommitted(type) > 0) {
+ H5O_info_t type_oinfo;
- type = H5Dget_type(dset);
-
- if(H5Tcommitted(type) > 0) {
- H5Oget_info(type, &oinfo);
- if(search_obj(info->type_table, oinfo.addr) == NULL) {
- char *type_name = HDstrdup(tmp);
-
- add_obj(info->type_table, oinfo.addr, type_name, FALSE);
- } /* end if */
- } /* end if */
-
- H5Tclose(type);
- H5Dclose(dset);
+ H5Oget_info(type, &type_oinfo);
+ if(search_obj(info->type_table, type_oinfo.addr) == NULL)
+ add_obj(info->type_table, type_oinfo.addr, name, FALSE);
} /* end if */
- else
- ret_value = FAIL;
- } /* end if */
- break;
- case H5O_TYPE_NAMED_DATATYPE:
- {
- obj_t *found_obj;
-
- tmp = build_obj_path_name(info->prefix, name);
- if((found_obj = search_obj(info->type_table, oinfo.addr)) == NULL)
- add_obj(info->type_table, oinfo.addr, tmp, TRUE);
- else {
- /* Use latest version of name */
- HDfree(found_obj->objname);
- found_obj->objname = HDstrdup(tmp);
-
- /* Mark named datatype as having valid name */
- found_obj->recorded = TRUE;
- } /* end else */
- break;
- }
-
- default:
- /* Ignore links, etc. */
- break;
+ H5Tclose(type);
+ H5Dclose(dset);
+ } /* end if */
+ else
+ ret_value = FAIL;
+ } /* end if */
+ break;
+
+ case H5O_TYPE_NAMED_DATATYPE:
+ {
+ obj_t *found_obj;
+
+ if((found_obj = search_obj(info->type_table, oinfo->addr)) == NULL)
+ add_obj(info->type_table, oinfo->addr, name, TRUE);
+ else {
+ /* Use latest version of name */
+ HDfree(found_obj->objname);
+ found_obj->objname = HDstrdup(name);
+
+ /* Mark named datatype as having valid name */
+ found_obj->recorded = TRUE;
+ } /* end else */
+ break;
}
- } /* end else */
+
+ default:
+ break;
+ } /* end switch */
return ret_value;
}
@@ -589,31 +533,19 @@ herr_t
init_objs(hid_t fid, find_objs_t *info, table_t **group_table,
table_t **dset_table, table_t **type_table)
{
- H5O_info_t oinfo;
-
/* Initialize the tables */
init_table(group_table);
init_table(dset_table);
init_table(type_table);
/* Init the find_objs_t */
- info->prefix = HDcalloc(1, 1);
+ info->fid = fid;
info->group_table = *group_table;
info->type_table = *type_table;
info->dset_table = *dset_table;
- /* add the root group as an object, it may have hard links to it */
- if(H5Oget_info(fid, &oinfo) < 0)
- return FAIL;
- else {
- /* call with an empty string, it appends '/' group separator */
- char *tmp = build_obj_path_name(info->prefix, "");
-
- add_obj(info->group_table, oinfo.addr, tmp, TRUE);
- } /* end else */
-
/* Find all shared objects */
- return(H5Literate(fid, H5_INDEX_NAME, H5_ITER_INC, NULL, find_objs_cb, (void *)info));
+ return(h5trav_visit(fid, "/", TRUE, TRUE, find_objs_cb, NULL, info));
}
@@ -632,22 +564,22 @@ init_objs(hid_t fid, find_objs_t *info, table_t **group_table,
*-------------------------------------------------------------------------
*/
static void
-add_obj(table_t *table, haddr_t objno, char *objname, hbool_t record)
+add_obj(table_t *table, haddr_t objno, const char *objname, hbool_t record)
{
unsigned u;
/* See if we need to make table larger */
- if (table->nobjs == table->size) {
+ if(table->nobjs == table->size) {
table->size *= 2;
- table->objs = HDrealloc(table->objs, table->size * sizeof(obj_t));
- }
+ table->objs = HDrealloc(table->objs, table->size * sizeof(table->objs[0]));
+ } /* end if */
/* Increment number of objects in table */
u = table->nobjs++;
/* Set information about object */
table->objs[u].objno = objno;
- table->objs[u].objname = objname;
+ table->objs[u].objname = HDstrdup(objname);
table->objs[u].recorded = record;
table->objs[u].displayed = 0;
}
diff --git a/tools/lib/h5tools_utils.h b/tools/lib/h5tools_utils.h
index e604e5a..e7b175c 100644
--- a/tools/lib/h5tools_utils.h
+++ b/tools/lib/h5tools_utils.h
@@ -95,7 +95,7 @@ typedef struct table_t {
/*this struct stores the information that is passed to the find_objs function*/
typedef struct find_objs_t {
- char *prefix;
+ hid_t fid;
table_t *group_table;
table_t *type_table;
table_t *dset_table;
diff --git a/tools/lib/h5trav.c b/tools/lib/h5trav.c
index 97de021..14ced60 100644
--- a/tools/lib/h5trav.c
+++ b/tools/lib/h5trav.c
@@ -24,24 +24,25 @@
typedef struct trav_addr_t {
size_t nalloc;
size_t nused;
- haddr_t *addrs;
+ struct {
+ haddr_t addr;
+ char *path;
+ } *objs;
} trav_addr_t;
typedef struct {
- herr_t (*visit_obj)(const char *path_name, const H5O_info_t *oinfo, hbool_t already_visited, void *udata);
- herr_t (*visit_lnk)(const char *path_name, const H5L_info_t *linfo, void *udata);
+ h5trav_obj_func_t visit_obj; /* Callback for visiting objects */
+ h5trav_lnk_func_t visit_lnk; /* Callback for visiting links */
void *udata; /* User data to pass to callbacks */
} trav_visitor_t;
typedef struct {
trav_addr_t *seen; /* List of addresses seen already */
- const char *curr_path; /* Current path to parent group */
const trav_visitor_t *visitor; /* Information for visiting each link/object */
} trav_ud_traverse_t;
typedef struct {
hid_t fid; /* File ID being traversed */
- trav_table_t *table; /* Table for tracking name of objects with >1 hard link */
} trav_print_udata_t;
/*-------------------------------------------------------------------------
@@ -52,10 +53,8 @@ static void trav_table_add(trav_table_t *table,
const char *objname,
const H5O_info_t *oinfo);
-static size_t trav_table_search(const trav_table_t *table, haddr_t objno);
-
static void trav_table_addlink(trav_table_t *table,
- size_t j /* the object index */,
+ haddr_t objno,
const char *path);
/*-------------------------------------------------------------------------
@@ -78,19 +77,20 @@ static void trav_table_addlink(trav_table_t *table,
*-------------------------------------------------------------------------
*/
static void
-trav_addr_add(trav_addr_t *visited, haddr_t addr)
+trav_addr_add(trav_addr_t *visited, haddr_t addr, const char *path)
{
size_t idx; /* Index of address to use */
/* Allocate space if necessary */
if(visited->nused == visited->nalloc) {
visited->nalloc = MAX(1, visited->nalloc * 2);;
- visited->addrs = (haddr_t *)HDrealloc(visited->addrs, visited->nalloc * sizeof(haddr_t));
+ visited->objs = HDrealloc(visited->objs, visited->nalloc * sizeof(visited->objs[0]));
} /* end if */
/* Append it */
idx = visited->nused++;
- visited->addrs[idx] = addr;
+ visited->objs[idx].addr = addr;
+ visited->objs[idx].path = HDstrdup(path);
} /* end trav_addr_add() */
@@ -107,7 +107,7 @@ trav_addr_add(trav_addr_t *visited, haddr_t addr)
*
*-------------------------------------------------------------------------
*/
-static hbool_t
+static const char *
trav_addr_visited(trav_addr_t *visited, haddr_t addr)
{
size_t u; /* Local index variable */
@@ -115,11 +115,11 @@ trav_addr_visited(trav_addr_t *visited, haddr_t addr)
/* Look for address */
for(u = 0; u < visited->nused; u++)
/* Check for address already in array */
- if(visited->addrs[u] == addr)
- return(TRUE);
+ if(visited->objs[u].addr == addr)
+ return(visited->objs[u].path);
/* Didn't find address */
- return(FALSE);
+ return(NULL);
} /* end trav_addr_visited() */
@@ -135,68 +135,44 @@ trav_addr_visited(trav_addr_t *visited, haddr_t addr)
*-------------------------------------------------------------------------
*/
static herr_t
-traverse_cb(hid_t loc_id, const char *link_name, const H5L_info_t *linfo,
+traverse_cb(hid_t loc_id, const char *path, const H5L_info_t *linfo,
void *_udata)
{
trav_ud_traverse_t *udata = (trav_ud_traverse_t *)_udata; /* User data */
- hbool_t is_group = FALSE; /* If the object is a group */
- hbool_t already_visited = FALSE; /* Whether the link/object was already visited */
- char *link_path; /* Full path name of a link */
+ char *full_name;
+ const char *already_visited = NULL; /* Whether the link/object was already visited */
- /* Construct the full path name of this link */
- link_path = (char*)HDmalloc(HDstrlen(udata->curr_path) + HDstrlen(link_name) + 2);
- HDassert(link_path);
- HDstrcpy(link_path, udata->curr_path);
- HDstrcat(link_path, "/");
- HDstrcat(link_path, link_name);
+ /* Create the full path name for the link */
+ full_name = HDmalloc(HDstrlen(path) + 2);
+ *full_name = '/';
+ HDstrcpy(full_name + 1, path);
/* Perform the correct action for different types of links */
if(linfo->type == H5L_TYPE_HARD) {
H5O_info_t oinfo;
/* Get information about the object */
- if(H5Oget_info_by_name(loc_id, link_name, &oinfo, H5P_DEFAULT) < 0)
+ if(H5Oget_info_by_name(loc_id, path, &oinfo, H5P_DEFAULT) < 0)
return(H5_ITER_ERROR);
/* If the object has multiple links, add it to the list of addresses
* already visited, if it isn't there already
*/
- if(oinfo.rc > 1) {
- already_visited = trav_addr_visited(udata->seen, oinfo.addr);
- if(!already_visited)
- trav_addr_add(udata->seen, oinfo.addr);
- } /* end if */
-
- /* Check if object is a group, for later */
- is_group = (oinfo.type == H5O_TYPE_GROUP) ? TRUE : FALSE;
+ if(oinfo.rc > 1)
+ if(NULL == (already_visited = trav_addr_visited(udata->seen, oinfo.addr)))
+ trav_addr_add(udata->seen, oinfo.addr, full_name);
/* Make 'visit object' callback */
if(udata->visitor->visit_obj)
- (*udata->visitor->visit_obj)(link_path, &oinfo, already_visited, udata->visitor->udata);
+ (*udata->visitor->visit_obj)(full_name, &oinfo, already_visited, udata->visitor->udata);
} /* end if */
else {
/* Make 'visit link' callback */
if(udata->visitor->visit_lnk)
- (*udata->visitor->visit_lnk)(link_path, linfo, udata->visitor->udata);
+ (*udata->visitor->visit_lnk)(full_name, linfo, udata->visitor->udata);
} /* end else */
- /* Check for group that we haven't visited yet & recurse */
- if(is_group && !already_visited) {
- const char *prev_path = udata->curr_path; /* Previous path to link's parent group */
-
- /* Set current path to this object */
- udata->curr_path = link_path;
-
- /* Iterate over all links in group object */
- if(H5Literate_by_name(loc_id, link_name, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, udata, H5P_DEFAULT) < 0)
- return(H5_ITER_ERROR);
-
- /* Restore path in udata */
- udata->curr_path = prev_path;
- } /* end if */
-
- /* Free path name for current link/object */
- HDfree(link_path);
+ HDfree(full_name);
return(H5_ITER_CONT);
} /* end traverse_cb() */
@@ -217,39 +193,58 @@ traverse_cb(hid_t loc_id, const char *link_name, const H5L_info_t *linfo,
*-------------------------------------------------------------------------
*/
static int
-traverse(hid_t file_id, const trav_visitor_t *visitor)
+traverse(hid_t file_id, const char *grp_name, hbool_t visit_start,
+ hbool_t recurse, const trav_visitor_t *visitor)
{
- H5O_info_t oinfo; /* Object info for root group */
- trav_addr_t seen; /* List of addresses seen */
- trav_ud_traverse_t udata; /* User data for iteration callback */
+ H5O_info_t oinfo; /* Object info for starting group */
- /* Get info for root group */
- if(H5Oget_info(file_id, &oinfo) < 0)
+ /* Get info for starting object */
+ if(H5Oget_info_by_name(file_id, grp_name, &oinfo, H5P_DEFAULT) < 0)
return -1;
- /* Visit the root group of the file */
- (*visitor->visit_obj)("/", &oinfo, FALSE, visitor->udata);
+ /* Visit the starting object */
+ if(visit_start && visitor->visit_obj)
+ (*visitor->visit_obj)(grp_name, &oinfo, NULL, visitor->udata);
- /* Init addresses seen */
- seen.nused = seen.nalloc = 0;
- seen.addrs = NULL;
+ /* Go visiting, if the object is a group */
+ if(oinfo.type == H5O_TYPE_GROUP) {
+ trav_addr_t seen; /* List of addresses seen */
+ trav_ud_traverse_t udata; /* User data for iteration callback */
- /* Check for multiple links to root group */
- if(oinfo.rc > 1)
- trav_addr_add(&seen, oinfo.addr);
+ /* Init addresses seen */
+ seen.nused = seen.nalloc = 0;
+ seen.objs = NULL;
- /* Set up user data structure */
- udata.seen = &seen;
- udata.curr_path = "";
- udata.visitor = visitor;
+ /* Check for multiple links to top group */
+ if(oinfo.rc > 1)
+ trav_addr_add(&seen, oinfo.addr, grp_name);
- /* Iterate over all links in root group */
- if(H5Literate(file_id, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, &udata) < 0)
- return -1;
+ /* Set up user data structure */
+ udata.seen = &seen;
+ udata.visitor = visitor;
- /* Free visited addresses table */
- if(seen.addrs)
- HDfree(seen.addrs);
+ /* Check for iteration of links vs. visiting all links recursively */
+ if(recurse) {
+ /* Visit all links in group, recursively */
+ if(H5Lvisit_by_name(file_id, grp_name, H5_INDEX_NAME, H5_ITER_INC, traverse_cb, &udata, H5P_DEFAULT) < 0)
+ return -1;
+ } /* end if */
+ else {
+ /* Iterate over links in group */
+ if(H5Literate_by_name(file_id, grp_name, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, &udata, H5P_DEFAULT) < 0)
+ return -1;
+ } /* end else */
+
+ /* Free visited addresses table */
+ if(seen.objs) {
+ size_t u; /* Local index variable */
+
+ /* Free paths to objects */
+ for(u = 0; u < seen.nused; u++)
+ HDfree(seen.objs[u].path);
+ HDfree(seen.objs);
+ } /* end if */
+ } /* end if */
return 0;
}
@@ -301,7 +296,7 @@ trav_info_add(trav_info_t *info, const char *path, h5trav_type_t obj_type)
*/
static int
trav_info_visit_obj(const char *path, const H5O_info_t *oinfo,
- hbool_t UNUSED already_visited, void *udata)
+ const char UNUSED *already_visited, void *udata)
{
/* Add the object to the 'info' struct */
/* (object types map directly to "traversal" types) */
@@ -359,7 +354,7 @@ h5trav_getinfo(hid_t file_id, trav_info_t *info)
info_visitor.udata = info;
/* Traverse all objects in the file, visiting each object & link */
- if(traverse(file_id, &info_visitor) < 0)
+ if(traverse(file_id, "/", TRUE, TRUE, &info_visitor) < 0)
return -1;
return 0;
@@ -470,24 +465,17 @@ trav_info_free(trav_info_t *info)
*/
static int
trav_table_visit_obj(const char *path, const H5O_info_t *oinfo,
- hbool_t already_visited, void *udata)
+ const char *already_visited, void *udata)
{
trav_table_t *table = (trav_table_t *)udata;
/* Check if we've already seen this object */
- if(!already_visited)
+ if(NULL == already_visited)
/* add object to table */
trav_table_add(table, path, oinfo);
- else {
- size_t found; /* Index of original object seen */
-
- /* Look for object in existing table */
- found = trav_table_search(table, oinfo->addr);
- HDassert(found < table->nobjs);
-
+ else
/* Add alias for object to table */
- trav_table_addlink(table, found, path);
- } /* end else */
+ trav_table_addlink(table, oinfo->addr, path);
return(0);
} /* end trav_table_visit_obj() */
@@ -541,7 +529,7 @@ h5trav_gettable(hid_t fid, trav_table_t *table)
table_visitor.udata = table;
/* Traverse all objects in the file, visiting each object & link */
- if(traverse(fid, &table_visitor) < 0)
+ if(traverse(fid, "/", TRUE, TRUE, &table_visitor) < 0)
return -1;
return 0;
}
@@ -670,25 +658,33 @@ trav_table_add(trav_table_t *table,
*/
static void
-trav_table_addlink(trav_table_t *table,
- size_t j /* the object index */,
- const char *path)
+trav_table_addlink(trav_table_t *table, haddr_t objno, const char *path)
{
- size_t new;
+ size_t i; /* Local index variable */
- /* already inserted */
- if(HDstrcmp(table->objs[j].name, path) == 0)
- return;
+ for(i = 0; i < table->nobjs; i++) {
+ if(table->objs[i].objno == objno) {
+ size_t n;
- /* allocate space if necessary */
- if(table->objs[j].nlinks == (unsigned)table->objs[j].sizelinks) {
- table->objs[j].sizelinks = MAX(1, table->objs[j].sizelinks * 2);
- table->objs[j].links = (trav_link_t*)HDrealloc(table->objs[j].links, table->objs[j].sizelinks * sizeof(trav_link_t));
- } /* end if */
+ /* already inserted? */
+ if(HDstrcmp(table->objs[i].name, path) == 0)
+ return;
+
+ /* allocate space if necessary */
+ if(table->objs[i].nlinks == (unsigned)table->objs[i].sizelinks) {
+ table->objs[i].sizelinks = MAX(1, table->objs[i].sizelinks * 2);
+ table->objs[i].links = (trav_link_t*)HDrealloc(table->objs[i].links, table->objs[i].sizelinks * sizeof(trav_link_t));
+ } /* end if */
- /* insert it */
- new = table->objs[j].nlinks++;
- table->objs[j].links[new].new_name = (char *)HDstrdup(path);
+ /* insert it */
+ n = table->objs[i].nlinks++;
+ table->objs[i].links[n].new_name = (char *)HDstrdup(path);
+
+ return;
+ } /* end for */
+ } /* end for */
+
+ HDassert(0 && "object not in table?!?");
}
@@ -809,10 +805,8 @@ void trav_table_free( trav_table_t *table )
*/
static int
trav_print_visit_obj(const char *path, const H5O_info_t *oinfo,
- hbool_t already_visited, void *udata)
+ const char *already_visited, void UNUSED *udata)
{
- trav_print_udata_t *print_udata = (trav_print_udata_t *)udata;
-
/* Print the name of the object */
/* (no new-line, so that objects that we've encountered before can print
* the name of the original object)
@@ -836,26 +830,12 @@ trav_print_visit_obj(const char *path, const H5O_info_t *oinfo,
} /* end switch */
/* Check if we've already seen this object */
- if(!already_visited) {
+ if(NULL == already_visited)
/* Finish printing line about object */
printf("\n");
-
- /* Check if we will encounter another hard link to this object */
- if(oinfo->rc > 1) {
- /* Add object to table */
- trav_table_add(print_udata->table, path, oinfo);
- } /* end if */
- } /* end if */
- else {
- size_t found; /* Index of original object seen */
-
- /* Locate object in table */
- found = trav_table_search(print_udata->table, oinfo->addr);
- HDassert(found < print_udata->table->nobjs);
-
- /* Print the link's destination */
- printf(" -> %s\n", print_udata->table->objs[found].name);
- } /* end else */
+ else
+ /* Print the link's original name */
+ printf(" -> %s\n", already_visited);
return(0);
} /* end trav_print_visit_obj() */
@@ -938,16 +918,11 @@ trav_print_visit_lnk(const char *path, const H5L_info_t *linfo, void *udata)
int
h5trav_print(hid_t fid)
{
- trav_table_t *table = NULL; /* Table for objects w/multiple hard links */
trav_print_udata_t print_udata; /* User data for traversal */
trav_visitor_t print_visitor; /* Visitor structure for printing objects */
- /* Initialize the table */
- trav_table_init(&table);
-
/* Init user data for printing */
print_udata.fid = fid;
- print_udata.table = table;
/* Init visitor structure */
print_visitor.visit_obj = trav_print_visit_obj;
@@ -955,11 +930,42 @@ h5trav_print(hid_t fid)
print_visitor.udata = &print_udata;
/* Traverse all objects in the file, visiting each object & link */
- if(traverse(fid, &print_visitor) < 0)
+ if(traverse(fid, "/", TRUE, TRUE, &print_visitor) < 0)
return -1;
- /* Free table */
- trav_table_free(table);
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5trav_visit
+ *
+ * Purpose: Generic traversal routine for visiting objects and links
+ *
+ * Return: 0, -1 on error
+ *
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
+ *
+ * Date: November 6, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+
+int
+h5trav_visit(hid_t fid, const char *grp_name, hbool_t visit_start,
+ hbool_t recurse, h5trav_obj_func_t visit_obj, h5trav_lnk_func_t visit_lnk,
+ void *udata)
+{
+ trav_visitor_t visitor; /* Visitor structure for objects */
+
+ /* Init visitor structure */
+ visitor.visit_obj = visit_obj;
+ visitor.visit_lnk = visit_lnk;
+ visitor.udata = udata;
+
+ /* Traverse all objects in the file, visiting each object & link */
+ if(traverse(fid, grp_name, visit_start, recurse, &visitor) < 0)
+ return -1;
return 0;
}
diff --git a/tools/lib/h5trav.h b/tools/lib/h5trav.h
index 05bc3cb..5c07331 100644
--- a/tools/lib/h5trav.h
+++ b/tools/lib/h5trav.h
@@ -18,6 +18,12 @@
#include "hdf5.h"
+/* Typedefs for visiting objects */
+typedef herr_t (*h5trav_obj_func_t)(const char *path_name, const H5O_info_t *oinfo,
+ const char *first_seen, void *udata);
+typedef herr_t (*h5trav_lnk_func_t)(const char *path_name, const H5L_info_t *linfo,
+ void *udata);
+
/*-------------------------------------------------------------------------
* public enum to specify type of an object
* the TYPE can be:
@@ -101,6 +107,14 @@ extern "C" {
#endif
/*-------------------------------------------------------------------------
+ * "h5trav general" public functions
+ *-------------------------------------------------------------------------
+ */
+int h5trav_visit(hid_t file_id, const char *grp_name, hbool_t visit_start,
+ hbool_t recurse, h5trav_obj_func_t visit_obj, h5trav_lnk_func_t visit_lnk,
+ void *udata);
+
+/*-------------------------------------------------------------------------
* "h5trav info" public functions
*-------------------------------------------------------------------------
*/
diff --git a/tools/testfiles/h5copytst.out.ls b/tools/testfiles/h5copytst.out.ls
index c4d1778..785c3f0 100644
--- a/tools/testfiles/h5copytst.out.ls
+++ b/tools/testfiles/h5copytst.out.ls
@@ -2,6 +2,9 @@
Expected output for 'h5ls ../testfiles/h5copytst.out.h5'
#############################
Opened "../testfiles/h5copytst.out.h5" with sec2 driver.
+/ Group
+ Location: 1:96
+ Links: 1
/A Group
Location: 1:90344
Links: 1
diff --git a/tools/testfiles/h5mkgrp_nested.ls b/tools/testfiles/h5mkgrp_nested.ls
index 2b9fb25..472656d 100644
--- a/tools/testfiles/h5mkgrp_nested.ls
+++ b/tools/testfiles/h5mkgrp_nested.ls
@@ -2,6 +2,9 @@
Expected output for 'h5ls ../testfiles/h5mkgrp_nested.h5'
#############################
Opened "../testfiles/h5mkgrp_nested.h5" with sec2 driver.
+/ Group
+ Location: 1:96
+ Links: 1
/one Group
Location: 1:800
Links: 1
diff --git a/tools/testfiles/h5mkgrp_nested_latest.ls b/tools/testfiles/h5mkgrp_nested_latest.ls
index f0bab6f..c00292d 100644
--- a/tools/testfiles/h5mkgrp_nested_latest.ls
+++ b/tools/testfiles/h5mkgrp_nested_latest.ls
@@ -2,6 +2,10 @@
Expected output for 'h5ls ../testfiles/h5mkgrp_nested_latest.h5'
#############################
Opened "../testfiles/h5mkgrp_nested_latest.h5" with sec2 driver.
+/ Group
+ Location: 1:48
+ Links: 1
+ Modified: XXXX-XX-XX XX:XX:XX XXX
/one Group
Location: 1:195
Links: 1
diff --git a/tools/testfiles/h5mkgrp_nested_mult.ls b/tools/testfiles/h5mkgrp_nested_mult.ls
index 4fccd83..6a22ffd 100644
--- a/tools/testfiles/h5mkgrp_nested_mult.ls
+++ b/tools/testfiles/h5mkgrp_nested_mult.ls
@@ -2,6 +2,9 @@
Expected output for 'h5ls ../testfiles/h5mkgrp_nested_mult.h5'
#############################
Opened "../testfiles/h5mkgrp_nested_mult.h5" with sec2 driver.
+/ Group
+ Location: 1:96
+ Links: 1
/one Group
Location: 1:800
Links: 1
diff --git a/tools/testfiles/h5mkgrp_nested_mult_latest.ls b/tools/testfiles/h5mkgrp_nested_mult_latest.ls
index 7835050..0b19ff9 100644
--- a/tools/testfiles/h5mkgrp_nested_mult_latest.ls
+++ b/tools/testfiles/h5mkgrp_nested_mult_latest.ls
@@ -2,6 +2,10 @@
Expected output for 'h5ls ../testfiles/h5mkgrp_nested_mult_latest.h5'
#############################
Opened "../testfiles/h5mkgrp_nested_mult_latest.h5" with sec2 driver.
+/ Group
+ Location: 1:48
+ Links: 1
+ Modified: XXXX-XX-XX XX:XX:XX XXX
/one Group
Location: 1:195
Links: 1
diff --git a/tools/testfiles/h5mkgrp_several.ls b/tools/testfiles/h5mkgrp_several.ls
index dcbe3eb..bbf5c92 100644
--- a/tools/testfiles/h5mkgrp_several.ls
+++ b/tools/testfiles/h5mkgrp_several.ls
@@ -2,6 +2,9 @@
Expected output for 'h5ls ../testfiles/h5mkgrp_several.h5'
#############################
Opened "../testfiles/h5mkgrp_several.h5" with sec2 driver.
+/ Group
+ Location: 1:96
+ Links: 1
/one Group
Location: 1:800
Links: 1
diff --git a/tools/testfiles/h5mkgrp_several_latest.ls b/tools/testfiles/h5mkgrp_several_latest.ls
index c59107e..a3b5224 100644
--- a/tools/testfiles/h5mkgrp_several_latest.ls
+++ b/tools/testfiles/h5mkgrp_several_latest.ls
@@ -2,6 +2,10 @@
Expected output for 'h5ls ../testfiles/h5mkgrp_several_latest.h5'
#############################
Opened "../testfiles/h5mkgrp_several_latest.h5" with sec2 driver.
+/ Group
+ Location: 1:48
+ Links: 1
+ Modified: XXXX-XX-XX XX:XX:XX XXX
/one Group
Location: 1:195
Links: 1
diff --git a/tools/testfiles/h5mkgrp_single.ls b/tools/testfiles/h5mkgrp_single.ls
index 1f7e828..e9932f7 100644
--- a/tools/testfiles/h5mkgrp_single.ls
+++ b/tools/testfiles/h5mkgrp_single.ls
@@ -2,6 +2,9 @@
Expected output for 'h5ls ../testfiles/h5mkgrp_single.h5'
#############################
Opened "../testfiles/h5mkgrp_single.h5" with sec2 driver.
+/ Group
+ Location: 1:96
+ Links: 1
/single Group
Location: 1:800
Links: 1
diff --git a/tools/testfiles/h5mkgrp_single_latest.ls b/tools/testfiles/h5mkgrp_single_latest.ls
index 7f5ee72..b6e6ea4 100644
--- a/tools/testfiles/h5mkgrp_single_latest.ls
+++ b/tools/testfiles/h5mkgrp_single_latest.ls
@@ -2,6 +2,10 @@
Expected output for 'h5ls ../testfiles/h5mkgrp_single_latest.h5'
#############################
Opened "../testfiles/h5mkgrp_single_latest.h5" with sec2 driver.
+/ Group
+ Location: 1:48
+ Links: 1
+ Modified: XXXX-XX-XX XX:XX:XX XXX
/latest Group
Location: 1:195
Links: 1
diff --git a/tools/testfiles/tall-2.ls b/tools/testfiles/tall-2.ls
index 5513214..2e4cd37 100644
--- a/tools/testfiles/tall-2.ls
+++ b/tools/testfiles/tall-2.ls
@@ -1,6 +1,7 @@
#############################
output for 'h5ls -w80 -r -d tall.h5'
#############################
+/ Group
/g1 Group
/g1/g1.1 Group
/g1/g1.1/dset1.1.1 Dataset {10, 10}
diff --git a/tools/testfiles/tarray1.ls b/tools/testfiles/tarray1.ls
index 83a51a8..60c002d 100644
--- a/tools/testfiles/tarray1.ls
+++ b/tools/testfiles/tarray1.ls
@@ -1,6 +1,7 @@
#############################
output for 'h5ls -w80 -r -d tarray1.h5'
#############################
+/ Group
/Dataset1 Dataset {4}
Data:
(0) [0,1,2,3], [10,11,12,13], [20,21,22,23], [30,31,32,33]
diff --git a/tools/testfiles/tattr2.ls b/tools/testfiles/tattr2.ls
index 88b24cd..0448868 100644
--- a/tools/testfiles/tattr2.ls
+++ b/tools/testfiles/tattr2.ls
@@ -2,149 +2,6 @@
output for 'h5ls -w80 -v -S tattr2.h5'
#############################
Opened "tattr2.h5" with sec2 driver.
- Attribute: array {2}
- Type: [3] 32-bit little-endian integer
- Data: [1,2,3], [4,5,6]
- Attribute: array2D {3, 2}
- Type: [3] 32-bit little-endian integer
- Data:
- (0,0) [1,2,3], [4,5,6], [7,8,9], [10,11,12], [13,14,15], [16,17,18]
- Attribute: array3D {4, 3, 2}
- Type: [3] 32-bit little-endian integer
- Data:
- (0,0,0) [1,2,3], [4,5,6], [7,8,9], [10,11,12], [13,14,15],
- (0,2,1) [16,17,18], [19,20,21], [22,23,24], [25,26,27], [28,29,30],
- (1,2,0) [31,32,33], [34,35,36], [37,38,39], [40,41,42], [43,44,45],
- (2,1,1) [46,47,48], [49,50,51], [52,53,54], [55,56,57], [58,59,60],
- (3,1,0) [61,62,63], [64,65,66], [67,68,69], [70,71,72]
- Attribute: bitfield {2}
- Type: 8-bit bitfield
- Data: 0x01, 0x02
- Attribute: bitfield2D {3, 2}
- Type: 8-bit bitfield
- Data:
- (0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
- Attribute: bitfield3D {4, 3, 2}
- Type: 8-bit bitfield
- Data:
- (0,0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
- (1,2,0) 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
- (3,1,0) 0x15, 0x16, 0x17, 0x18
- Attribute: compound {2}
- Type: struct {
- "a" +0 8-bit integer
- "b" +4 IEEE 64-bit little-endian float
- } 12 bytes
- Data: {1, 2}, {3, 4}
- Attribute: compound2D {3, 2}
- Type: struct {
- "a" +0 8-bit integer
- "b" +4 IEEE 64-bit little-endian float
- } 12 bytes
- Data:
- (0,0) {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}
- Attribute: compound3D {4, 3, 2}
- Type: struct {
- "a" +0 8-bit integer
- "b" +4 IEEE 64-bit little-endian float
- } 12 bytes
- Data:
- (0,0,0) {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}, {13,
- (1,0,0) 14}, {15, 16}, {17, 18}, {19, 20}, {21, 22}, {23, 24},
- (2,0,0) {25, 26}, {27, 28}, {29, 30}, {31, 32}, {33, 34}, {35, 36},
- (3,0,0) {37, 38}, {39, 40}, {41, 42}, {43, 44}, {45, 46}, {47, 48}
- Attribute: enum {2}
- Type: enum 32-bit little-endian integer {
- RED = 0
- GREEN = 1
- }
- Data: RED, RED
- Attribute: enum2D {3, 2}
- Type: enum 32-bit little-endian integer {
- RED = 0
- GREEN = 1
- }
- Data:
- (0,0) RED, RED, RED, RED, RED, RED
- Attribute: enum3D {4, 3, 2}
- Type: enum 32-bit little-endian integer {
- RED = 0
- GREEN = 1
- }
- Data:
- (0,0,0) RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED,
- (2,0,0) RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED
- Attribute: float {2}
- Type: IEEE 32-bit little-endian float
- Data: 1, 2
- Attribute: float2D {3, 2}
- Type: IEEE 32-bit little-endian float
- Data:
- (0,0) 1, 2, 3, 4, 5, 6
- Attribute: float3D {4, 3, 2}
- Type: IEEE 32-bit little-endian float
- Data:
- (0,0,0) 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- (2,2,1) 18, 19, 20, 21, 22, 23, 24
- Attribute: integer {2}
- Type: 32-bit little-endian integer
- Data: 1, 2
- Attribute: integer2D {3, 2}
- Type: 32-bit little-endian integer
- Data:
- (0,0) 1, 2, 3, 4, 5, 6
- Attribute: integer3D {4, 3, 2}
- Type: 32-bit little-endian integer
- Data:
- (0,0,0) 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- (2,2,1) 18, 19, 20, 21, 22, 23, 24
- Attribute: opaque {2}
- Type: 1-byte opaque type
- (tag = "1-byte opaque type")
- Data: 0x01, 0x02
- Attribute: opaque2D {3, 2}
- Type: 1-byte opaque type
- (tag = "1-byte opaque type")
- Data:
- (0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
- Attribute: opaque3D {4, 3, 2}
- Type: 1-byte opaque type
- (tag = "1-byte opaque type")
- Data:
- (0,0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
- (1,2,0) 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
- (3,1,0) 0x15, 0x16, 0x17, 0x18
- Attribute: string {2}
- Type: 2-byte null-terminated ASCII string
- Data: "ab", "de"
- Attribute: string2D {3, 2}
- Type: 2-byte null-terminated ASCII string
- Data:
- (0,0) "ab", "cd", "ef", "gh", "ij", "kl"
- Attribute: string3D {4, 3, 2}
- Type: 2-byte null-terminated ASCII string
- Data:
- (0,0,0) "ab", "cd", "ef", "gh", "ij", "kl", "mn", "pq", "rs", "tu",
- (1,2,0) "vw", "xz", "AB", "CD", "EF", "GH", "IJ", "KL", "MN", "PQ",
- (3,1,0) "RS", "TU", "VW", "XZ"
- Attribute: vlen {2}
- Type: variable length of
- 32-bit little-endian integer
- Data: (1), (2,3)
- Attribute: vlen2D {3, 2}
- Type: variable length of
- 32-bit little-endian integer
- Data:
- (0,0) (0), (1), (2,3), (4,5), (6,7,8), (9,10,11)
- Attribute: vlen3D {4, 3, 2}
- Type: variable length of
- 32-bit little-endian integer
- Data:
- (0,0,0) (0), (1), (2), (3), (4), (5), (6,7), (8,9), (10,11),
- (1,1,1) (12,13), (14,15), (16,17), (18,19,20), (21,22,23),
- (2,1,0) (24,25,26), (27,28,29), (30,31,32), (33,34,35),
- (3,0,0) (36,37,38,39), (40,41,42,43), (44,45,46,47), (48,49,50,51),
- (3,2,0) (52,53,54,55), (56,57,58,59)
dset Dataset {2/2}
Attribute: array {2}
Type: [3] 32-bit little-endian integer
diff --git a/tools/testfiles/tcomp-1.ls b/tools/testfiles/tcomp-1.ls
index 599fe68..9cfb47d 100644
--- a/tools/testfiles/tcomp-1.ls
+++ b/tools/testfiles/tcomp-1.ls
@@ -1,6 +1,7 @@
#############################
output for 'h5ls -w80 -r -d tcompound.h5'
#############################
+/ Group
/dset1 Dataset {5}
Data:
(0) {0, 0, 1}, {1, 1, 0.5}, {2, 4, 0.333333333333333}, {3, 9, 0.25},
diff --git a/tools/testfiles/tdset-1.ls b/tools/testfiles/tdset-1.ls
index 6853429..b6e4671 100644
--- a/tools/testfiles/tdset-1.ls
+++ b/tools/testfiles/tdset-1.ls
@@ -1,6 +1,7 @@
#############################
output for 'h5ls -w80 -r -d tdset.h5'
#############################
+/ Group
/dset1 Dataset {10, 20}
Data:
(0,0) 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
diff --git a/tools/testfiles/textlink-1.ls b/tools/testfiles/textlink-1.ls
index f92786b..87be5a7 100644
--- a/tools/testfiles/textlink-1.ls
+++ b/tools/testfiles/textlink-1.ls
@@ -1,5 +1,6 @@
#############################
output for 'h5ls -w80 -r textlink.h5'
#############################
+/ Group
/extlink1 -> file: filename path: objname
/extlink2 -> file: anotherfile path: anotherobj
diff --git a/tools/testfiles/tgroup-1.ls b/tools/testfiles/tgroup-1.ls
index 62ebe70..0ca929d 100644
--- a/tools/testfiles/tgroup-1.ls
+++ b/tools/testfiles/tgroup-1.ls
@@ -1,17 +1,29 @@
#############################
output for 'h5ls -w80 -r -g tgroup.h5'
#############################
-/ Group
-/g1 Group
-/g1/g1.1 Group
-/g1/g1.2 Group
-/g2 Group
-/g2/g2.1 Group
-/g2/g2.1/g2.1.1 Group
-/g2/g2.1/g2.1.2 Group
-/g2/g2.1/g2.1.3 Group
-/g3 Group
-/g3/g3.1 Group
-/g3/g3.2 Group
-/g3/g3.3 Group
-/g3/g3.4 Group
+Error: 'recursive' option not compatible with 'group info' option!
+
+usage: h5ls [OPTIONS] [OBJECTS...]
+ OPTIONS
+ -h, -?, --help Print a usage message and exit
+ -a, --address Print addresses for raw data
+ -d, --data Print the values of datasets
+ -e, --errors Show all HDF5 error reporting
+ -f, --full Print full path names instead of base names
+ -g, --group Show information about a group, not its contents
+ -l, --label Label members of compound datasets
+ -r, --recursive List all groups recursively, avoiding cycles
+ -s, --string Print 1-byte integer datasets as ASCII
+ -S, --simple Use a machine-readable output format
+ -wN, --width=N Set the number of columns of output
+ -v, --verbose Generate more verbose output
+ -V, --version Print version number and exit
+ --vfd=DRIVER Use the specified virtual file driver
+ -x, --hexdump Show raw data in hexadecimal format
+
+ OBJECTS
+ Each object consists of an HDF5 file name optionally followed by a
+ slash and an object name within the file (if no object is specified
+ within the file then the contents of the root group are displayed).
+ The file name may include a printf(3C) integer format such as
+ "%05d" to open a file family.
diff --git a/tools/testfiles/tgroup-2.ls b/tools/testfiles/tgroup-2.ls
new file mode 100644
index 0000000..0817d93
--- /dev/null
+++ b/tools/testfiles/tgroup-2.ls
@@ -0,0 +1,4 @@
+#############################
+ output for 'h5ls -w80 -g tgroup.h5/g1'
+#############################
+g1 Group
diff --git a/tools/testfiles/tloop-1.ls b/tools/testfiles/tloop-1.ls
index b9631b7..22cb6c7 100644
--- a/tools/testfiles/tloop-1.ls
+++ b/tools/testfiles/tloop-1.ls
@@ -1,6 +1,7 @@
#############################
output for 'h5ls -w80 -r -d tloop.h5'
#############################
+/ Group
/g1 Group
/g1/g1.1 Group
/g1/g1.1/g2.1 Group, same as /g1
diff --git a/tools/testfiles/tnestcomp-1.ls b/tools/testfiles/tnestcomp-1.ls
index eef41ef..9dc193d 100644
--- a/tools/testfiles/tnestcomp-1.ls
+++ b/tools/testfiles/tnestcomp-1.ls
@@ -1,6 +1,7 @@
#############################
output for 'h5ls -w80 -r -d tnestedcomp.h5'
#############################
+/ Group
/ArrayOfStructures Dataset {10}
Data:
(0) {0, 0, 1, {"A", [-100,100]}}, {1, 1, 0.5, {"B", [-100,100]}},
diff --git a/tools/testfiles/tsaf.ls b/tools/testfiles/tsaf.ls
index 8efc0f2..96d4811 100644
--- a/tools/testfiles/tsaf.ls
+++ b/tools/testfiles/tsaf.ls
@@ -1,6 +1,7 @@
#############################
output for 'h5ls -w80 -r -d tsaf.h5'
#############################
+/ Group
/.DSL_METADATA Dataset {5919/Inf}
Data:
(0) 47, 32, 67, 79, 78, 84, 65, 73, 78, 69, 82, 10, 47, 46, 97, 116,
diff --git a/tools/testfiles/tslink-1.ls b/tools/testfiles/tslink-1.ls
index 05b9bca..4c16958 100644
--- a/tools/testfiles/tslink-1.ls
+++ b/tools/testfiles/tslink-1.ls
@@ -1,5 +1,6 @@
#############################
output for 'h5ls -w80 -r tslink.h5'
#############################
+/ Group
/slink1 -> somevalue
/slink2 -> linkvalue
diff --git a/tools/testfiles/tstr-1.ls b/tools/testfiles/tstr-1.ls
index 1961fd4..8a223cc 100644
--- a/tools/testfiles/tstr-1.ls
+++ b/tools/testfiles/tstr-1.ls
@@ -1,6 +1,7 @@
#############################
output for 'h5ls -w80 -r -d tstr.h5'
#############################
+/ Group
/comp1 Dataset {3, 6}
Data:
(0,0) {[0,1,4,9,16,25,36,49,64,81,1,4,9,16,25,36,49,64,81,100,4,9,16,
diff --git a/tools/testfiles/tudlink-1.ls b/tools/testfiles/tudlink-1.ls
index e83fce7..b8578ce 100644
--- a/tools/testfiles/tudlink-1.ls
+++ b/tools/testfiles/tudlink-1.ls
@@ -1,5 +1,6 @@
#############################
output for 'h5ls -w80 -r tudlink.h5'
#############################
+/ Group
/udlink1 -> cannot follow UD links
/udlink2 -> cannot follow UD links
diff --git a/tools/testfiles/tvldtypes1.ls b/tools/testfiles/tvldtypes1.ls
index cf1688e..4c4c162 100644
--- a/tools/testfiles/tvldtypes1.ls
+++ b/tools/testfiles/tvldtypes1.ls
@@ -1,6 +1,7 @@
#############################
output for 'h5ls -w80 -r -d tvldtypes1.h5'
#############################
+/ Group
/Dataset1.0 Dataset {4}
Data:
(0) (0), (10,11), (20,21,22), (30,31,32,33)