summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1998-03-24 23:18:34 (GMT)
committerRobb Matzke <matzke@llnl.gov>1998-03-24 23:18:34 (GMT)
commite987de2c42628f94e713111c5cbb09bbd3db4a68 (patch)
tree4baf097e2a0480c9cf24e2ce28749f969afb8fd8 /src
parent2ed9aa69f74cc2002fb9a03c8893056a1daea1db (diff)
downloadhdf5-e987de2c42628f94e713111c5cbb09bbd3db4a68.zip
hdf5-e987de2c42628f94e713111c5cbb09bbd3db4a68.tar.gz
hdf5-e987de2c42628f94e713111c5cbb09bbd3db4a68.tar.bz2
[svn-r329] Changes since 19980324
---------------------- ./src/H5D.c Zero element requests for H5Dread() and H5Dwrite() succeed. ./src/H5F.c ./src/H5Fprivate.h All files will have a root group. This greatly simplifies the library at the expense of ~1k extra bytes in files that have only one object. ./src/H5D.c ./src/H5Dprivate.h ./html/Groups.html Functions that used to take a file ID and an object name can now take a group ID instead of a file ID. This doesn't change the API, only it's documentation. ./src/H5G.c ./src/H5Gprivate.h ./src/H5O.c ./src/H5Oprivate.h Removed extra file arguments from some internal functions since the file pointer can be found from the group pointer or a symbol table entry (ent->file or H5G_fileof(group)). Besides, when we eventually implement mounting one file on another, H5G_namei() might return a different file than what you gave it, and that file is part of the returned symbol table entry. ./src/H5G.c Fixed bug with `.' appearing in a name. It used to hang the library. ./src/Makefile.in ./src/h5ls.c [NEW] ./MANIFEST Added `h5ls' a simple program that takes a file name and a directory and lists the contents of that directory using H5Giterate(). ./test/istore.c Changed an argument to H5G_create(). ./test/tstab.c Removed test_1 which was testing that files with a single object don't have a root group. This no longer applies.
Diffstat (limited to 'src')
-rw-r--r--src/H5D.c87
-rw-r--r--src/H5Dprivate.h4
-rw-r--r--src/H5F.c34
-rw-r--r--src/H5Fprivate.h2
-rw-r--r--src/H5G.c721
-rw-r--r--src/H5Gprivate.h17
-rw-r--r--src/H5O.c10
-rw-r--r--src/H5Oprivate.h2
-rw-r--r--src/H5detect.c2
-rw-r--r--src/Makefile.in7
-rw-r--r--src/h5ls.c102
11 files changed, 567 insertions, 421 deletions
diff --git a/src/H5D.c b/src/H5D.c
index 19942ad..b4f8766 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -130,7 +130,7 @@ H5D_term_interface(void)
/*-------------------------------------------------------------------------
* Function: H5Dcreate
*
- * Purpose: Creates a new dataset named NAME in file FILE_ID, opens the
+ * Purpose: Creates a new dataset named NAME at LOC_ID, opens the
* dataset for access, and associates with that dataset constant
* and initial persistent properties including the type of each
* datapoint as stored in the file (TYPE_ID), the size of the
@@ -168,10 +168,10 @@ H5D_term_interface(void)
*-------------------------------------------------------------------------
*/
hid_t
-H5Dcreate(hid_t file_id, const char *name, hid_t type_id, hid_t space_id,
+H5Dcreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
hid_t create_parms_id)
{
- H5F_t *f = NULL;
+ H5G_t *loc = NULL;
H5T_t *type = NULL;
H5S_t *space = NULL;
H5D_t *new_dset = NULL;
@@ -181,9 +181,8 @@ H5Dcreate(hid_t file_id, const char *name, hid_t type_id, hid_t space_id,
FUNC_ENTER(H5Dcreate, FAIL);
/* Check arguments */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL == (loc = H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
@@ -207,7 +206,8 @@ H5Dcreate(hid_t file_id, const char *name, hid_t type_id, hid_t space_id,
}
/* build and open the new dataset */
- if (NULL == (new_dset = H5D_create(f, name, type, space, create_parms))) {
+ if (NULL == (new_dset = H5D_create(loc, name, type, space,
+ create_parms))) {
HRETURN_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
"unable to create dataset");
}
@@ -219,23 +219,20 @@ H5Dcreate(hid_t file_id, const char *name, hid_t type_id, hid_t space_id,
}
FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5Dopen
*
- * Purpose: Finds a dataset named NAME in file FILE_ID, opens it, and
- * returns its ID. The dataset should be close when the caller
- * is no longer interested in it.
+ * Purpose: Finds a dataset named NAME at LOC_ID, opens it, and returns
+ * its ID. The dataset should be close when the caller is no
+ * longer interested in it.
*
* Return: Success: A new dataset ID
*
* Failure: FAIL
*
* Errors:
- * ARGS BADTYPE Not a file.
- * ARGS BADVALUE No name.
- * DATASET CANTREGISTER Can't register dataset.
- * DATASET NOTFOUND Dataset not found.
*
* Programmer: Robb Matzke
* Thursday, December 4, 1997
@@ -245,25 +242,24 @@ H5Dcreate(hid_t file_id, const char *name, hid_t type_id, hid_t space_id,
*-------------------------------------------------------------------------
*/
hid_t
-H5Dopen(hid_t file_id, const char *name)
+H5Dopen(hid_t loc_id, const char *name)
{
- H5F_t *file = NULL; /*file holding the dataset */
+ H5G_t *loc = NULL; /*location holding the dataset */
H5D_t *dataset = NULL; /*the dataset */
hid_t ret_value = FAIL;
FUNC_ENTER(H5Dopen, FAIL);
/* Check args */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (file = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL == (loc = H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
}
/* Find the dataset */
- if (NULL == (dataset = H5D_open(file, name))) {
+ if (NULL == (dataset = H5D_open(loc, name))) {
HRETURN_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "dataset not found");
}
@@ -722,7 +718,7 @@ H5Dextend (hid_t dataset_id, const size_t *size)
*-------------------------------------------------------------------------
*/
H5D_t *
-H5D_create(H5F_t *f, const char *name, const H5T_t *type, const H5S_t *space,
+H5D_create(H5G_t *loc, const char *name, const H5T_t *type, const H5S_t *space,
const H5D_create_t *create_parms)
{
H5D_t *new_dset = NULL;
@@ -730,15 +726,17 @@ H5D_create(H5F_t *f, const char *name, const H5T_t *type, const H5S_t *space,
intn i, ndims;
size_t max_dim[H5O_LAYOUT_NDIMS];
H5O_efl_t *efl = NULL;
+ H5F_t *f = H5G_fileof (loc);
FUNC_ENTER(H5D_create, NULL);
/* check args */
- assert(f);
- assert(name && *name);
- assert(type);
- assert(space);
- assert(create_parms);
+ assert (f);
+ assert (loc);
+ assert (name && *name);
+ assert (type);
+ assert (space);
+ assert (create_parms);
/* Initialize the dataset object */
new_dset = H5MM_xcalloc(1, sizeof(H5D_t));
@@ -869,7 +867,7 @@ H5D_create(H5F_t *f, const char *name, const H5T_t *type, const H5S_t *space,
}
/* Give the dataset a name */
- if (H5G_insert(name, &(new_dset->ent)) < 0) {
+ if (H5G_insert(loc, name, &(new_dset->ent)) < 0) {
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to name dataset");
}
@@ -913,27 +911,29 @@ H5D_create(H5F_t *f, const char *name, const H5T_t *type, const H5S_t *space,
*-------------------------------------------------------------------------
*/
H5D_t *
-H5D_open(H5F_t *f, const char *name)
+H5D_open(H5G_t *loc, const char *name)
{
H5D_t *dataset = NULL; /*the dataset which was found */
H5D_t *ret_value = NULL; /*return value */
intn i;
-
+ H5F_t *f = NULL;
+
FUNC_ENTER(H5D_open, NULL);
/* check args */
- assert(f);
- assert(name && *name);
-
+ assert (loc);
+ assert (name && *name);
+
+ f = H5G_fileof (loc);
dataset = H5MM_xcalloc(1, sizeof(H5D_t));
dataset->create_parms = H5P_copy (H5P_DATASET_CREATE, &H5D_create_dflt);
H5F_addr_undef(&(dataset->ent.header));
/* Open the dataset object */
- if (H5G_find(f, name, NULL, &(dataset->ent)) < 0) {
+ if (H5G_find(loc, name, NULL, &(dataset->ent)) < 0) {
HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, NULL, "not found");
}
- if (H5O_open(f, &(dataset->ent)) < 0) {
+ if (H5O_open(&(dataset->ent)) < 0) {
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "unable to open");
}
@@ -1127,6 +1127,11 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
* enough value in xfer_parms since turning off data type conversion also
* turns off background preservation.
*/
+ if (nelmts!=H5S_get_npoints (file_space)) {
+ HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
+ "src and dest data spaces have different sizes");
+ }
+ if (0==nelmts) HRETURN (SUCCEED);
if (NULL == (tconv_func = H5T_find(dataset->type, mem_type,
xfer_parms->need_bkg, &cdata))) {
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL,
@@ -1142,10 +1147,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL,
"unable to convert from file to memory data space");
}
- if (nelmts!=H5S_get_npoints (file_space)) {
- HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
- "src and dest data spaces have different sizes");
- }
+
/*
* If there is no type conversion then try reading directly into the
@@ -1352,6 +1354,11 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
* enough value in xfer_parms since turning off data type conversion also
* turns off background preservation.
*/
+ if (nelmts!=H5S_get_npoints (file_space)) {
+ HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
+ "src and dest data spaces have different sizes");
+ }
+ if (0==nelmts) HRETURN (SUCCEED);
if (NULL == (tconv_func = H5T_find(mem_type, dataset->type,
xfer_parms->need_bkg, &cdata))) {
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL,
@@ -1367,10 +1374,6 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL,
"unable to convert from memory to file data space");
}
- if (nelmts!=H5S_get_npoints (file_space)) {
- HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
- "src and dest data spaces have different sizes");
- }
/*
* If there is no type conversion then try writing directly from
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index 681928f..6068f00 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -61,9 +61,9 @@ extern const H5D_create_t H5D_create_dflt;
extern const H5D_xfer_t H5D_xfer_dflt;
/* Functions defined in H5D.c */
-H5D_t *H5D_create (H5F_t *f, const char *name, const H5T_t *type,
+H5D_t *H5D_create (H5G_t *loc, const char *name, const H5T_t *type,
const H5S_t *space, const H5D_create_t *create_parms);
-H5D_t *H5D_open (H5F_t *f, const char *name);
+H5D_t *H5D_open (H5G_t *loc, const char *name);
herr_t H5D_close (H5D_t *dataset);
herr_t H5D_read (H5D_t *dataset, const H5T_t *mem_type,
const H5S_t *mem_space, const H5S_t *file_space,
diff --git a/src/H5F.c b/src/H5F.c
index 553bbeb..6acdf81 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -538,8 +538,8 @@ H5F_dest(H5F_t *f)
if (f) {
if (0 == --(f->shared->nrefs)) {
+ /* Do not close the root group since we didn't count it */
H5AC_dest(f);
- f->shared->root_ent = H5MM_xfree(f->shared->root_ent);
f->shared = H5MM_xfree(f->shared);
}
f->name = H5MM_xfree(f->name);
@@ -834,7 +834,7 @@ H5F_open(const char *name, uintn flags,
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL,
"can't write file boot block");
}
-
+
} else if (1 == f->shared->nrefs) {
/* For existing files we must read the boot block. */
if (H5F_locate_signature(f->shared->lf,
@@ -940,11 +940,11 @@ H5F_open(const char *name, uintn flags,
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL,
"can't read root symbol entry");
}
- if (H5F_addr_defined(&(root_ent.header))) {
- f->shared->root_ent = H5MM_xmalloc(sizeof(H5G_entry_t));
- *(f->shared->root_ent) = root_ent;
+ if (H5G_mkroot (f, &root_ent)<0) {
+ HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL,
+ "unable to read root group");
}
-
+
/*
* The userdefined data is the area of the file before the base
* address.
@@ -984,6 +984,12 @@ H5F_open(const char *name, uintn flags,
#endif
H5F_low_seteof(f->shared->lf, &addr2);
}
+
+ /* Create and/or open the root group if we haven't already done so */
+ if (H5G_mkroot (f, NULL)<0) {
+ HGOTO_ERROR (H5E_FILE, H5E_CANTINIT, NULL,
+ "unable to create/open root group");
+ }
/* Success! */
ret_value = f;
@@ -1268,7 +1274,7 @@ H5F_flush(H5F_t *f, hbool_t invalidate)
H5F_addr_encode(f, &p, &(f->shared->smallobj_addr));
H5F_addr_encode(f, &p, &(f->shared->freespace_addr));
H5F_addr_encode(f, &p, &(f->shared->hdf5_eof));
- H5G_ent_encode(f, &p, f->shared->root_ent);
+ H5G_ent_encode(f, &p, H5G_entof(f->shared->root_grp));
/* update file length if necessary */
if (!H5F_addr_defined(&(f->shared->hdf5_eof))) {
@@ -1312,8 +1318,8 @@ H5F_close(H5F_t *f)
FUNC_ENTER(H5F_close, FAIL);
/* Close all current working groups */
- while (H5G_pop(f) >= 0) /*void*/;
-
+ while (H5G_pop(f)>=0) /*void*/;
+
/* Flush the boot block and caches */
if (H5F_flush(f, TRUE) < 0) {
HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache");
@@ -1324,7 +1330,7 @@ H5F_close(H5F_t *f)
* they have all been closed. The file is in a consistent state now, so
* forgetting to close everything is not a major problem.
*/
- if (f->nopen > 0) {
+ if (f->nopen>0) {
#ifndef NDEBUG
fprintf(stderr, "HDF5-DIAG: H5F_close: %u object header%s still "
"open (file close will complete when %s closed)\n",
@@ -1610,10 +1616,10 @@ H5F_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent,
(unsigned) (f->shared->create_parms.sharedheader_ver));
fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Root symbol table entry:",
- f->shared->root_ent ? "" : "(none)");
- if (f->shared->root_ent) {
- H5G_ent_debug(f, f->shared->root_ent, stream,
+ "Root group symbol table entry:",
+ f->shared->root_grp ? "" : "(none)");
+ if (f->shared->root_grp) {
+ H5G_ent_debug(f, H5G_entof (f->shared->root_grp), stream,
indent + 3, MAX(0, fwidth - 3));
}
FUNC_LEAVE(SUCCEED);
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 77a299f..9b7192a 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -404,7 +404,7 @@ typedef struct H5F_file_t {
struct H5AC_t *cache; /* The object cache */
H5F_create_t create_parms; /* File-creation property list */
H5F_access_t access_parms; /* File-access property list */
- struct H5G_entry_t *root_ent; /* Root symbol table entry */
+ struct H5G_t *root_grp; /* Open root group */
} H5F_file_t;
/*
diff --git a/src/H5G.c b/src/H5G.c
index 1b7a700..f5162e0 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -4,21 +4,62 @@
*
*-------------------------------------------------------------------------
*
- * Created: H5G.c
- * Jul 18 1997
- * Robb Matzke <matzke@llnl.gov>
+ * Created: H5G.c
+ * Jul 18 1997
+ * Robb Matzke <matzke@llnl.gov>
+ *
+ * Purpose: Symbol table functions. The functions that begin with
+ * `H5G_stab_' don't understand the naming system; they operate
+ * on a single symbol table at a time.
+ *
+ * The functions that begin with `H5G_node_' operate on the leaf
+ * nodes of a symbol table B-tree. They should be defined in
+ * the H5Gnode.c file.
+ *
+ * The remaining functions know how to traverse the group
+ * directed graph.
+ *
+ * Names: Object names are a slash-separated list of components. If
+ * the name begins with a slash then it's absolute, otherwise
+ * it's relative ("/foo/bar" is absolute while "foo/bar" is
+ * relative). Multiple consecutive slashes are treated as
+ * single slashes and trailing slashes are ignored. The special
+ * case `/' is the root group. Every file has a root group.
+ *
+ * API functions that look up names take a location ID and a
+ * name. The location ID can be a file ID or a group ID and the
+ * name can be relative or absolute.
+ *
+ * +--------------+----------- +--------------------------------+
+ * | Location ID | Name | Meaning |
+ * +--------------+------------+--------------------------------+
+ * | File ID | "/foo/bar" | Find `foo' within `bar' within |
+ * | | | the root group of the specified|
+ * | | | file. |
+ * +--------------+------------+--------------------------------+
+ * | File ID | "foo/bar" | Find `foo' within `bar' within |
+ * | | | the current working group of |
+ * | | | the specified file. |
+ * +--------------+------------+--------------------------------+
+ * | File ID | "/" | The root group of the specified|
+ * | | | file. |
+ * +--------------+------------+--------------------------------+
+ * | File ID | "." | The current working group of |
+ * | | | the specified file. |
+ * +--------------+------------+--------------------------------+
+ * | Group ID | "/foo/bar" | Find `foo' within `bar' within |
+ * | | | the root group of the file |
+ * | | | containing the specified group.|
+ * +--------------+------------+--------------------------------+
+ * | Group ID | "foo/bar" | File `foo' within `bar' within |
+ * | | | the specified group. |
+ * +--------------+------------+--------------------------------+
+ * | Group ID | "/" | The root group of the file |
+ * | | | containing the specified group.|
+ * +--------------+------------+--------------------------------+
+ * | Group ID | "." | The specified group. |
+ * +--------------+------------+--------------------------------+
*
- * Purpose: Symbol table functions. The functions that
- * begin with `H5G_stab_' don't understand the
- * naming system; they operate on a single
- * symbol table at a time.
- *
- * The functions that begin with `H5G_node_' operate
- * on the leaf nodes of a symbol table B-tree. They
- * should be defined in the H5Gnode.c file.
- *
- * The remaining functions know how to traverse the
- * group directed graph
*
* Modifications:
*
@@ -30,7 +71,7 @@
*
*-------------------------------------------------------------------------
*/
-#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h */
+#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h */
/* Packages needed by this file... */
#include <H5private.h>
@@ -47,19 +88,17 @@
#define PABLO_MASK H5G_mask
/* Interface initialization */
-static hbool_t interface_initialize_g = FALSE;
+static hbool_t interface_initialize_g = FALSE;
#define INTERFACE_INIT H5G_init_interface
-static herr_t H5G_init_interface(void);
-static void H5G_term_interface(void);
+static herr_t H5G_init_interface(void);
+static void H5G_term_interface(void);
-static H5G_entry_t *H5G_getcwg(H5F_t *f);
/*-------------------------------------------------------------------------
* Function: H5Gcreate
*
- * Purpose: Creates a new group in FILE and gives it the specified
- * NAME. Unless NAME begins with `/' it is relative to the
- * current working group. The group is opened for write access
+ * Purpose: Creates a new group relative to LOC_ID and gives it the
+ * specified NAME. The group is opened for write access
* and it's object ID is returned.
*
* The optional SIZE_HINT specifies how much file space to
@@ -85,24 +124,24 @@ static H5G_entry_t *H5G_getcwg(H5F_t *f);
*-------------------------------------------------------------------------
*/
hid_t
-H5Gcreate(hid_t file_id, const char *name, size_t size_hint)
+H5Gcreate(hid_t loc_id, const char *name, size_t size_hint)
{
- H5F_t *f = NULL;
- H5G_t *grp;
+ H5G_t *loc = NULL;
+ H5G_t *grp = NULL;
hid_t ret_value = FAIL;
FUNC_ENTER(H5Gcreate, FAIL);
/* Check arguments */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL==(loc=H5G_loc (loc_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given");
}
+
/* Create the group */
- if (NULL == (grp = H5G_create(f, name, size_hint))) {
+ if (NULL == (grp = H5G_create(loc, name, size_hint))) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group");
}
if ((ret_value = H5I_register(H5_GROUP, grp)) < 0) {
@@ -112,6 +151,7 @@ H5Gcreate(hid_t file_id, const char *name, size_t size_hint)
}
FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5Gopen
@@ -133,24 +173,24 @@ H5Gcreate(hid_t file_id, const char *name, size_t size_hint)
*-------------------------------------------------------------------------
*/
hid_t
-H5Gopen(hid_t file_id, const char *name)
+H5Gopen(hid_t loc_id, const char *name)
{
- hid_t ret_value = FAIL;
- H5F_t *f = NULL;
- H5G_t *grp = NULL;
+ hid_t ret_value = FAIL;
+ H5G_t *grp = NULL;
+ H5G_t *loc = NULL;
FUNC_ENTER(H5Gopen, FAIL);
/* Check args */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL==(loc=H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
}
+
/* Open the group */
- if (NULL == (grp = H5G_open(f, name))) {
+ if (NULL == (grp = H5G_open(loc, name))) {
HRETURN_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group");
}
/* Register an atom for the group */
@@ -161,6 +201,7 @@ H5Gopen(hid_t file_id, const char *name)
}
FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5Gclose
@@ -198,6 +239,7 @@ H5Gclose(hid_t grp_id)
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5Gset
@@ -211,6 +253,8 @@ H5Gclose(hid_t grp_id)
* handles, then each handle's current working group can be
* set independently of the other file handles for that file.
*
+ * The initial current working group is the root group.
+ *
* See also: H5Gpush(), H5Gpop()
*
* Errors:
@@ -227,35 +271,37 @@ H5Gclose(hid_t grp_id)
*-------------------------------------------------------------------------
*/
herr_t
-H5Gset(hid_t file_id, const char *name)
+H5Gset(hid_t loc_id, const char *name)
{
- H5F_t *f = NULL;
- H5G_t *grp;
+ H5G_t *grp = NULL;
+ H5G_t *loc = NULL;
FUNC_ENTER(H5Gset, FAIL);
/* Check/fix arguments */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL==(loc=H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
}
- if (NULL == (grp = H5G_open(f, name))) {
+
+ /* Set the current working group */
+ if (NULL == (grp = H5G_open(loc, name))) {
HRETURN_ERROR(H5E_ARGS, H5E_NOTFOUND, FAIL, "no such group");
}
- /* Set the current working group */
- if (H5G_set(f, grp) < 0) {
+ if (H5G_set(grp) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
"unable to change current working group");
}
+
/* Close the handle */
- if (H5G_close(grp) < 0) {
+ if (H5G_close(grp)<0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close group");
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5Gpush
@@ -285,26 +331,26 @@ H5Gset(hid_t file_id, const char *name)
*-------------------------------------------------------------------------
*/
herr_t
-H5Gpush(hid_t file_id, const char *name)
+H5Gpush(hid_t loc_id, const char *name)
{
- H5F_t *f = NULL;
- H5G_t *grp;
+ H5G_t *grp = NULL;
+ H5G_t *loc = NULL;
FUNC_ENTER(H5Gpush, FAIL);
/* Check arguments */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL == (loc = H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
}
- if (NULL == (grp = H5G_open(f, name))) {
+
+ /* Push group onto stack */
+ if (NULL == (grp = H5G_open(loc, name))) {
HRETURN_ERROR(H5E_ARGS, H5E_NOTFOUND, FAIL, "no such group");
}
- /* Push group onto stack */
- if (H5G_push(f, grp) < 0) {
+ if (H5G_push(grp) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
"can't change current working group");
}
@@ -314,6 +360,7 @@ H5Gpush(hid_t file_id, const char *name)
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5Gpop
@@ -327,6 +374,9 @@ H5Gpush(hid_t file_id, const char *name)
* handles, then each handle's current working group can be
* set independently of the other file handles for that file.
*
+ * If LOC_ID is a group ID then it's used only to determine the
+ * file from which to pop.
+ *
* See also: H5Gset(), H5Gpush()
*
* Errors:
@@ -345,21 +395,20 @@ H5Gpush(hid_t file_id, const char *name)
*-------------------------------------------------------------------------
*/
herr_t
-H5Gpop(hid_t file_id)
+H5Gpop(hid_t loc_id)
{
- H5F_t *f = NULL;
+ H5G_t *loc = NULL;
FUNC_ENTER(H5Gpop, FAIL);
/* Check arguments */
- if (H5_FILE != H5I_group(file_id) ||
- NULL == (f = H5I_object(file_id))) {
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL == (loc = H5G_loc(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
+
/* pop */
- if (H5G_pop(f) < 0) {
- HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
- "stack is empty");
+ if (H5G_pop(H5G_fileof (loc))<0) {
+ HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "stack is empty");
}
FUNC_LEAVE(SUCCEED);
}
@@ -368,8 +417,8 @@ H5Gpop(hid_t file_id)
/*-------------------------------------------------------------------------
* Function: H5Giterate
*
- * Purpose: Iterates over the entries of a group. The FILE_ID and NAME
- * identify the group over which to iterate and INDEX indicates
+ * Purpose: Iterates over the entries of a group. The LOC_ID and NAME
+ * identify the group over which to iterate and IDX indicates
* where to start iterating (zero means at the beginning). The
* OPERATOR is called for each member and the iteration
* continues until the operator returns non-zero or all members
@@ -393,25 +442,24 @@ H5Gpop(hid_t file_id)
*-------------------------------------------------------------------------
*/
herr_t
-H5Giterate (hid_t file_id, const char *name, int *index,
+H5Giterate (hid_t loc_id, const char *name, int *idx,
H5G_iterate_t op, void *op_data)
{
- H5F_t *f = NULL;
- int _index = 0;
+ int _idx = 0;
H5G_bt_ud2_t udata;
herr_t ret_value = FAIL;
+ H5G_t *loc = NULL;
FUNC_ENTER (H5Giterate, FAIL);
/* Check args */
- if (H5_FILE!=H5I_group (file_id) ||
- NULL==(f=H5I_object (file_id))) {
- HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file");
+ if (NULL==(loc=H5G_loc (loc_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
if (!name || !*name) {
HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified");
}
- if (!index) index = &_index;
+ if (!idx) idx = &_idx;
if (!op) {
HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified");
}
@@ -420,7 +468,7 @@ H5Giterate (hid_t file_id, const char *name, int *index,
* Open the group on which to operate. We also create a group ID which
* we can pass to the application-defined operator.
*/
- if (NULL==(udata.group = H5G_open (f, name))) {
+ if (NULL==(udata.group = H5G_open (loc, name))) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to open group");
}
if ((udata.group_id=H5I_register (H5_GROUP, udata.group))<0) {
@@ -430,12 +478,12 @@ H5Giterate (hid_t file_id, const char *name, int *index,
}
/* Build udata to pass through H5B_iterate() to H5G_node_iterate() */
- udata.skip = *index;
+ udata.skip = *idx;
udata.op = op;
udata.op_data = op_data;
/* Iterate over the group members */
- if ((ret_value = H5B_iterate (f, H5B_SNODE,
+ if ((ret_value = H5B_iterate (H5G_fileof(udata.group), H5B_SNODE,
&(udata.group->ent.cache.stab.btree_addr),
&udata))<0) {
HERROR (H5E_SYM, H5E_CANTINIT, "iteration operator failed");
@@ -482,6 +530,7 @@ H5G_init_interface(void)
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_term_interface
@@ -502,6 +551,7 @@ H5G_term_interface(void)
{
H5I_destroy_group(H5_GROUP);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_component
@@ -525,17 +575,16 @@ H5G_term_interface(void)
*
*-------------------------------------------------------------------------
*/
-static const char *
+static const char *
H5G_component(const char *name, size_t *size_p)
{
assert(name);
- while ('/' == *name)
- name++;
- if (size_p)
- *size_p = HDstrcspn(name, "/");
+ while ('/' == *name) name++;
+ if (size_p) *size_p = HDstrcspn(name, "/");
return name;
}
+
/*-------------------------------------------------------------------------
* Function: H5G_namei
@@ -566,22 +615,14 @@ H5G_component(const char *name, size_t *size_p)
* GRP_ENT has an undefined object header address, and GRP_ENT
* is the symbol table entry for `bar' in `/foo'.
*
- * If a file contains more than one object, then `/' is the name
- * of the root object which is a group. Otherwise, a file can
- * consist of a single object, not necessarily a group, whose
- * name is `/foo' where `foo' is the value of the name messsage
- * in the object header. A file can also contain no objects in
- * which case the function returns so REST points to the
- * beginning of NAME and OBJ_ENT and GRP_ENT contain undefined
- * header addresses.
- *
- * Components of a name are separated from one another by one or
- * more slashes (/). Slashes at the end of a name are ignored.
- * If the name begins with a slash then the search begins at the
- * root object, otherwise it begins at the group CWG, otherwise
- * it begins at the current working group of file F. The
- * component `.' is a no-op, but `..' is not understood by this
- * function (unless it appears as an entry in the symbol table).
+ * Every file has a root group whose name is `/'. Components of
+ * a name are separated from one another by one or more slashes
+ * (/). Slashes at the end of a name are ignored. If the name
+ * begins with a slash then the search begins at the root group
+ * of the file containing LOC_ENT. Otherwise it begins at
+ * LOC_ENT. The component `.' is a no-op, but `..' is not
+ * understood by this function (unless it appears as an entry in
+ * the symbol table).
*
* Errors:
*
@@ -602,15 +643,13 @@ H5G_component(const char *name, size_t *size_p)
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_namei(H5F_t *f, H5G_entry_t *cwg, const char *name,
- const char **rest/*out*/, H5G_entry_t *grp_ent/*out*/,
- H5G_entry_t *obj_ent/*out*/)
+H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/,
+ H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/)
{
H5G_entry_t _grp_ent; /*entry for current group */
H5G_entry_t _obj_ent; /*entry found */
size_t nchars; /*component name length */
char comp[1024]; /*component name buffer */
- hbool_t aside = FALSE; /*did we look at a name message?*/
/* clear output args before FUNC_ENTER() in case it fails */
if (rest) *rest = name;
@@ -623,36 +662,43 @@ H5G_namei(H5F_t *f, H5G_entry_t *cwg, const char *name,
FUNC_ENTER(H5G_namei, FAIL);
- /* check args */
- assert(f);
- assert(name && *name);
-
- /* If the file contains no objects then return failure */
- if (!f->shared->root_ent) {
- HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "no root group");
- }
- /* starting point */
- if ('/' == *name) {
- *obj_ent = *(f->shared->root_ent);
- } else if (cwg) {
- *obj_ent = *cwg;
- } else if ((cwg = H5G_getcwg(f))) {
- *obj_ent = *cwg;
+ /*
+ * Where does the searching start? For absolute names it starts at the
+ * root of the file; for relative names it starts at CWG.
+ */
+ if (!name || !*name) {
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "no name given");
+ } else if (!loc_ent) {
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
+ "no current working group");
+ } else if ('/' == *name) {
+ *obj_ent = loc_ent->file->shared->root_grp->ent;
} else {
- HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "no current working group");
+ *obj_ent = *loc_ent;
}
- assert(H5F_addr_defined(&(obj_ent->header)));
/* traverse the name */
while ((name = H5G_component(name, &nchars)) && *name) {
- if (rest)
- *rest = name;
+ if (rest) *rest = name;
+
+ /*
+ * Copy the component name into a null-terminated buffer so
+ * we can pass it down to the other symbol table functions.
+ */
+ if (nchars+1 > sizeof(comp)) {
+ HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, FAIL,
+ "component is too long");
+ }
+ HDmemcpy(comp, name, nchars);
+ comp[nchars] = '\0';
/*
* The special name `.' is a no-op.
*/
- if ('.' == name[0] && !name[1])
+ if ('.' == comp[0] && !comp[1]) {
+ name += nchars;
continue;
+ }
/*
* Advance to the next component of the name.
@@ -661,68 +707,35 @@ H5G_namei(H5F_t *f, H5G_entry_t *cwg, const char *name,
HDmemset(obj_ent, 0, sizeof(H5G_entry_t));
H5F_addr_undef(&(obj_ent->header));
- /*
- * Copy the component name into a null-terminated buffer so
- * we can pass it down to the other symbol table functions.
- */
- if (nchars + 1 > sizeof(comp)) {
- HRETURN_ERROR(H5E_SYM, H5E_COMPLEN, FAIL, "component is too long");
- }
- HDmemcpy(comp, name, nchars);
- comp[nchars] = '\0';
-
- if (H5G_stab_find(grp_ent, comp, obj_ent /*out */ ) < 0) {
+ if (H5G_stab_find(grp_ent, comp, obj_ent/*out*/)<0) {
/*
* Component was not found in the current symbol table, possibly
- * because GRP_ENT isn't a symbol table. If it is the root symbol
- * then see if it has the appropriate name field. The ASIDE
- * variable prevents us from saying `/foo/foo' where the root object
- * has the name `foo'.
+ * because GRP_ENT isn't a symbol table.
*/
- H5O_name_t mesg =
- {0};
- if (!aside &&
- H5F_addr_eq(&(grp_ent->header),
- &(f->shared->root_ent->header)) &&
- H5O_read(grp_ent, H5O_NAME, 0, &mesg) &&
- !HDstrcmp(mesg.s, comp)) {
- H5O_reset(H5O_NAME, &mesg);
- *obj_ent = *grp_ent;
- HDmemset(grp_ent, 0, sizeof(H5G_entry_t));
- H5F_addr_undef(&(grp_ent->header));
- aside = TRUE;
- } else {
- H5O_reset(H5O_NAME, &mesg);
- HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found");
- }
+ HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found");
}
/* next component */
name += nchars;
}
- if (rest)
- *rest = name; /*final null */
+ if (rest) *rest = name; /*final null */
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_mkroot
*
- * Purpose: Creates the root group if it doesn't exist; otherwise
- * nothing happens. If the root symbol table entry previously
- * pointed to something other than a group, then that object
- * is made a member of the root group and is given a name
- * corresponding to the object's name message (the name message
- * is removed). If the root object doesn't have a name message
- * then the name `Root Object' is used.
+ * Purpose: Creates a root group in an empty file and opens it. If a
+ * root group is already open then this function immediately
+ * returnes. If ENT is non-null then it's the symbol table
+ * entry for an existing group which will be opened as the root
+ * group. Otherwise a new root group is created and then
+ * opened.
*
- * Errors:
- *
* Return: Success: SUCCEED
*
- * Failure: FAIL. This function returns -2 if the
- * failure is because a root group already
- * exists.
+ * Failure: FAIL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -732,88 +745,68 @@ H5G_namei(H5F_t *f, H5G_entry_t *cwg, const char *name,
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5G_mkroot(H5F_t *f, size_t size_hint)
+herr_t
+H5G_mkroot (H5F_t *f, H5G_entry_t *ent)
{
- herr_t ret_value = FAIL; /*return value */
- H5O_name_t name =
- {NULL}; /*object name */
- H5O_stab_t stab; /*symbol table message */
- H5G_entry_t new_root; /*new root object */
- const char *obj_name = NULL; /*name of old root object */
+ H5G_entry_t new_root; /*new root object */
+ H5O_stab_t stab; /*symbol table message */
FUNC_ENTER(H5G_mkroot, FAIL);
/* check args */
assert(f);
+ if (f->shared->root_grp) return SUCCEED;
/*
- * If we already have a root object, then get it's name.
+ * If there is no root object then create one. The root group always has
+ * a hard link count of one since it's pointed to by the boot block.
*/
- if (f->shared->root_ent) {
- if (H5O_read(f->shared->root_ent, H5O_STAB, 0, &stab)) {
- HGOTO_ERROR(H5E_SYM, H5E_EXISTS, -2, "root group already exists");
- } else if (NULL == H5O_read(f->shared->root_ent, H5O_NAME, 0, &name)) {
- obj_name = "Root Object";
- } else {
- obj_name = name.s; /*don't reset message until the end! */
+ if (!ent) {
+ ent = &new_root;
+ if (H5G_stab_create (f, 16, ent/*out*/)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL,
+ "unable to create root group");
}
- }
- /*
- * Create the new root group. Set the link count to 1.
- */
- if (H5G_stab_create(f, size_hint, &new_root /*out */ ) < 0) {
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cant create root");
- }
- if (1 != H5O_link(&new_root, 1)) {
- HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL,
- "internal error (wrong link count)");
- }
- /*
- * If there was a previous root object then insert it into the new root
- * symbol table with the specified name. Then make the root object the
- * new symbol table.
- */
- if (f->shared->root_ent) {
- assert(1 == H5O_link(f->shared->root_ent, 0));
-
- if (H5G_stab_insert(&new_root, obj_name, f->shared->root_ent) < 0) {
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
- "can't reinsert old root object");
+ if (1 != H5O_link (ent, 1)) {
+ HRETURN_ERROR (H5E_SYM, H5E_LINK, FAIL,
+ "internal error (wrong link count)");
}
+ } else {
/*
- * Remove all `name' messages from the old root object. The only time
- * a name message should ever appear is to give the root object a name,
- * but the old root object is no longer the root object.
+ * Open the root object as a group.
*/
- H5O_remove(f->shared->root_ent, H5O_NAME, H5O_ALL);
- H5E_clear(); /*who really cares? */
-
- *(f->shared->root_ent) = new_root;
-
- } else {
- f->shared->root_ent = H5G_ent_calloc(&new_root);
+ if (H5O_open (ent)<0) {
+ HRETURN_ERROR (H5E_SYM, H5E_CANTOPENOBJ, FAIL,
+ "unable to open root group");
+ }
+ if (NULL==H5O_read (ent, H5O_STAB, 0, &stab)) {
+ H5O_close (ent);
+ HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
+ "root object is not a group");
+ }
+ H5O_reset (H5O_STAB, &stab);
}
- H5O_close(&new_root);
- ret_value = SUCCEED;
+ /*
+ * Create the group pointer. Also decrement the open object count so we
+ * don't count the root group as an open object. The root group will
+ * never be closed.
+ */
+ f->shared->root_grp = H5MM_xcalloc (1, sizeof(H5G_t));
+ f->shared->root_grp->ent = *ent;
+ f->shared->root_grp->nref = 1;
+ assert (1==f->nopen);
+ f->nopen = 0;
- done:
- H5O_reset(H5O_NAME, &name);
- FUNC_LEAVE(ret_value);
+ FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_create
*
* Purpose: Creates a new empty group with the specified name. The name
- * is either an absolute name or is relative to the current
- * working group.
- *
- * A root group is created implicitly by this function
- * when necessary. Calling this function with the name "/"
- * (or any equivalent name) will result in an H5E_EXISTS
- * failure.
+ * is either an absolute name or is relative to LOC.
*
* Errors:
*
@@ -832,32 +825,22 @@ H5G_mkroot(H5F_t *f, size_t size_hint)
*-------------------------------------------------------------------------
*/
H5G_t *
-H5G_create(H5F_t *f, const char *name, size_t size_hint)
+H5G_create(H5G_t *loc, const char *name, size_t size_hint)
{
const char *rest = NULL; /*the base name */
H5G_entry_t grp_ent; /*group containing new group */
char _comp[1024]; /*name component */
size_t nchars; /*number of characters in compon*/
- herr_t status; /*function return status */
H5G_t *grp = NULL; /*new group */
FUNC_ENTER(H5G_create, NULL);
/* check args */
- assert(f);
+ assert(loc);
assert(name && *name);
- /*
- * Try to create the root group. Ignore the error if this function
- * fails because the root group already exists.
- */
- if ((status=H5G_mkroot(f, H5G_SIZE_HINT))<0 && -2!=status) {
- HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't create root group");
- }
- H5E_clear();
-
/* lookup name */
- if (0 == H5G_namei(f, NULL, name, &rest, &grp_ent, NULL)) {
+ if (0 == H5G_namei(H5G_entof(loc), name, &rest, &grp_ent, NULL)) {
HRETURN_ERROR(H5E_SYM, H5E_EXISTS, NULL, "already exists");
}
H5E_clear(); /*it's OK that we didn't find it */
@@ -881,7 +864,7 @@ H5G_create(H5F_t *f, const char *name, size_t size_hint)
/* create an open group */
grp = H5MM_xcalloc(1, sizeof(H5G_t));
- if (H5G_stab_create(f, size_hint, &(grp->ent)/*out*/) < 0) {
+ if (H5G_stab_create(grp_ent.file, size_hint, &(grp->ent)/*out*/) < 0) {
grp = H5MM_xfree(grp);
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't create grp");
}
@@ -914,7 +897,7 @@ H5G_create(H5F_t *f, const char *name, size_t size_hint)
*-------------------------------------------------------------------------
*/
H5G_t *
-H5G_open(H5F_t *f, const char *name)
+H5G_open(H5G_t *loc, const char *name)
{
H5G_t *grp = NULL;
H5G_t *ret_value = NULL;
@@ -923,15 +906,15 @@ H5G_open(H5F_t *f, const char *name)
FUNC_ENTER(H5G_open, NULL);
/* Check args */
- assert(f);
+ assert(loc);
assert(name && *name);
/* Open the object, making sure it's a group */
grp = H5MM_xcalloc(1, sizeof(H5G_t));
- if (H5G_find(f, name, NULL, &(grp->ent)) < 0) {
+ if (H5G_find(loc, name, NULL, &(grp->ent)/*out*/) < 0) {
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "group not found");
}
- if (H5O_open(f, &(grp->ent)) < 0) {
+ if (H5O_open(&(grp->ent)) < 0) {
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open group");
}
if (NULL==H5O_read (&(grp->ent), H5O_STAB, 0, &mesg)) {
@@ -947,6 +930,7 @@ H5G_open(H5F_t *f, const char *name)
}
FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_reopen
@@ -964,7 +948,7 @@ H5G_open(H5F_t *f, const char *name)
*
*-------------------------------------------------------------------------
*/
-H5G_t *
+H5G_t *
H5G_reopen(H5G_t *grp)
{
FUNC_ENTER(H5G_reopen, NULL);
@@ -976,6 +960,7 @@ H5G_reopen(H5G_t *grp)
FUNC_LEAVE(grp);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_close
@@ -1003,6 +988,7 @@ H5G_close(H5G_t *grp)
assert(grp->nref > 0);
if (1 == grp->nref) {
+ assert (grp!=H5G_fileof(grp)->shared->root_grp);
if (H5O_close(&(grp->ent)) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close");
}
@@ -1011,6 +997,7 @@ H5G_close(H5G_t *grp)
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_set
@@ -1041,13 +1028,15 @@ H5G_close(H5G_t *grp)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_set(H5F_t *f, H5G_t *grp)
+H5G_set (H5G_t *grp)
{
+ H5F_t *f;
+
FUNC_ENTER(H5G_set, FAIL);
/* check args */
- assert(f);
assert(grp);
+ f = H5G_fileof (grp);
/*
* If there is no stack then create one, otherwise close the current
@@ -1056,25 +1045,23 @@ H5G_set(H5F_t *f, H5G_t *grp)
if (!f->cwg_stack) {
f->cwg_stack = H5MM_xcalloc(1, sizeof(H5G_cwgstk_t));
} else if (H5G_close(f->cwg_stack->grp) < 0) {
- HRETURN_ERROR(H5E_SYM, H5E_CWG, FAIL, "couldn't close previous c.w.g.");
+ HRETURN_ERROR(H5E_SYM, H5E_CWG, FAIL,
+ "couldn't close previous current working group");
}
- f->cwg_stack->grp = H5G_reopen(grp);
+ f->cwg_stack->grp = H5G_reopen (grp);
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_getcwg
*
- * Purpose: Returns a ptr to the symbol table entry for the current
- * working group. If there is no current working group then a
- * pointer to the root symbol is returned. If there is no root
- * symbol then the null pointer is returned.
- *
- * Return: Success: Ptr to the current working group or root
- * object. The pointer is valid only until the
- * root object changes or the current working
- * group changes.
+ * Purpose: Returns the current working group.
+ *
+ * Return: Success: The current working group. This group should
+ * not* be closed with H5G_close() when the
+ * caller is done with it.
*
* Failure: NULL
*
@@ -1085,25 +1072,25 @@ H5G_set(H5F_t *f, H5G_t *grp)
*
*-------------------------------------------------------------------------
*/
-static H5G_entry_t *
+H5G_t *
H5G_getcwg(H5F_t *f)
{
- H5G_entry_t *ret_value = NULL;
+ H5G_t *ret_value = NULL;
FUNC_ENTER(H5G_getcwg, NULL);
/* check args */
assert(f);
- /* return a pointer directly into the stack */
- if (f->cwg_stack && f->cwg_stack->grp) {
- ret_value = &(f->cwg_stack->grp->ent);
+ if (f->cwg_stack) {
+ ret_value = f->cwg_stack->grp;
} else {
- ret_value = f->shared->root_ent;
+ ret_value = f->shared->root_grp;
}
-
+
FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_push
@@ -1112,8 +1099,6 @@ H5G_getcwg(H5F_t *f)
* is reopened and held open until it is removed from the stack.
*
* Errors:
- * SYM CWG Can't open group.
- * SYM CWG Not a group.
*
* Return: Success: SUCCEED
*
@@ -1127,14 +1112,13 @@ H5G_getcwg(H5F_t *f)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_push(H5F_t *f, H5G_t *grp)
+H5G_push (H5G_t *grp)
{
- H5G_cwgstk_t *stack = NULL;
+ H5G_cwgstk_t *stack = NULL;
FUNC_ENTER(H5G_push, FAIL);
/* check args */
- assert(f);
assert(grp);
/*
@@ -1142,20 +1126,21 @@ H5G_push(H5F_t *f, H5G_t *grp)
*/
stack = H5MM_xcalloc(1, sizeof(H5G_cwgstk_t));
stack->grp = H5G_reopen(grp);
- stack->next = f->cwg_stack;
- f->cwg_stack = stack;
+ stack->next = H5G_fileof(grp)->cwg_stack;
+ H5G_fileof(grp)->cwg_stack = stack;
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_pop
*
- * Purpose: Pops the top current working group off the stack.
+ * Purpose: Pops the top current working group off the stack. If the
+ * stack becomes empty then the current working group is
+ * implicitly the root group.
*
* Errors:
- * SYM CWG Can't close current working group.
- * SYM CWG Stack is empty.
*
* Return: Success: SUCCEED
*
@@ -1169,7 +1154,7 @@ H5G_push(H5F_t *f, H5G_t *grp)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_pop(H5F_t *f)
+H5G_pop (H5F_t *f)
{
H5G_cwgstk_t *stack = NULL;
@@ -1192,12 +1177,12 @@ H5G_pop(H5F_t *f)
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_insert
*
- * Purpose: Inserts a symbol table entry into the group graph. The file
- * that is used is contained in the ENT argument.
+ * Purpose: Inserts a symbol table entry into the group graph.
*
* Errors:
*
@@ -1213,46 +1198,29 @@ H5G_pop(H5F_t *f)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_insert(const char *name, H5G_entry_t *ent)
+H5G_insert(H5G_t *loc, const char *name, H5G_entry_t *ent)
{
const char *rest = NULL; /*part of name not existing yet */
H5G_entry_t grp; /*entry for group to contain obj */
size_t nchars; /*number of characters in name */
char _comp[1024]; /*name component */
- hbool_t update_grp;
- herr_t status;
FUNC_ENTER(H5G_insert, FAIL);
/* Check args. */
- assert(name && *name);
- assert(ent);
+ assert (loc);
+ assert (name && *name);
+ assert (ent);
/*
* Look up the name -- it shouldn't exist yet.
*/
- if (H5G_namei(ent->file, NULL, name, &rest, &grp, NULL) >= 0) {
+ if (H5G_namei(H5G_entof(loc), name, &rest, &grp, NULL) >= 0) {
HRETURN_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "already exists");
}
H5E_clear(); /*it's OK that we didn't find it */
rest = H5G_component(rest, &nchars);
- if (!rest || !*rest) {
- /*
- * The caller is attempting to insert a root object that either
- * doesn't have a name or we shouldn't interfere with the name
- * it already has as a message.
- */
- if (ent->file->shared->root_ent) {
- HRETURN_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "root exists");
- }
- if (1 != H5O_link(ent, 1)) {
- HRETURN_ERROR(H5E_SYM, H5E_LINK, FAIL, "bad link count");
- }
- ent->name_off = 0;
- ent->file->shared->root_ent = H5G_ent_calloc(ent);
- HRETURN(SUCCEED);
- }
/*
* There should be one component left. Make sure it's null
* terminated.
@@ -1269,40 +1237,9 @@ H5G_insert(const char *name, H5G_entry_t *ent)
rest = _comp;
}
}
- if (!ent->file->shared->root_ent) {
- /*
- * This will be the only object in the file. Insert it as the root
- * object and add a name messaage to the object header (or modify
- * the first one we find).
- */
- H5O_name_t name_mesg;
- name_mesg.s = rest;
- if (H5O_modify(ent, H5O_NAME, 0, 0, &name_mesg) < 0) {
- HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
- "cannot add/change name message");
- }
- if (1 != H5O_link(ent, 1)) {
- HRETURN_ERROR(H5E_SYM, H5E_LINK, FAIL, "bad link count");
- }
- ent->file->shared->root_ent = H5G_ent_calloc(ent);
- HRETURN(SUCCEED);
- }
- /*
- * Make sure the root group exists. Ignore the failure if it's
- * because the group already exists.
- */
- update_grp = (hbool_t)H5F_addr_eq(&(grp.header),
- &(ent->file->shared->root_ent->header));
- if ((status = H5G_mkroot(ent->file, H5G_SIZE_HINT)) < 0 && -2 != status) {
- HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create root group");
- }
- H5E_clear();
- if (update_grp==TRUE)
- grp = *(ent->file->shared->root_ent);
/*
- * This is the normal case. The object is just being inserted as a normal
- * entry into a symbol table.
+ * The object into a symbol table.
*/
if (H5O_link(ent, 1) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_LINK, FAIL, "link inc failure");
@@ -1312,23 +1249,19 @@ H5G_insert(const char *name, H5G_entry_t *ent)
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5G_find
*
- * Purpose: Finds an object with the specified NAME in file F. If
- * the name is relative then it is interpretted relative
- * to the current working group. On successful return,
- * GRP_ENT (if non-null) will be initialized with the symbol
- * table information for the group in which the object
- * appears (it will have an undefined object header address if
- * the object is the root object) and OBJ_ENT will be
+ * Purpose: Finds an object with the specified NAME at location LOC. On
+ * successful return, GRP_ENT (if non-null) will be initialized
+ * with the symbol table information for the group in which the
+ * object appears (it will have an undefined object header
+ * address if the object is the root object) and OBJ_ENT will be
* initialized with the symbol table entry for the object
* (OBJ_ENT is optional when the caller is interested only in
- * the existence of the object).
- *
- * This function will fail if the root object is requested and
- * there is none.
+ * the existence of the object).
*
* Errors:
*
@@ -1346,17 +1279,109 @@ H5G_insert(const char *name, H5G_entry_t *ent)
*-------------------------------------------------------------------------
*/
herr_t
-H5G_find(H5F_t *f, const char *name,
- H5G_entry_t *grp_ent /*out */ , H5G_entry_t *obj_ent /*out */ )
+H5G_find(H5G_t *loc, const char *name,
+ H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/)
{
FUNC_ENTER(H5G_find, FAIL);
/* check args */
- assert(f);
- assert(name && *name);
+ assert (loc);
+ assert (name && *name);
- if (H5G_namei(f, NULL, name, NULL, grp_ent, obj_ent) < 0) {
+ if (H5G_namei(H5G_entof(loc), name, NULL, grp_ent, obj_ent) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found");
}
FUNC_LEAVE(SUCCEED);
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_entof
+ *
+ * Purpose: Returns a pointer to the entry for a group.
+ *
+ * Return: Success: Ptr to group entry
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, March 24, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_entry_t *
+H5G_entof (H5G_t *grp)
+{
+ return grp ? &(grp->ent) : NULL;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_fileof
+ *
+ * Purpose: Returns the file to which the specified group belongs.
+ *
+ * Return: Success: File pointer.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, March 24, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5F_t *
+H5G_fileof (H5G_t *grp)
+{
+ assert (grp);
+ return grp->ent.file;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_loc
+ *
+ * Purpose: Given a location ID return a group. The group should not be
+ * closed.
+ *
+ * Return: Success: Group pointer.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, March 24, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_t *
+H5G_loc (hid_t loc_id)
+{
+ H5F_t *f;
+ H5G_t *ret_value = NULL;
+
+ FUNC_ENTER (H5G_loc, NULL);
+
+ if (H5_FILE==H5I_group (loc_id)) {
+ if (NULL==(f=H5I_object (loc_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, NULL, "invalid file ID");
+ }
+ if (NULL==(ret_value=H5G_getcwg (f))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, NULL,
+ "unable to get current working directory");
+ }
+ } else if (H5_GROUP==H5I_group (loc_id)) {
+ if (NULL==(ret_value=H5I_object (loc_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, NULL, "invalid group ID");
+ }
+ } else {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, NULL, "not a location");
+ }
+
+ FUNC_LEAVE (ret_value);
+}
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 425d8a5..b79d1e2 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -91,15 +91,20 @@ typedef struct H5G_t H5G_t;
* Library prototypes... These are the ones that other packages routinely
* call.
*/
-H5G_t *H5G_create (H5F_t *f, const char *name, size_t size_hint);
-H5G_t *H5G_open (H5F_t *f, const char *name);
+H5G_t *H5G_loc (hid_t loc_id);
+herr_t H5G_mkroot (H5F_t *f, H5G_entry_t *root_entry);
+H5G_entry_t *H5G_entof (H5G_t *grp);
+H5F_t *H5G_fileof (H5G_t *grp);
+H5G_t *H5G_create (H5G_t *loc, const char *name, size_t size_hint);
+H5G_t *H5G_open (H5G_t *loc, const char *name);
H5G_t *H5G_reopen (H5G_t *grp);
herr_t H5G_close (H5G_t *grp);
-herr_t H5G_set (H5F_t *f, H5G_t *grp);
-herr_t H5G_push (H5F_t *f, H5G_t *grp);
+herr_t H5G_set (H5G_t *grp);
+herr_t H5G_push (H5G_t *grp);
herr_t H5G_pop (H5F_t *f);
-herr_t H5G_insert (const char *name, H5G_entry_t *ent);
-herr_t H5G_find (H5F_t *f, const char *name, H5G_entry_t *grp_ent/*out*/,
+H5G_t *H5G_getcwg(H5F_t *f);
+herr_t H5G_insert (H5G_t *cwg, const char *name, H5G_entry_t *ent);
+herr_t H5G_find (H5G_t *cwg, const char *name, H5G_entry_t *grp_ent/*out*/,
H5G_entry_t *ent/*out*/);
herr_t H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent);
herr_t H5G_ent_decode (H5F_t *f, const uint8 **pp, H5G_entry_t *ent/*out*/);
diff --git a/src/H5O.c b/src/H5O.c
index af9ec82..bf60b09 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -147,6 +147,7 @@ H5O_create(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/)
/* allocate disk space for header and first chunk */
size = H5O_SIZEOF_HDR(f) + size_hint;
+ ent->file = f;
if (H5MF_alloc(f, H5MF_META, size, &(ent->header)/*out*/) < 0) {
HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"unable to allocate file space for object header hdr");
@@ -190,12 +191,13 @@ H5O_create(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/)
}
/* open it */
- if (H5O_open(f, ent) < 0) {
+ if (H5O_open(ent) < 0) {
HRETURN_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL,
"unable to open object header");
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5O_open
@@ -215,13 +217,13 @@ H5O_create(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/)
*-------------------------------------------------------------------------
*/
herr_t
-H5O_open(H5F_t *f, H5G_entry_t *obj_ent)
+H5O_open(H5G_entry_t *obj_ent)
{
FUNC_ENTER(H5O_open, FAIL);
/* Check args */
- assert(f);
assert(obj_ent);
+ assert(obj_ent->file);
#ifdef H5O_DEBUG
fprintf(stderr, ">");
@@ -230,10 +232,10 @@ H5O_open(H5F_t *f, H5G_entry_t *obj_ent)
#endif
/* Increment open-lock counters */
- obj_ent->file = f;
obj_ent->file->nopen++;
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5O_close
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 079ba24..b20e6ed 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -202,7 +202,7 @@ typedef struct H5O_stab_t {
/* General message operators */
herr_t H5O_create (H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/);
-herr_t H5O_open (H5F_t *f, H5G_entry_t *ent);
+herr_t H5O_open (H5G_entry_t *ent);
herr_t H5O_close (H5G_entry_t *ent);
intn H5O_link (H5G_entry_t *ent, intn adjust);
void *H5O_read (H5G_entry_t *ent, const H5O_class_t *type, intn sequence,
diff --git a/src/H5detect.c b/src/H5detect.c
index 3d56c39..93343fd 100644
--- a/src/H5detect.c
+++ b/src/H5detect.c
@@ -1,4 +1,4 @@
-/**/
+/*keep this here -RPM*/
static const char *FileHeader = "\n\
/*-------------------------------------------------------------------------\n\
* Copyright (C) 1997 National Center for Supercomputing Applications. \n\
diff --git a/src/Makefile.in b/src/Makefile.in
index aff0d60..66a3949 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -11,7 +11,7 @@ CPPFLAGS=-I. @CPPFLAGS@
# These are our main targets:
LIB=libhdf5.a
-PROGS=debug
+PROGS=debug h5ls
# Source and object files for the library (lexicographically)...
PARALLEL_SRC=H5Fmpio.c
@@ -29,7 +29,7 @@ LIB_OBJ=$(LIB_SRC:.c=.o)
MOSTLYCLEAN=H5detect.o H5detect H5Tinit.o H5Tinit.c
# Source and object files for programs...
-PROG_SRC=debug.c
+PROG_SRC=debug.c h5ls.c
PROG_OBJ=$(PROG_SRC:.c=.o)
# Public header files (to be installed)...
@@ -56,4 +56,7 @@ H5detect: H5detect.o
debug: debug.o $(LIB)
$(CC) $(CFLAGS) -o $@ debug.o $(LIB) $(LIBS)
+h5ls: h5ls.o $(LIB)
+ $(CC) $(CFLAGS) -o $@ h5ls.o $(LIB) $(LIBS)
+
@CONCLUDE@
diff --git a/src/h5ls.c b/src/h5ls.c
new file mode 100644
index 0000000..e8ac70c
--- /dev/null
+++ b/src/h5ls.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 1998 NCSA
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Monday, March 23, 1998
+ */
+#include <assert.h>
+#include <hdf5.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: list
+ *
+ * Purpose: Prints the group member name.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Monday, March 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+list (hid_t group, const char *name, void *op_data)
+{
+ hid_t obj;
+ hid_t (*func)(void*);
+ void *edata;
+ int i;
+
+ /* Disable error reporting */
+ H5Eget_auto (&func, &edata);
+ H5Eset_auto (NULL, NULL);
+
+ /* Print info about each name */
+ printf ("%-30s", name);
+ if ((obj=H5Dopen (group, name))>=0) {
+ size_t size[64];
+ hid_t space = H5Dget_space (obj);
+ int ndims = H5Sget_dims (space, size);
+ printf (" Dataset {");
+ for (i=0; i<ndims; i++) {
+ printf ("%s%lu", i?", ":"", (unsigned long)size[i]);
+ }
+ printf ("}\n");
+ H5Dclose (space);
+ H5Dclose (obj);
+ } else if ((obj=H5Gopen (group, name))>=0) {
+ printf (" Group\n");
+ H5Gclose (obj);
+ } else {
+ printf (" Unknown Type\n");
+ }
+
+ /* Restore error reporting */
+ H5Eset_auto (func, edata);
+ return 0;
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: Opens a file and lists the specified group
+ *
+ * Return: Success: 0
+ *
+ * Failure: 1
+ *
+ * Programmer: Robb Matzke
+ * Monday, March 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main (int argc, char *argv[])
+{
+ hid_t file;
+ herr_t status;
+
+ assert (3==argc);
+
+ file = H5Fopen (argv[1], H5F_ACC_RDONLY, H5P_DEFAULT);
+ assert (file>=0);
+
+ status = H5Giterate (file, argv[2], NULL, list, NULL);
+ assert (status>=0);
+
+ H5Fclose (file);
+ return 0;
+}