summaryrefslogtreecommitdiffstats
path: root/tools/lib/h5trav.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lib/h5trav.c')
-rw-r--r--tools/lib/h5trav.c1305
1 files changed, 678 insertions, 627 deletions
diff --git a/tools/lib/h5trav.c b/tools/lib/h5trav.c
index 6ff68d5..65cca66 100644
--- a/tools/lib/h5trav.c
+++ b/tools/lib/h5trav.c
@@ -18,255 +18,357 @@
#include "H5private.h"
/*-------------------------------------------------------------------------
- * local functions
+ * local typedefs
*-------------------------------------------------------------------------
*/
-static int traverse( hid_t loc_id,
- const char *group_name,
- trav_table_t *table,
- trav_info_t *info,
- int *idx,
- int print);
+typedef struct trav_addr_t {
+ size_t nalloc;
+ size_t nused;
+ haddr_t *addrs;
+} 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);
+ 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;
-static hssize_t get_nnames( hid_t loc_id,
- const char *group_name );
+/*-------------------------------------------------------------------------
+ * local functions
+ *-------------------------------------------------------------------------
+ */
+static void trav_table_add(trav_table_t *table,
+ const char *objname,
+ const H5O_info_t *oinfo);
-static herr_t get_name_type( hid_t loc_id,
- const char *group_name,
- int idx,
- char **name,
- H5G_obj_t *type );
+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 */,
+ const char *path);
/*-------------------------------------------------------------------------
* "h5trav info" public functions. used in h5diff
*-------------------------------------------------------------------------
*/
+
/*-------------------------------------------------------------------------
- * Function: h5trav_getinfo
+ * Function: trav_addr_add
*
- * Purpose: get an array of "trav_info_t" , containing the name and type of
- * objects in the file
+ * Purpose: Add a hardlink address to visited data structure
*
- * Return: number of object names in file
+ * Return: void
*
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
*
- * Date: November 6, 2002
+ * Date: September 1, 2007
*
*-------------------------------------------------------------------------
*/
-
-int h5trav_getinfo(hid_t file_id,
- trav_info_t *info,
- int print )
+static void
+trav_addr_add(trav_addr_t *visited, haddr_t addr)
{
- trav_table_t *table = NULL;
- int nnames = 0;
-
- /* init table */
- trav_table_init(&table);
+ size_t idx; /* Index of address to use */
- /* iterate starting on the root group */
- if((nnames = traverse(file_id, "/", table, info, &nnames, print)) < 0)
- return -1;
+ /* 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));
+ } /* end if */
- /* free table */
- trav_table_free(table);
-
- return nnames;
-}
+ /* Append it */
+ idx = visited->nused++;
+ visited->addrs[idx] = addr;
+} /* end trav_addr_add() */
+
/*-------------------------------------------------------------------------
- * Function: h5trav_getindex
+ * Function: trav_addr_visited
*
- * Purpose: get index of OBJ in list
+ * Purpose: Check if an address has already been visited
*
- * Return: index, -1 if not found
+ * Return: TRUE/FALSE
*
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
*
- * Date: May 9, 2003
+ * Date: September 1, 2007
*
*-------------------------------------------------------------------------
*/
-
-int h5trav_getindex( const char *obj, int nobjs, trav_info_t *info )
+static hbool_t
+trav_addr_visited(trav_addr_t *visited, haddr_t addr)
{
- char *pdest;
- int result;
- int i;
-
- for ( i = 0; i < nobjs; i++)
- {
- if ( strcmp(obj,info[i].name)==0 )
- return i;
-
- pdest = strstr( info[i].name, obj );
- result = (int)(pdest - info[i].name);
-
- /* found at position 1, meaning without '/' */
- if( pdest != NULL && result==1 )
- return i;
- }
- return -1;
-}
+ size_t u; /* Local index variable */
+
+ /* Look for address */
+ for(u = 0; u < visited->nused; u++)
+ /* Check for address already in array */
+ if(visited->addrs[u] == addr)
+ return(TRUE);
+
+ /* Didn't find address */
+ return(FALSE);
+} /* end trav_addr_visited() */
+
/*-------------------------------------------------------------------------
- * Function: h5trav_freeinfo
+ * Function: traverse_cb
*
- * Purpose: free info memory
+ * Purpose: Iterator callback for traversing objects in file
+ *
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
+ *
+ * Date: September 1, 2007
*
*-------------------------------------------------------------------------
*/
+static herr_t
+traverse_cb(hid_t loc_id, const char *link_name, 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 */
+
+ /* 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);
+
+ /* 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(loc_id, link_name, &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;
+
+ /* Make 'visit object' callback */
+ (*udata->visitor->visit_obj)(link_path, &oinfo, already_visited, udata->visitor->udata);
+ } /* end if */
+ else {
+ /* Make 'visit link' callback */
+ (*udata->visitor->visit_lnk)(link_path, 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(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);
+
+ return(H5_ITER_CONT);
+} /* end traverse_cb() */
-void h5trav_freeinfo( trav_info_t *info, int nobjs )
+
+/*-------------------------------------------------------------------------
+ * Function: traverse
+ *
+ * Purpose: Iterate over all the objects/links in a file. Conforms to the
+ * "visitor" pattern.
+ *
+ * Return: 0 on success, -1 on failure
+ *
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
+ *
+ * Date: September 1, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+traverse(hid_t file_id, const trav_visitor_t *visitor)
{
- int i;
- if ( info )
- {
- for ( i = 0; i < nobjs; i++)
- {
- if (info[i].name)
- HDfree( info[i].name );
- }
- HDfree(info);
- }
+ 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 */
+
+ /* Get info for root group */
+ if(H5Oget_info(file_id, "/", &oinfo, H5P_DEFAULT) < 0)
+ return -1;
+
+ /* Visit the root group of the file */
+ (*visitor->visit_obj)("/", &oinfo, FALSE, visitor->udata);
+
+ /* Init addresses seen */
+ seen.nused = seen.nalloc = 0;
+ seen.addrs = NULL;
+
+ /* Check for multiple links to root group */
+ if(oinfo.rc > 1)
+ trav_addr_add(&seen, oinfo.addr);
+
+ /* Set up user data structure */
+ udata.seen = &seen;
+ udata.curr_path = "";
+ udata.visitor = visitor;
+
+ /* Iterate over all links in root group */
+ if(H5Literate(file_id, "/", H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, &udata, H5P_DEFAULT) < 0)
+ return -1;
+
+ /* Free visited addresses table */
+ if(seen.addrs)
+ HDfree(seen.addrs);
+
+ return 0;
}
+
/*-------------------------------------------------------------------------
- * Function: h5trav_printinfo
+ * Function: trav_info_add
*
- * Purpose: print list of names in file
+ * Purpose: Add a link path & type to info struct
*
* Return: void
*
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
*
- * Date: May 9, 2003
+ * Date: September 1, 2007
*
*-------------------------------------------------------------------------
*/
-void h5trav_printinfo(int nobjs, trav_info_t *travi)
+static void
+trav_info_add(trav_info_t *info, const char *path, H5G_obj_t obj_type)
{
- int i;
- for ( i = 0; i < nobjs; i++)
- {
- switch ( travi[i].type )
- {
- case H5G_GROUP:
- printf(" %-10s %s\n", "group", travi[i].name );
- break;
- case H5G_DATASET:
- printf(" %-10s %s\n", "dataset", travi[i].name );
- break;
- case H5G_TYPE:
- printf(" %-10s %s\n", "datatype", travi[i].name );
- break;
- case H5G_LINK:
- printf(" %-10s %s\n", "link", travi[i].name );
- break;
- case H5G_UDLINK:
- printf(" %-10s %s\n", "User defined link", travi[i].name );
- break;
- default:
- printf(" %-10s %s\n", "User defined object", travi[i].name );
- break;
- }
- }
-}
+ size_t idx; /* Index of address to use */
+ /* Allocate space if necessary */
+ if(info->nused == info->nalloc) {
+ info->nalloc = MAX(1, info->nalloc * 2);;
+ info->paths = (trav_path_t *)HDrealloc(info->paths, info->nalloc * sizeof(trav_path_t));
+ } /* end if */
+
+ /* Append it */
+ idx = info->nused++;
+ info->paths[idx].path = HDstrdup(path);
+ info->paths[idx].type = obj_type;
+} /* end trav_info_add() */
+
+
/*-------------------------------------------------------------------------
- * "h5trav table" public functions. used in h5repack
+ * Function: trav_info_visit_obj
+ *
+ * Purpose: Callback for visiting object, with 'info' structure
+ *
+ * Return: 0 on success, -1 on failure
+ *
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
+ *
+ * Date: September 1, 2007
+ *
*-------------------------------------------------------------------------
*/
+static int
+trav_info_visit_obj(const char *path, const H5O_info_t *oinfo,
+ hbool_t UNUSED already_visited, void *udata)
+{
+ /* Add the object to the 'info' struct */
+ /* (object types map directly to "group" types) */
+ trav_info_add((trav_info_t *)udata, path, (H5G_obj_t)oinfo->type);
+
+ return(0);
+} /* end trav_info_visit_obj() */
+
/*-------------------------------------------------------------------------
- * Function: h5trav_getindext
+ * Function: trav_info_visit_lnk
*
- * Purpose: get index of NAME in list
+ * Purpose: Callback for visiting link, with 'info' structure
*
- * Return: index, -1 if not found
+ * Return: 0 on success, -1 on failure
*
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
*
- * Date: December 18, 2003
+ * Date: September 1, 2007
*
*-------------------------------------------------------------------------
*/
-
-int h5trav_getindext(const char *name, trav_table_t *table)
+static int
+trav_info_visit_lnk(const char *path, const H5L_info_t *linfo, void *udata)
{
- char *pdest;
- int result;
- unsigned int i, j;
-
- for ( i = 0; i < table->nobjs; i++)
- {
- if ( strcmp(name,table->objs[i].name)==0 )
- return i;
-
- pdest = strstr( table->objs[i].name, name );
- result = (int)(pdest - table->objs[i].name);
-
- /* found at position 1, meaning without '/' */
- if( pdest != NULL && result==1 && strlen(table->objs[i].name)-1==strlen(name))
- return i;
-
- /* search also in the list of links */
- if (table->objs[i].nlinks)
- {
- for ( j=0; j<table->objs[i].nlinks; j++)
- {
- if ( strcmp(name,table->objs[i].links[j].new_name)==0 )
- return i;
-
- pdest = strstr( table->objs[i].links[j].new_name, name );
- result = (int)(pdest - table->objs[i].links[j].new_name);
-
- /* found at position 1, meaning without '/' */
- if( pdest != NULL && result==1 )
- return i;
-
- }
- }
-
- }
- return -1;
-}
+ /* Add the link to the 'info' struct */
+ trav_info_add((trav_info_t *)udata, path, ((linfo->type == H5L_TYPE_SOFT) ? H5G_LINK : H5G_UDLINK));
+ return(0);
+} /* end trav_info_visit_lnk() */
+
+
/*-------------------------------------------------------------------------
- * Function: h5trav_gettable
+ * Function: h5trav_getinfo
*
- * Purpose: get the trav_table_t struct
+ * Purpose: get an array of "trav_info_t" , containing the name and type of
+ * objects in the file
*
- * Return: 0, -1 on error
+ * Return: number of object names in file
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
*
- * Date: December 17, 2003
+ * Date: November 6, 2002
*
*-------------------------------------------------------------------------
*/
-
-int h5trav_gettable(hid_t fid, trav_table_t *travt)
+int
+h5trav_getinfo(hid_t file_id, trav_info_t *info)
{
- int nnames = 0;
+ trav_visitor_t info_visitor; /* Visitor structure for trav_info_t's */
- /* iterate starting on the root group */
- if((nnames = traverse(fid, "/", travt, NULL, &nnames, 0)) < 0)
+ /* Init visitor structure */
+ info_visitor.visit_obj = trav_info_visit_obj;
+ info_visitor.visit_lnk = trav_info_visit_lnk;
+ info_visitor.udata = info;
+
+ /* Traverse all objects in the file, visiting each object & link */
+ if(traverse(file_id, &info_visitor) < 0)
return -1;
return 0;
}
/*-------------------------------------------------------------------------
- * Function: h5trav_printtable
+ * Function: h5trav_getindex
*
- * Purpose: print list of objects in file
+ * Purpose: get index of OBJ in list
*
- * Return: void
+ * Return: index, -1 if not found
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
*
@@ -274,403 +376,219 @@ int h5trav_gettable(hid_t fid, trav_table_t *travt)
*
*-------------------------------------------------------------------------
*/
-void h5trav_printtable(trav_table_t *table)
+
+ssize_t
+h5trav_getindex(const trav_info_t *info, const char *obj)
{
- unsigned int i, j;
-
- for ( i = 0; i < table->nobjs; i++)
- {
- switch ( table->objs[i].type )
- {
- case H5G_GROUP:
- printf(" %-10s %s\n", "group", table->objs[i].name );
- break;
- case H5G_DATASET:
- printf(" %-10s %s\n", "dataset", table->objs[i].name );
- break;
- case H5G_TYPE:
- printf(" %-10s %s\n", "datatype", table->objs[i].name );
- break;
- case H5G_LINK:
- printf(" %-10s %s\n", "link", table->objs[i].name );
- break;
- default:
- printf(" %-10s %s\n", "User defined object", table->objs[i].name );
- break;
- }
-
- if (table->objs[i].nlinks)
- {
- for ( j=0; j<table->objs[i].nlinks; j++)
- {
- printf(" %-10s %s\n", " hardlink", table->objs[i].links[j].new_name );
- }
- }
-
- }
-}
+ size_t u; /* Local index variable */
+
+ /* Loop over all paths in 'info' struct, looking for object */
+ for(u = 0; u < info->nused; u++) {
+ /* Check for object name having full path (with leading '/') */
+ if(HDstrcmp(obj, info->paths[u].path) == 0)
+ return((ssize_t)u);
+
+ /* Check for object name without leading '/' */
+ if(HDstrcmp(obj, (info->paths[u].path + 1)) == 0)
+ return((ssize_t)u);
+ } /* end for */
+
+ return((ssize_t)-1);
+} /* end h5trav_getindex() */
/*-------------------------------------------------------------------------
- * Function: get_nnames
+ * Function: trav_info_init
*
- * Purpose: Counts the number of names in the group GROUP_NAME
+ * Purpose: Initialize the info
*
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
- *
- * Date: October 10, 2002
+ * Return: void
*
- * 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.
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
*
- * Failure: Negative if something goes wrong within the
- * library, or the negative value returned by one
- * of the operators.
+ * Date: September 6, 2007
*
*-------------------------------------------------------------------------
*/
-static hssize_t get_nnames( hid_t loc_id, const char *group_name )
+void
+trav_info_init(trav_info_t **_info)
{
- hid_t gid;
- hsize_t nobjs = 0;
+ trav_info_t *info = (trav_info_t *)HDmalloc(sizeof(trav_info_t));
- /* Open the group */
- if((gid = H5Gopen2(loc_id, group_name, H5P_DEFAULT)) < 0)
- return(-1);
+ /* Init info structure */
+ info->nused = info->nalloc = 0;
+ info->paths = NULL;
- /* Retrieve the number of objects in it */
- if(H5Gget_num_objs(gid, &nobjs) < 0)
- return(-1);
+ *_info = info;
+} /* end trav_info_init() */
- /* Close the group */
- if(H5Gclose(gid) < 0)
- return(-1);
+
+/*-------------------------------------------------------------------------
+ * Function: trav_info_free
+ *
+ * Purpose: free info memory
+ *
+ *-------------------------------------------------------------------------
+ */
- return((hssize_t)nobjs);
-}
+void
+trav_info_free(trav_info_t *info)
+{
+ size_t u; /* Local index variable */
+
+ if(info) {
+ /* Free path names */
+ for(u = 0; u < info->nused; u++)
+ HDfree(info->paths[u].path);
+ HDfree(info->paths);
+ HDfree(info);
+ } /* end if */
+} /* end trav_info_free() */
/*-------------------------------------------------------------------------
- * Function: opget_info
- *
- * Purpose: operator function
+ * "h5trav table" public functions. used in h5repack
+ *-------------------------------------------------------------------------
+ */
+
+
+/*-------------------------------------------------------------------------
+ * Function: trav_table_visit_obj
*
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ * Purpose: Callback for visiting object, with 'table' sructure
*
- * Date: October 10, 2002
+ * Return: 0 on success, -1 on failure
*
- * Comments:
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
*
- * Modifications:
+ * Date: September 1, 2007
*
*-------------------------------------------------------------------------
*/
-
-static herr_t
-opget_info(hid_t loc_id, const char *name, const H5L_info_t *linfo, void *op_data)
+static int
+trav_table_visit_obj(const char *path, const H5O_info_t *oinfo,
+ hbool_t already_visited, void *udata)
{
- H5G_stat_t statbuf;
+ trav_table_t *table = (trav_table_t *)udata;
- if(H5Gget_objinfo(loc_id, name, FALSE, &statbuf) < 0)
- return -1;
+ /* Check if we've already seen this object */
+ if(!already_visited)
+ /* add object to table */
+ trav_table_add(table, path, oinfo);
+ else {
+ size_t found; /* Index of original object seen */
- ((trav_info_t *)op_data)->type = statbuf.type;
- ((trav_info_t *)op_data)->name = (char *)HDstrdup(name);
+ /* Look for object in existing table */
+ found = trav_table_search(table, oinfo->addr);
+ HDassert(found < table->nobjs);
- /* Define 1 for return. This will cause the iterator to stop */
- return 1;
-}
+ /* Add alias for object to table */
+ trav_table_addlink(table, found, path);
+ } /* end else */
+ return(0);
+} /* end trav_table_visit_obj() */
+
/*-------------------------------------------------------------------------
- * Function: get_name_type
+ * Function: trav_table_visit_lnk
*
- * Purpose:
+ * Purpose: Callback for visiting link, with 'table' sructure
*
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ * Return: 0 on success, -1 on failure
+ *
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
+ *
+ * Date: September 1, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+trav_table_visit_lnk(const char *path, const H5L_info_t UNUSED *linfo, void *udata)
+{
+ /* Add the link to the 'table' struct */
+ trav_table_add((trav_table_t *)udata, path, NULL);
+
+ return(0);
+} /* end trav_table_visit_lnk() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5trav_gettable
*
- * Date: October 10, 2002
+ * Purpose: get the trav_table_t struct
*
- * 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.
+ * Return: 0, -1 on error
*
- * Failure: Negative if something goes wrong within the
- * library, or the negative value returned by one
- * of the operators.
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ *
+ * Date: December 17, 2003
*
*-------------------------------------------------------------------------
*/
-static herr_t get_name_type( hid_t loc_id,
- const char *group_name,
- int _idx,
- char **name,
- H5G_obj_t *type )
+int
+h5trav_gettable(hid_t fid, trav_table_t *table)
{
- trav_info_t info;
- hsize_t idx = (hsize_t)_idx;
-
- if(H5Literate(loc_id, group_name, H5_INDEX_NAME, H5_ITER_INC, &idx, opget_info, (void *)&info, H5P_DEFAULT) < 0)
- return -1;
+ trav_visitor_t table_visitor; /* Visitor structure for trav_table_t's */
- *name = info.name;
- *type = info.type;
+ /* Init visitor structure */
+ table_visitor.visit_obj = trav_table_visit_obj;
+ table_visitor.visit_lnk = trav_table_visit_lnk;
+ table_visitor.udata = table;
+ /* Traverse all objects in the file, visiting each object & link */
+ if(traverse(fid, &table_visitor) < 0)
+ return -1;
return 0;
}
/*-------------------------------------------------------------------------
- * Function: traverse
+ * Function: h5trav_getindext
*
- * Purpose: recursive function that searches HDF5 objects in LOC_ID
+ * Purpose: get index of NAME in list
*
- * Return: number of objects found in LOC_ID
+ * Return: index, -1 if not found
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
*
- * Date: November 4, 2002
+ * Date: December 18, 2003
*
*-------------------------------------------------------------------------
*/
-static int traverse(hid_t loc_id,
- const char *group_name,
- trav_table_t *table,
- trav_info_t *info,
- int *idx,
- int print)
+int
+h5trav_getindext(const char *name, const trav_table_t *table)
{
- haddr_t objno; /* Compact form of object's location */
- char *name = NULL;
- H5G_obj_t type;
- int n_names;
- char *path = NULL;
- H5G_stat_t statbuf;
- int inserted_objs = 0;
- int i, j;
-
- /* get the number of names */
- if((n_names = (int)get_nnames(loc_id, group_name)) < 0)
- return -1;
-
- for(i = 0; i < n_names; i++) {
- if(get_name_type(loc_id, group_name, i, &name, &type) < 0)
- return -1;
-
- /* allocate path buffer */
- path = (char*) HDmalloc(HDstrlen(group_name) + HDstrlen(name) + 2);
-
- /* initialize path */
- HDstrcpy( path, group_name );
- if(HDstrcmp(group_name, "/") != 0)
- HDstrcat( path, "/" );
- HDstrcat(path, name);
-
- /* disable error reporting */
- H5E_BEGIN_TRY {
- /* get info */
- H5Gget_objinfo( loc_id, path, FALSE, &statbuf);
- } H5E_END_TRY;
- objno = (haddr_t)statbuf.objno[0] | ((haddr_t)statbuf.objno[1] << (8 * sizeof(long)));
-
- /* add to array */
- if(info) {
- info[*idx].name = (char *)HDstrdup(path);
- info[*idx].type = type;
- (*idx)++;
+ unsigned int i;
+
+ for(i = 0; i < table->nobjs; i++) {
+ /* Check for object name having full path (with leading '/') */
+ if(HDstrcmp(name, table->objs[i].name) == 0)
+ return(i);
+
+ /* Check for object name without leading '/' */
+ if(HDstrcmp(name, table->objs[i].name + 1) == 0)
+ return(i);
+
+ /* search also in the list of links */
+ if(table->objs[i].nlinks) {
+ unsigned int j;
+
+ for ( j=0; j<table->objs[i].nlinks; j++) {
+ /* Check for object name having full path (with leading '/') */
+ if(HDstrcmp(name, table->objs[i].links[j].new_name) == 0)
+ return(i);
+
+ /* Check for object name without leading '/' */
+ if(HDstrcmp(name, table->objs[i].links[j].new_name + 1) == 0)
+ return(i);
+ } /* end for */
} /* end if */
+ } /* end for */
- switch(type) {
- /*-------------------------------------------------------------------------
- * H5G_GROUP
- *-------------------------------------------------------------------------
- */
- case H5G_GROUP:
- /* increment */
- inserted_objs++;
-
- /* nlink is number of hard links to object */
- if(statbuf.nlink > 0 && trav_table_search(objno, table) == -1) {
- /* add object to table */
- trav_table_add(objno, path, H5G_GROUP, table);
-
- /* print it */
- if(print)
- printf(" %-10s %s\n", "group", path);
-
- /* recurse with the absolute name */
- inserted_objs += traverse(loc_id, path, table, info, idx, print);
- } /* end if */
-
- /* search table group with more than one link to it */
- if(statbuf.nlink > 1) {
- if((j = trav_table_search(objno, table)) < 0)
- return -1;
-
- trav_table_addlink(table, j, path);
-
- if(table->objs[j].displayed == 0) {
- table->objs[j].displayed = 1;
- }
- else {
- /* print it */
- if (print)
- printf(" %-10s %s %s %s\n", "group", path, "->", table->objs[j].name );
- }
- } /* end if */
- break;
-
- /*-------------------------------------------------------------------------
- * H5G_DATASET
- *-------------------------------------------------------------------------
- */
- case H5G_DATASET:
- /* increment */
- inserted_objs++;
-
- /* nlink is number of hard links to object */
- if(statbuf.nlink > 0 && trav_table_search(objno, table) == -1) {
- /* add object to table */
- trav_table_add(objno, path, H5G_DATASET, table );
-
- /* print it */
- if(print)
- printf(" %-10s %s\n", "dataset", path );
- } /* end if */
-
- /* search table dataset with more than one link to it */
- if(statbuf.nlink > 1) {
- if((j = trav_table_search(objno, table)) < 0)
- return -1;
-
- trav_table_addlink(table, j, path);
-
- if(table->objs[j].displayed == 0) {
- table->objs[j].displayed = 1;
- }
- else {
- /* print it */
- if(print)
- printf(" %-10s %s %s %s\n", "dataset", path, "->", table->objs[j].name);
- } /* displayed==1 */
- } /* nlink>1 */
- break;
-
- /*-------------------------------------------------------------------------
- * H5G_TYPE
- *-------------------------------------------------------------------------
- */
-
- case H5G_TYPE:
- /* increment */
- inserted_objs++;
-
- /* nlink is number of hard links to object */
- if(statbuf.nlink > 0 && trav_table_search(objno, table) == -1) {
- /* add object to table */
- trav_table_add(objno, path, H5G_TYPE, table);
-
- /* print it */
- if(print)
- printf(" %-10s %s\n", "datatype", path );
- } /* end if */
- break;
-
-
- /*-------------------------------------------------------------------------
- * H5G_LINK
- *-------------------------------------------------------------------------
- */
-
- case H5G_LINK:
- /* increment */
- inserted_objs++;
-
- /* add object to table */
- trav_table_add(HADDR_UNDEF, path, H5G_LINK, table);
-
- if(statbuf.linklen > 0) {
- char *targbuf;
-
- targbuf = HDmalloc(statbuf.linklen);
- assert(targbuf);
- H5Lget_val(loc_id, path, targbuf, statbuf.linklen, H5P_DEFAULT);
- if(print)
- printf(" %-10s %s -> %s\n", "link", path, targbuf);
- free(targbuf);
- }
- else {
- if(print)
- printf(" %-10s %s ->\n", "link", path);
- }
- break;
-
- /*-------------------------------------------------------------------------
- * H5G_UDLINK
- *-------------------------------------------------------------------------
- */
-
- case H5G_UDLINK:
- {
- H5L_info_t linkbuf;
-
- /* increment */
- inserted_objs++;
-
- /* add object to table */
- trav_table_add(HADDR_UNDEF, path, H5G_UDLINK, table);
-
- /* Get type of link */
- H5E_BEGIN_TRY {
- /* get link class info */
- H5Lget_info(loc_id, path, &linkbuf, H5P_DEFAULT);
- } H5E_END_TRY;
-
- if(linkbuf.type == H5L_TYPE_EXTERNAL) {
- if(statbuf.linklen > 0) {
- char *targbuf;
- const char *filename;
- const char *objname;
-
- targbuf = HDmalloc(statbuf.linklen);
- assert(targbuf);
- H5Lget_val(loc_id, path, targbuf, statbuf.linklen, H5P_DEFAULT);
- H5Lunpack_elink_val(targbuf, statbuf.linklen, NULL, &filename, &objname);
- if(print)
- printf(" %-10s %s -> %s %s\n", "ext link", path, filename, objname);
- free(targbuf);
- } /* end if */
- else {
- if(print)
- printf(" %-10s %s ->\n", "udlink", path);
- } /* end else */
- } /* end if */
- else { /* Unknown user-defined type */
- if(print)
- printf(" %-10s %s ->\n", "UD link type", path);
- } /* end else */
- }
- break;
-
-
- default:
- HDfprintf(stderr, "traverse: Unknown object %d!\n", type);
- return(-1);
- break;
- } /* end switch */
-
- if(name)
- HDfree(name);
- if(path)
- HDfree(path);
- } /* i */
-
- return inserted_objs;
+ return -1;
}
/*-------------------------------------------------------------------------
@@ -687,15 +605,15 @@ static int traverse(hid_t loc_id,
*-------------------------------------------------------------------------
*/
-int trav_table_search(haddr_t objno, trav_table_t *table )
+static size_t
+trav_table_search(const trav_table_t *table, haddr_t objno)
{
- unsigned int i;
+ size_t i;
- for (i = 0; i < table->nobjs; i++)
- if (table->objs[i].objno == objno)
- return i;
-
- return -1;
+ for(i = 0; i < table->nobjs; i++)
+ if(table->objs[i].objno == objno)
+ return(i);
+ return(i);
}
@@ -713,41 +631,66 @@ int trav_table_search(haddr_t objno, trav_table_t *table )
*-------------------------------------------------------------------------
*/
-void trav_table_add(haddr_t objno,
- char *name,
- H5G_obj_t type,
- trav_table_t *table)
+static void
+trav_table_add(trav_table_t *table,
+ const char *path,
+ const H5O_info_t *oinfo)
{
- unsigned int i;
-
- if (table->nobjs == table->size) {
- table->size *= 2;
- table->objs =
- (trav_obj_t*)HDrealloc(table->objs, table->size * sizeof(trav_obj_t));
-
- for (i = table->nobjs; i < table->size; i++) {
- table->objs[i].objno = 0;
- table->objs[i].flags[0] = table->objs[i].flags[1] = 0;
- table->objs[i].displayed = 0;
- table->objs[i].type = H5G_UNKNOWN;
- table->objs[i].name = NULL;
- table->objs[i].links = NULL;
- table->objs[i].nlinks = 0;
- table->objs[i].sizelinks = 0;
- }
- }
-
- i = table->nobjs++;
- table->objs[i].objno = objno;
- table->objs[i].flags[0] = table->objs[i].flags[1] = 0;
- HDfree(table->objs[i].name);
- table->objs[i].name = (char *)HDstrdup(name);
- table->objs[i].type = type;
- table->objs[i].links = NULL;
- table->objs[i].nlinks = 0;
+ size_t new;
+
+ if(table->nobjs == table->size) {
+ table->size = MAX(1, table->size * 2);
+ table->objs = (trav_obj_t*)HDrealloc(table->objs, table->size * sizeof(trav_obj_t));
+ } /* end if */
+
+ new = table->nobjs++;
+ table->objs[new].objno = oinfo ? oinfo->addr : HADDR_UNDEF;
+ table->objs[new].flags[0] = table->objs[new].flags[1] = 0;
+ table->objs[new].name = (char *)HDstrdup(path);
+ table->objs[new].type = oinfo ? (H5G_obj_t)oinfo->type : H5G_LINK;
+ table->objs[new].nlinks = 0;
+ table->objs[new].sizelinks = 0;
+ table->objs[new].links = NULL;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: trav_table_addlink
+ *
+ * Purpose: Add a hardlink name to the object
+ *
+ * Return: void
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ *
+ * Date: December 17, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+trav_table_addlink(trav_table_t *table,
+ size_t j /* the object index */,
+ const char *path)
+{
+ size_t new;
+
+ /* already inserted */
+ if(HDstrcmp(table->objs[j].name, path) == 0)
+ return;
+
+ /* 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 */
+
+ /* insert it */
+ new = table->objs[j].nlinks++;
+ table->objs[j].links[new].new_name = (char *)HDstrdup(path);
}
+
/*-------------------------------------------------------------------------
* Function: trav_table_addflags
*
@@ -767,34 +710,22 @@ void trav_table_addflags(unsigned *flags,
H5G_obj_t type,
trav_table_t *table)
{
- unsigned int i;
-
- if (table->nobjs == table->size) {
- table->size *= 2;
- table->objs =
- (trav_obj_t*)HDrealloc(table->objs, table->size * sizeof(trav_obj_t));
-
- for (i = table->nobjs; i < table->size; i++) {
- table->objs[i].objno = 0;
- table->objs[i].flags[0] = table->objs[i].flags[1] = 0;
- table->objs[i].displayed = 0;
- table->objs[i].type = H5G_UNKNOWN;
- table->objs[i].name = NULL;
- table->objs[i].links = NULL;
- table->objs[i].nlinks = 0;
- table->objs[i].sizelinks = 0;
- }
- }
-
- i = table->nobjs++;
- table->objs[i].objno = 0;
- table->objs[i].flags[0] = flags[0];
- table->objs[i].flags[1] = flags[1];
- HDfree(table->objs[i].name);
- table->objs[i].name = (char *)HDstrdup(name);
- table->objs[i].type = type;
- table->objs[i].links = NULL;
- table->objs[i].nlinks = 0;
+ unsigned int new;
+
+ if(table->nobjs == table->size) {
+ table->size = MAX(1, table->size * 2);
+ table->objs = (trav_obj_t *)HDrealloc(table->objs, table->size * sizeof(trav_obj_t));
+ }
+
+ new = table->nobjs++;
+ table->objs[new].objno = 0;
+ table->objs[new].flags[0] = flags[0];
+ table->objs[new].flags[1] = flags[1];
+ table->objs[new].name = (char *)HDstrdup(name);
+ table->objs[new].type = type;
+ table->objs[new].nlinks = 0;
+ table->objs[new].sizelinks = 0;
+ table->objs[new].links = NULL;
}
@@ -812,28 +743,15 @@ void trav_table_addflags(unsigned *flags,
*-------------------------------------------------------------------------
*/
-void trav_table_init( trav_table_t **tbl )
+void trav_table_init(trav_table_t **tbl)
{
- unsigned int i;
- trav_table_t* table = (trav_table_t*) HDmalloc(sizeof(trav_table_t));
-
- table->size = 20;
- table->nobjs = 0;
- table->objs =
- (trav_obj_t*)HDmalloc(table->size * sizeof(trav_obj_t));
-
- for (i = 0; i < table->size; i++) {
- table->objs[i].objno = 0;
- table->objs[i].flags[0] = table->objs[i].flags[1] = 0;
- table->objs[i].displayed = 0;
- table->objs[i].type = H5G_UNKNOWN;
- table->objs[i].name = NULL;
- table->objs[i].links = NULL;
- table->objs[i].nlinks = 0;
- table->objs[i].sizelinks = 0;
- }
-
- *tbl = table;
+ trav_table_t* table = (trav_table_t*) HDmalloc(sizeof(trav_table_t));
+
+ table->size = 0;
+ table->nobjs = 0;
+ table->objs = NULL;
+
+ *tbl = table;
}
@@ -854,60 +772,193 @@ void trav_table_init( trav_table_t **tbl )
void trav_table_free( trav_table_t *table )
{
- unsigned int i, j;
-
- for ( i = 0; i < table->nobjs; i++)
- {
- HDfree( table->objs[i].name );
- if (table->objs[i].nlinks)
- {
- for ( j=0; j<table->objs[i].nlinks; j++)
- HDfree( table->objs[i].links[j].new_name );
-
- HDfree(table->objs[i].links);
- }
- }
- HDfree(table->objs);
- HDfree(table);
-
+ if(table->objs) {
+ unsigned int i;
+
+ for(i = 0; i < table->nobjs; i++) {
+ HDfree(table->objs[i].name );
+ if(table->objs[i].nlinks) {
+ unsigned int j;
+
+ for(j = 0; j < table->objs[i].nlinks; j++)
+ HDfree(table->objs[i].links[j].new_name);
+
+ HDfree(table->objs[i].links);
+ } /* end if */
+ } /* end for */
+ HDfree(table->objs);
+ } /* end if */
+ HDfree(table);
}
+
+/*-------------------------------------------------------------------------
+ * Function: trav_print_visit_obj
+ *
+ * Purpose: Callback for visiting object, when printing info
+ *
+ * Return: 0 on success, -1 on failure
+ *
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
+ *
+ * Date: September 6, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+trav_print_visit_obj(const char *path, const H5O_info_t *oinfo,
+ hbool_t already_visited, void *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)
+ */
+ switch(oinfo->type) {
+ case H5O_TYPE_GROUP:
+ printf(" %-10s %s", "group", path);
+ break;
+
+ case H5O_TYPE_DATASET:
+ printf(" %-10s %s", "dataset", path);
+ break;
+
+ case H5O_TYPE_NAMED_DATATYPE:
+ printf(" %-10s %s", "datatype", path);
+ break;
+
+ default:
+ printf(" %-10s %s", "unknown object type", path);
+ break;
+ } /* end switch */
+
+ /* Check if we've already seen this object */
+ if(!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 */
+ return(0);
+} /* end trav_print_visit_obj() */
+
+
/*-------------------------------------------------------------------------
- * Function: trav_table_addlink
+ * Function: trav_print_visit_lnk
*
- * Purpose: Add a hardlink name to the object
+ * Purpose: Callback for visiting link, when printing info
*
- * Return: void
+ * Return: 0 on success, -1 on failure
*
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
*
- * Date: December 17, 2003
+ * Date: September 6, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+trav_print_visit_lnk(const char *path, const H5L_info_t *linfo, void *udata)
+{
+ trav_print_udata_t *print_udata = (trav_print_udata_t *)udata;
+
+ /* Print appropriate information for the type of link */
+ switch(linfo->type) {
+ case H5L_TYPE_SOFT:
+ if(linfo->u.val_size > 0) {
+ char *targbuf = HDmalloc(linfo->u.val_size + 1);
+ HDassert(targbuf);
+
+ H5Lget_val(print_udata->fid, path, targbuf, linfo->u.val_size + 1, H5P_DEFAULT);
+ printf(" %-10s %s -> %s\n", "link", path, targbuf);
+ free(targbuf);
+ } /* end if */
+ else
+ printf(" %-10s %s ->\n", "link", path);
+ break;
+
+ case H5L_TYPE_EXTERNAL:
+ if(linfo->u.val_size > 0) {
+ char *targbuf;
+ const char *filename;
+ const char *objname;
+
+ targbuf = HDmalloc(linfo->u.val_size + 1);
+ assert(targbuf);
+
+ H5Lget_val(print_udata->fid, path, targbuf, linfo->u.val_size + 1, H5P_DEFAULT);
+ H5Lunpack_elink_val(targbuf, linfo->u.val_size, NULL, &filename, &objname);
+ printf(" %-10s %s -> %s %s\n", "ext link", path, filename, objname);
+ free(targbuf);
+ } /* end if */
+ else
+ printf(" %-10s %s ->\n", "ext link", path);
+ break;
+
+ default:
+ printf(" %-10s %s -> ???\n", "unknown type of UD link", path);
+ break;
+ } /* end switch() */
+
+ return(0);
+} /* end trav_print_visit_lnk() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: h5trav_print
+ *
+ * Purpose: Print information about the objects & links in the file
+ *
+ * Return: 0, -1 on error
+ *
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
+ *
+ * Date: September 6, 2007
*
*-------------------------------------------------------------------------
*/
-void trav_table_addlink(trav_table_t *table,
- int j /* the object index */,
- char *path )
+int
+h5trav_print(hid_t fid)
{
- unsigned int k;
-
- /* already inserted */
- if (strcmp(table->objs[j].name,path)==0)
- return;
-
- /* allocate space if necessary */
- if (table->objs[j].nlinks == (unsigned)table->objs[j].sizelinks) {
- 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));
- }
-
- /* insert it */
- k=table->objs[j].nlinks++;
- table->objs[j].links[k].new_name = (char*)HDstrdup(path);
-}
+ 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;
+ print_visitor.visit_lnk = trav_print_visit_lnk;
+ print_visitor.udata = &print_udata;
+ /* Traverse all objects in the file, visiting each object & link */
+ if(traverse(fid, &print_visitor) < 0)
+ return -1;
+
+ /* Free table */
+ trav_table_free(table);
+
+ return 0;
+}