[svn-r346] Changes since 19980410

----------------------

./html/H5.format.html
./src/H5E.c
./src/H5Epublic.h
./src/H5F.c
./src/H5G.c
./src/H5Gent.c
./src/H5Gnode.c
./src/H5Gprivate.h
./src/h5ls.c
./test/Makefile.in
	Symbolic links are now supported.  The ./test/links program
	will create a `links.h5' file that demonstrates hard links,
	soft links, dangling links, and recursive links.  A symbolic
	link is a symbol table entity and doesn't have an object
	header.  It's format is described in H5.format.hml.

./src/H5G.c
./src/H5Gpublic.h
./src/h5ls.c
	Implemented H5Gstat() and H5Gget_linkval() as documented by
	Quincey.  The `H5G_type_t type' field of `H5G_stat_t' was
	changed to `int type' because H5G_type_t was already used and
	the `type' data type should be open-ended.

./src/H5Ffamily.c
	Removed an incorrect diagnostic message.

./test/big.c
	Added read/write calls to test partial I/O to big contiguous
	datasets.  With no arguments it writes to a dataset and prints
	the list of points written which should be redirected to a
	file.  With an argument (the name of a file containing the
	stdout of a run with no arguments) values are read from the
	dataset.  One would typically say `big >x && big x'.
This commit is contained in:
Robb Matzke 1998-04-14 11:44:46 -05:00
parent 3f571b6b44
commit b6fc6ede10
16 changed files with 807 additions and 104 deletions

View File

@ -198,6 +198,7 @@
./test/hyperslab.c
./test/iopipe.c
./test/istore.c
./test/links.c
./test/shtype.c
./test/testhdf5.c
./test/testhdf5.h

View File

@ -100,6 +100,7 @@ static const H5E_minor_mesg_t H5E_minor_mesg_g[] = {
{H5E_COMPLEN, "Name component is too long"},
{H5E_CWG, "Problem with current working group"},
{H5E_LINK, "Link count failure"},
{H5E_SLINK, "Symbolic link error"},
};
/* Interface initialization? */

View File

@ -112,7 +112,8 @@ typedef enum H5E_minor_t {
H5E_CANTOPENOBJ, /*Can't open object */
H5E_COMPLEN, /*name component is too long */
H5E_CWG, /*problem with current working group */
H5E_LINK /*link count failure */
H5E_LINK, /*link count failure */
H5E_SLINK /*symbolic link error */
} H5E_minor_t;
/* Information about an error */

View File

@ -1633,7 +1633,7 @@ H5F_debug(H5F_t *f, const haddr_t __unused__ *addr, FILE * stream,
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));
indent+3, MAX(0, fwidth-3), NULL);
}
FUNC_LEAVE(SUCCEED);
}

View File

@ -197,7 +197,7 @@ H5F_fam_open(const char *name, const H5F_access_t *access_parms,
* descriptors (all family members are open at once).
*/
#ifdef H5F_DEBUG
if (access_parms->u.fam.offset_bits+2>=8*sizeof(off_t)) {
if (access_parms->u.fam.offset_bits+2>8*sizeof(off_t)) {
fprintf (stderr, "H5F: family member size may be too large.\n");
}
#endif

428
src/H5G.c
View File

@ -75,11 +75,12 @@
/* Packages needed by this file... */
#include <H5private.h>
#include <H5Iprivate.h>
#include <H5Bprivate.h>
#include <H5Dprivate.h>
#include <H5Eprivate.h>
#include <H5Gpkg.h>
#include <H5HLprivate.h>
#include <H5Iprivate.h>
#include <H5MMprivate.h>
#include <H5Oprivate.h>
@ -561,6 +562,7 @@ H5Glink (hid_t loc_id, H5G_link_t type, const char *cur_name,
FUNC_ENTER (H5Glink, FAIL);
/* Check arguments */
if (NULL==(loc=H5G_loc (loc_id))) {
HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
}
@ -615,6 +617,93 @@ H5Gunlink (hid_t __unused__ loc_id, const char __unused__ *name)
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5Gstat
*
* Purpose: Returns information about an object. If FOLLOW_LINK is
* non-zero then all symbolic links are followed; otherwise all
* links except the last component of the name are followed.
*
* Return: Success: SUCCEED with the fields of STATBUF (if
* non-null) initialized.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Monday, April 13, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Gstat (hid_t loc_id, const char *name, hbool_t follow_link,
H5G_stat_t *statbuf/*out*/)
{
H5G_t *loc = NULL;
FUNC_ENTER (H5Gstat, FAIL);
/* Check arguments */
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");
}
/* Get info */
if (H5G_stat (loc, name, follow_link, statbuf)<0) {
HRETURN_ERROR (H5E_ARGS, H5E_CANTINIT, FAIL, "cannot stat object");
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5Gget_linkval
*
* Purpose: Returns the value of a symbolic link whose name is NAME. At
* most SIZE characters (counting the null terminator) are
* copied to the BUF result buffer.
*
* Return: Success: SUCCEED, the link value is in BUF.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Monday, April 13, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Gget_linkval (hid_t loc_id, const char *name, size_t size, char *buf/*out*/)
{
H5G_t *loc = NULL;
FUNC_ENTER (H5Gget_linkval, FAIL);
/* Check arguments */
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");
}
/* Get the link value */
if (H5G_linkval (loc, name, size, buf)<0) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
"unable to get link value");
}
FUNC_LEAVE (SUCCEED);
}
/*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
@ -746,12 +835,18 @@ H5G_component(const char *name, size_t *size_p)
* 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).
*
* Symbolic links are followed automatically, but if
* FOLLOW_SLINK is false and the last component of the name is a
* symbolic link then that link is not followed. At most NLINKS
* are followed and the next link generates an error.
*
* Errors:
*
* Return: Success: SUCCEED if name can be fully resolved. See
* above for values of REST, GRP_ENT, and
* OBJ_ENT.
* OBJ_ENT. NLINKS has been decremented for
* each symbolic link that was followed.
*
* Failure: FAIL if the name could not be fully resolved.
* See above for values of REST, GRP_ENT, and
@ -767,22 +862,21 @@ H5G_component(const char *name, size_t *size_p)
*/
static herr_t
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/*out*/, H5G_entry_t *obj_ent/*out*/,
hbool_t follow_slink, intn *nlinks)
{
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 */
/* clear output args before FUNC_ENTER() in case it fails */
int _nlinks = H5G_NLINKS;
const char *s = NULL;
if (rest) *rest = name;
if (!grp_ent) grp_ent = &_grp_ent;
if (!obj_ent) obj_ent = &_obj_ent;
memset(grp_ent, 0, sizeof(H5G_entry_t));
H5F_addr_undef(&(grp_ent->header));
memset(obj_ent, 0, sizeof(H5G_entry_t));
H5F_addr_undef(&(obj_ent->header));
if (!nlinks) nlinks = &_nlinks;
FUNC_ENTER(H5G_namei, FAIL);
/*
@ -799,6 +893,9 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/,
} else {
*obj_ent = *loc_ent;
}
memset(grp_ent, 0, sizeof(H5G_entry_t));
H5F_addr_undef(&(grp_ent->header));
/* traverse the name */
while ((name = H5G_component(name, &nchars)) && *name) {
@ -837,6 +934,24 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/,
*/
HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found");
}
/*
* If we found a symbolic link then we should follow it. But if this
* is the last component of the name and FOLLOW_SLINK is zero then we
* don't follow it.
*/
if (H5G_CACHED_SLINK==obj_ent->type &&
(follow_slink || ((s=H5G_component(name+nchars, NULL)) && *s))) {
if ((*nlinks)-- <= 0) {
HRETURN_ERROR (H5E_SYM, H5E_SLINK, FAIL,
"too many symbolic links");
}
if (H5G_traverse_slink (grp_ent, obj_ent, nlinks)<0) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
"symbolic link traversal failed");
}
}
/* next component */
name += nchars;
}
@ -845,6 +960,63 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/,
FUNC_LEAVE(SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_traverse_slink
*
* Purpose: Traverses symbolic link. The link head appears in the group
* whose entry is GRP_ENT and the link head entry is OBJ_ENT.
*
* Return: Success: SUCCEED, OBJ_ENT will contain information
* about the object to which the link points and
* GRP_ENT will contain the information about
* the group in which the link tail appears.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Friday, April 10, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/,
H5G_entry_t *obj_ent/*in,out*/,
intn *nlinks/*in,out*/)
{
H5O_stab_t stab_mesg; /*info about local heap */
const char *clv = NULL; /*cached link value */
char *linkval = NULL; /*the copied link value */
herr_t ret_value = FAIL; /*return value */
FUNC_ENTER (H5G_traverse_slink, FAIL);
/* Get the link value */
if (NULL==H5O_read (grp_ent, H5O_STAB, 0, &stab_mesg)) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
"unable to determine local heap address");
}
if (NULL==(clv=H5HL_peek (grp_ent->file, &(stab_mesg.heap_addr),
obj_ent->cache.slink.lval_offset))) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
"unable to read symbolic link value");
}
linkval = H5MM_xstrdup (clv);
/* Traverse the link */
if (H5G_namei (grp_ent, linkval, NULL, grp_ent, obj_ent, TRUE, nlinks)) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
"unable to follow symbolic link");
}
ret_value = SUCCEED;
done:
H5MM_xfree (linkval);
FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5G_mkroot
@ -963,7 +1135,8 @@ H5G_create(H5G_t *loc, const char *name, size_t size_hint)
assert(name && *name);
/* lookup name */
if (0 == H5G_namei(H5G_entof(loc), name, &rest, &grp_ent, NULL)) {
if (0 == H5G_namei(H5G_entof(loc), name, &rest, &grp_ent, NULL,
TRUE, NULL)) {
HRETURN_ERROR(H5E_SYM, H5E_EXISTS, NULL, "already exists");
}
H5E_clear(); /*it's OK that we didn't find it */
@ -1338,7 +1511,7 @@ H5G_insert(H5G_t *loc, const char *name, H5G_entry_t *ent)
/*
* Look up the name -- it shouldn't exist yet.
*/
if (H5G_namei(H5G_entof(loc), name, &rest, &grp, NULL) >= 0) {
if (H5G_namei(H5G_entof(loc), name, &rest, &grp, NULL, TRUE, NULL) >= 0) {
HRETURN_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "already exists");
}
H5E_clear(); /*it's OK that we didn't find it */
@ -1411,7 +1584,8 @@ H5G_find(H5G_t *loc, const char *name,
assert (loc);
assert (name && *name);
if (H5G_namei(H5G_entof(loc), name, NULL, grp_ent, obj_ent) < 0) {
if (H5G_namei(H5G_entof(loc), name, NULL, grp_ent, obj_ent,
TRUE, NULL)<0) {
HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found");
}
FUNC_LEAVE(SUCCEED);
@ -1531,7 +1705,13 @@ herr_t
H5G_link (H5G_t *loc, H5G_type_t type, const char *cur_name,
const char *new_name)
{
H5G_entry_t cur_obj;
H5G_entry_t cur_obj; /*entry for the link tail */
H5G_entry_t grp_ent; /*ent for grp containing link hd*/
H5O_stab_t stab_mesg; /*symbol table message */
const char *rest = NULL; /*last component of new name */
char _comp[1024]; /*name component */
size_t nchars; /*characters in component */
size_t offset; /*offset to sym-link value */
FUNC_ENTER (H5G_link, FAIL);
@ -1542,8 +1722,74 @@ H5G_link (H5G_t *loc, H5G_type_t type, const char *cur_name,
switch (type) {
case H5G_LINK_SOFT:
HRETURN_ERROR (H5E_SYM, H5E_UNSUPPORTED, FAIL,
"unable to create soft link (not implemented yet)");
/*
* Lookup the the new_name so we can get the group which will contain
* the new entry. The entry shouldn't exist yet.
*/
if (H5G_namei (H5G_entof(loc), new_name, &rest, &grp_ent, NULL,
TRUE, NULL)>=0) {
HRETURN_ERROR (H5E_SYM, H5E_EXISTS, FAIL, "already exists");
}
H5E_clear (); /*it's okay that we didn't find it*/
rest = H5G_component (rest, &nchars);
/*
* There should be one component left. Make sure it's null
* terminated and that `rest' points to it.
*/
if (rest[nchars]) {
if (H5G_component (rest+nchars, NULL)) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
"component not found");
} else if (nchars+1 > sizeof _comp) {
HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, FAIL,
"name component is too long");
} else {
HDmemcpy (_comp, rest, nchars);
_comp[nchars] = '\0';
rest = _comp;
}
}
/*
* Add the link-value to the local heap for the symbol table which
* will contain the link.
*/
if (NULL==H5O_read (&grp_ent, H5O_STAB, 0, &stab_mesg)) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL,
"unable to determine local heap address");
}
if ((size_t)(-1)==(offset=H5HL_insert (grp_ent.file,
&(stab_mesg.heap_addr),
strlen(cur_name)+1,
cur_name))) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL,
"unable to write link value to local heap");
}
H5O_reset (H5O_STAB, &stab_mesg);
/*
* Create a symbol table entry for the link. The object header is
* undefined and the cache contains the link-value offset.
*/
HDmemset (&cur_obj, 0, sizeof cur_obj);
H5F_addr_undef (&(cur_obj.header));
cur_obj.file = grp_ent.file;
cur_obj.type = H5G_CACHED_SLINK;
cur_obj.cache.slink.lval_offset = offset;
/*
* Insert the link head in the symbol table. This shouldn't ever
* fail because we've already checked that the link head doesn't
* exist and the file is writable (because the local heap is
* writable). But if it does, the only side effect is that the local
* heap has some extra garbage in it.
*/
if (H5G_stab_insert (&grp_ent, rest, &cur_obj)<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL,
"unable to create new name/link for object");
}
break;
case H5G_LINK_HARD:
if (H5G_find (loc, cur_name, NULL, &cur_obj)<0) {
@ -1563,3 +1809,153 @@ H5G_link (H5G_t *loc, H5G_type_t type, const char *cur_name,
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_stat
*
* Purpose: Returns information about an object.
*
* Return: Success: SUCCEED with info about the object returned
* through STATBUF if it isn't the null pointer.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Monday, April 13, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_stat (H5G_t *loc, const char *name, hbool_t follow_link,
H5G_stat_t *statbuf/*out*/)
{
H5O_stab_t stab_mesg;
H5G_entry_t grp_ent, obj_ent;
const char *s = NULL;
H5D_t *temp_dset = NULL;
H5G_t *temp_grp = NULL;
FUNC_ENTER (H5G_stat, FAIL);
assert (loc);
assert (name && *name);
if (statbuf) HDmemset (statbuf, 0, sizeof *statbuf);
/* Find the object's symbol table entry */
if (H5G_namei (H5G_entof(loc), name, NULL, &grp_ent/*out*/,
&obj_ent/*out*/, follow_link, NULL)<0) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to stat object");
}
/*
* Initialize the stat buf. Symbolic links aren't normal objects and
* therefor don't have much of the normal info. However, the link value
* length is specific to symbolic links.
*/
if (statbuf) {
if (H5G_CACHED_SLINK!=obj_ent.type) {
statbuf->objno[0] = (unsigned long)(obj_ent.header.offset);
statbuf->objno[1] = (unsigned long)(obj_ent.header.offset >>
8*sizeof(long));
statbuf->nlink = H5O_link (&obj_ent, 0);
statbuf->type = H5G_LINK;
} else {
if (NULL==H5O_read (&grp_ent, H5O_STAB, 0, &stab_mesg) ||
NULL==(s=H5HL_peek (grp_ent.file, &(stab_mesg.heap_addr),
obj_ent.cache.slink.lval_offset))) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL,
"unable to read symbolic link value");
}
statbuf->linklen = strlen(s)+1; /*count the null terminator*/
/*
* Determining the type of an object is a rather expensive
* operation compared to the other stuff here. It's also not
* very flexible.
*/
if (NULL!=(temp_dset=H5D_open (loc, name))) {
statbuf->type = H5G_DATASET;
H5D_close (temp_dset);
} else if (NULL!=(temp_grp=H5G_open (loc, name))) {
statbuf->type = H5G_GROUP;
H5G_close (temp_grp);
} else {
statbuf->type = H5G_UNKNOWN;
}
H5E_clear(); /*clear errors resulting from checking type*/
}
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_linkval
*
* Purpose: Returns the value of a symbolic link.
*
* Return: Success: SUCCEED, with at most SIZE bytes of the link
* value copied into the BUF buffer. If the
* link value is larger than SIZE characters
* counting the null terminator then the BUF
* result will not be null terminated.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Monday, April 13, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_linkval (H5G_t *loc, const char *name, size_t size, char *buf/*out*/)
{
const char *s = NULL;
H5G_entry_t grp_ent, obj_ent;
H5O_stab_t stab_mesg;
FUNC_ENTER (H5G_linkval, FAIL);
/*
* Get the symbol table entry for the link head and the symbol table
* entry for the group in which the link head appears.
*/
if (H5G_namei (H5G_entof(loc), name, NULL, &grp_ent/*out*/,
&obj_ent/*out*/, FALSE, NULL)<0) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
"symbolic link was not found");
}
if (H5G_CACHED_SLINK!=obj_ent.type) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL,
"object is not a symbolic link");
}
/*
* Get the address of the local heap for the link value and a pointer
* into that local heap.
*/
if (NULL==H5O_read (&grp_ent, H5O_STAB, 0, &stab_mesg)) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL,
"unable to determine local heap address");
}
if (NULL==(s=H5HL_peek (grp_ent.file, &(stab_mesg.heap_addr),
obj_ent.cache.slink.lval_offset))) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL,
"unable to read symbolic link value");
}
/* Copy to output buffer */
if (size>0 && buf) {
strncpy (buf, s, size);
}
FUNC_LEAVE (SUCCEED);
}

View File

@ -10,6 +10,7 @@
#include <H5private.h>
#include <H5Eprivate.h>
#include <H5Gpkg.h>
#include <H5HLprivate.h>
#include <H5MMprivate.h>
#define PABLO_MASK H5G_ent_mask
@ -204,6 +205,10 @@ H5G_ent_decode(H5F_t *f, const uint8 **pp, H5G_entry_t *ent)
H5F_addr_decode(f, pp, &(ent->cache.stab.heap_addr));
break;
case H5G_CACHED_SLINK:
UINT32DECODE (*pp, ent->cache.slink.lval_offset);
break;
default:
HDabort();
}
@ -310,6 +315,10 @@ H5G_ent_encode(H5F_t *f, uint8 **pp, H5G_entry_t *ent)
H5F_addr_encode(f, pp, &(ent->cache.stab.heap_addr));
break;
case H5G_CACHED_SLINK:
UINT32ENCODE (*pp, ent->cache.slink.lval_offset);
break;
default:
HDabort();
}
@ -350,8 +359,10 @@ H5G_ent_encode(H5F_t *f, uint8 **pp, H5G_entry_t *ent)
*/
herr_t
H5G_ent_debug(H5F_t __unused__ *f, H5G_entry_t *ent, FILE * stream,
intn indent, intn fwidth)
intn indent, intn fwidth, const haddr_t *heap)
{
const char *lval = NULL;
FUNC_ENTER(H5G_ent_debug, FAIL);
fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
@ -387,6 +398,19 @@ H5G_ent_debug(H5F_t __unused__ *f, H5G_entry_t *ent, FILE * stream,
fprintf(stream, "\n");
break;
case H5G_CACHED_SLINK:
fprintf (stream, "Symbolic Link\n");
fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
"Link value offset:",
(unsigned long)(ent->cache.slink.lval_offset));
if (heap && H5F_addr_defined (heap)) {
lval = H5HL_peek (ent->file, heap, ent->cache.slink.lval_offset);
fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth,
"Link value:",
lval);
}
break;
default:
fprintf(stream, "*** Unknown symbol type %d\n", ent->type);
break;

View File

@ -985,7 +985,7 @@ H5G_node_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent,
"Name:",
s);
}
H5G_ent_debug(f, sn->entry + i, stream, indent, fwidth);
H5G_ent_debug(f, sn->entry + i, stream, indent, fwidth, heap);
}
H5AC_unprotect(f, H5AC_SNODE, addr, sn);

View File

@ -33,6 +33,7 @@
#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
#define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */
#define H5G_NO_CHANGE (-1) /*see H5G_ent_modified() */
#define H5G_NLINKS 16 /*max symlinks to follow per lookup */
/*
* The disk size for a symbol table entry...
@ -54,8 +55,9 @@ typedef enum H5G_type_t {
H5G_CACHED_ERROR = -1, /*force enum to be signed */
H5G_NOTHING_CACHED = 0, /*nothing is cached, must be 0 */
H5G_CACHED_STAB = 1, /*symbol table, `stab' */
H5G_CACHED_SLINK = 2, /*symbolic link */
H5G_NCACHED = 2 /*THIS MUST BE LAST */
H5G_NCACHED = 3 /*THIS MUST BE LAST */
} H5G_type_t;
/*
@ -70,6 +72,10 @@ typedef union H5G_cache_t {
haddr_t btree_addr; /*file address of symbol table B-tree*/
haddr_t heap_addr; /*file address of stab name heap */
} stab;
struct {
size_t lval_offset; /*link value offset */
} slink;
} H5G_cache_t;
/*
@ -106,9 +112,16 @@ herr_t H5G_pop (H5F_t *f);
H5G_t *H5G_getcwg(H5F_t *f);
herr_t H5G_link (H5G_t *loc, H5G_type_t type, const char *cur_name,
const char *new_name);
herr_t H5G_stat (H5G_t *loc, const char *name, hbool_t follow_link,
H5G_stat_t *statbuf/*out*/);
herr_t H5G_linkval (H5G_t *loc, const char *name, size_t size,
char *buf/*out*/);
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_traverse_slink (H5G_entry_t *grp_ent/*in,out*/,
H5G_entry_t *obj_ent/*in,out*/,
intn *nlinks/*in,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*/);
@ -127,6 +140,6 @@ H5G_entry_t *H5G_ent_calloc (H5G_entry_t *init);
H5G_cache_t *H5G_ent_cache (H5G_entry_t *ent, H5G_type_t *cache_type);
herr_t H5G_ent_modified (H5G_entry_t *ent, H5G_type_t cache_type);
herr_t H5G_ent_debug (H5F_t *f, H5G_entry_t *ent, FILE * stream, intn indent,
intn fwidth);
intn fwidth, const haddr_t *heap);
#endif

View File

@ -27,12 +27,29 @@
extern "C" {
#endif
/* Types of links */
typedef enum H5G_link_t {
H5G_LINK_ERROR = -1,
H5G_LINK_HARD = 0,
H5G_LINK_SOFT = 1
} H5G_link_t;
/* An object has a certain type */
#define H5G_UNKNOWN (-1) /* Unknown object type */
#define H5G_LINK 0 /* Object is a symbolic link */
#define H5G_GROUP 1 /* Object is a group */
#define H5G_DATASET 2 /* Object is a dataset */
/* Information about an object */
typedef struct H5G_stat_t {
unsigned long fileno[2];
unsigned long objno[2];
unsigned nlink;
int type;
size_t linklen;
} H5G_stat_t;
typedef herr_t (*H5G_iterate_t)(hid_t group, const char *group_name,
void *op_data);
@ -48,6 +65,10 @@ herr_t H5Gmove (hid_t loc_id, const char *src, const char *dst);
herr_t H5Glink (hid_t loc_id, H5G_link_t type, const char *cur_name,
const char *new_name);
herr_t H5Gunlink (hid_t loc_id, const char *name);
herr_t H5Gstat (hid_t loc_id, const char *name, hbool_t follow_link,
H5G_stat_t *statbuf/*out*/);
herr_t H5Gget_linkval (hid_t loc_id, const char *name, size_t size,
char *buf/*out*/);
#ifdef __cplusplus
}

View File

@ -1,9 +1,9 @@
/*
* Copyright (C) 1997 National Center for Supercomputing Applications
* All rights reserved.
* All rights reserved.
*
* Programmer: Robb Matzke <matzke@llnl.gov>
* Friday, September 19, 1997
* Friday, September 19, 1997
*
*/
#define H5G_PACKAGE
@ -16,31 +16,31 @@
#include <H5MMprivate.h>
#include <H5Oprivate.h>
#define PABLO_MASK H5G_stab_mask
static hbool_t interface_initialize_g = FALSE;
#define INTERFACE_INIT NULL
#define PABLO_MASK H5G_stab_mask
static hbool_t interface_initialize_g = FALSE;
#define INTERFACE_INIT NULL
/*-------------------------------------------------------------------------
* Function: H5G_stab_create
* Function: H5G_stab_create
*
* Purpose: Creates a new empty symbol table (object header, name heap,
* and B-tree). The caller can specify an initial size for the
* name heap. The object header of the group is opened for
* write access.
* Purpose: Creates a new empty symbol table (object header, name heap,
* and B-tree). The caller can specify an initial size for the
* name heap. The object header of the group is opened for
* write access.
*
* In order for the B-tree to operate correctly, the first
* item in the heap is the empty string, and must appear at
* heap offset zero.
* In order for the B-tree to operate correctly, the first
* item in the heap is the empty string, and must appear at
* heap offset zero.
*
* Errors:
*
* Return: Success: SUCCEED
* Return: Success: SUCCEED
*
* Failure: FAIL
* Failure: FAIL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
* Aug 1 1997
* Programmer: Robb Matzke
* matzke@llnl.gov
* Aug 1 1997
*
* Modifications:
*
@ -49,8 +49,8 @@ static hbool_t interface_initialize_g = FALSE;
herr_t
H5G_stab_create(H5F_t *f, size_t init, H5G_entry_t *self/*out*/)
{
size_t name; /*offset of "" name */
H5O_stab_t stab; /*symbol table message */
size_t name; /*offset of "" name */
H5O_stab_t stab; /*symbol table message */
FUNC_ENTER(H5G_stab_create, FAIL);
@ -63,11 +63,11 @@ H5G_stab_create(H5F_t *f, size_t init, H5G_entry_t *self/*out*/)
/* Create symbol table private heap */
if (H5HL_create(f, init, &(stab.heap_addr)/*out*/)<0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create heap");
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create heap");
}
name = H5HL_insert(f, &(stab.heap_addr), 1, "");
if ((size_t)(-1)==name) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't initialize heap");
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't initialize heap");
}
/*
@ -78,23 +78,25 @@ H5G_stab_create(H5F_t *f, size_t init, H5G_entry_t *self/*out*/)
/* Create the B-tree */
if (H5B_create(f, H5B_SNODE, NULL, &(stab.btree_addr) /*out */ ) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create B-tree");
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create B-tree");
}
/*
* Create symbol table object header. It has a zero link count
* since nothing refers to it yet. The link count will be
* since nothing refers to it yet. The link count will be
* incremented if the object is added to the group directed graph.
*/
if (H5O_create(f, 4 + 2 * H5F_SIZEOF_ADDR(f), self /*out */ ) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create header");
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create header");
}
/*
* Insert the symbol table message into the object header and the symbol
* table entry.
*/
if (H5O_modify(self, H5O_STAB, H5O_NEW_MESG, H5O_FLAG_CONSTANT, &stab) < 0) {
H5O_close(self);
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message");
if (H5O_modify(self, H5O_STAB, H5O_NEW_MESG, H5O_FLAG_CONSTANT, &stab)<0) {
H5O_close(self);
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message");
}
self->cache.stab.btree_addr = stab.btree_addr;
self->cache.stab.heap_addr = stab.heap_addr;
@ -102,23 +104,24 @@ H5G_stab_create(H5F_t *f, size_t init, H5G_entry_t *self/*out*/)
FUNC_LEAVE(SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_stab_find
* Function: H5G_stab_find
*
* Purpose: Finds a symbol named NAME in the symbol table whose
* description is stored in GRP_ENT in file F and returns its
* symbol table entry through OBJ_ENT (which is optional).
* Purpose: Finds a symbol named NAME in the symbol table whose
* description is stored in GRP_ENT in file F and returns its
* symbol table entry through OBJ_ENT (which is optional).
*
* Errors:
*
* Return: Success: SUCCEED
* Return: Success: SUCCEED
*
* Failure: FAIL
* Failure: FAIL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
* Aug 1 1997
* Programmer: Robb Matzke
* matzke@llnl.gov
* Aug 1 1997
*
* Modifications:
*
@ -126,10 +129,10 @@ H5G_stab_create(H5F_t *f, size_t init, H5G_entry_t *self/*out*/)
*/
herr_t
H5G_stab_find(H5G_entry_t *grp_ent, const char *name,
H5G_entry_t *obj_ent /*out */ )
H5G_entry_t *obj_ent/*out*/)
{
H5G_bt_ud1_t udata; /*data to pass through B-tree */
H5O_stab_t stab; /*symbol table message */
H5G_bt_ud1_t udata; /*data to pass through B-tree */
H5O_stab_t stab; /*symbol table message */
FUNC_ENTER(H5G_stab_find, FAIL);
@ -140,7 +143,7 @@ H5G_stab_find(H5G_entry_t *grp_ent, const char *name,
/* set up the udata */
if (NULL == H5O_read(grp_ent, H5O_STAB, 0, &stab)) {
HRETURN_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't read message");
HRETURN_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't read message");
}
udata.operation = H5G_OPER_FIND;
udata.name = name;
@ -148,29 +151,28 @@ H5G_stab_find(H5G_entry_t *grp_ent, const char *name,
/* search the B-tree */
if (H5B_find(grp_ent->file, H5B_SNODE, &(stab.btree_addr), &udata) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found");
HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found");
}
if (obj_ent)
*obj_ent = udata.ent;
if (obj_ent) *obj_ent = udata.ent;
FUNC_LEAVE(SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5G_stab_insert
* Function: H5G_stab_insert
*
* Purpose: Insert a new symbol into the table described by GRP_ENT in
* file F. The name of the new symbol is NAME and its symbol
* table entry is OBJ_ENT.
* Purpose: Insert a new symbol into the table described by GRP_ENT in
* file F. The name of the new symbol is NAME and its symbol
* table entry is OBJ_ENT.
*
* Errors:
*
* Return: Success: SUCCEED
* Return: Success: SUCCEED
*
* Failure: FAIL
* Failure: FAIL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
* Aug 1 1997
* Programmer: Robb Matzke
* matzke@llnl.gov
* Aug 1 1997
*
* Modifications:
*
@ -179,8 +181,8 @@ H5G_stab_find(H5G_entry_t *grp_ent, const char *name,
herr_t
H5G_stab_insert(H5G_entry_t *grp_ent, const char *name, H5G_entry_t *obj_ent)
{
H5O_stab_t stab; /*symbol table message */
H5G_bt_ud1_t udata; /*data to pass through B-tree */
H5O_stab_t stab; /*symbol table message */
H5G_bt_ud1_t udata; /*data to pass through B-tree */
FUNC_ENTER(H5G_stab_insert, FAIL);
@ -192,7 +194,7 @@ H5G_stab_insert(H5G_entry_t *grp_ent, const char *name, H5G_entry_t *obj_ent)
/* initialize data to pass through B-tree */
if (NULL == H5O_read(grp_ent, H5O_STAB, 0, &stab)) {
HRETURN_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table");
HRETURN_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table");
}
udata.operation = H5G_OPER_INSERT;
udata.name = name;
@ -201,8 +203,9 @@ H5G_stab_insert(H5G_entry_t *grp_ent, const char *name, H5G_entry_t *obj_ent)
/* insert */
if (H5B_insert(grp_ent->file, H5B_SNODE, &(stab.btree_addr), &udata) < 0) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert entry");
HRETURN_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert entry");
}
/* update the name offset in the entry */
obj_ent->name_off = udata.ent.name_off;
FUNC_LEAVE(SUCCEED);

View File

@ -44,13 +44,22 @@ list (hid_t group, const char *name, void __unused__ *op_data)
hid_t (*func)(void*);
void *edata;
int i;
char linkval[512];
H5G_stat_t statbuf;
/* Disable error reporting */
H5Eget_auto (&func, &edata);
H5Eset_auto (NULL, NULL);
/* Print info about each name */
printf ("%-30s", name);
if (H5Gstat (group, name, TRUE, &statbuf)>=0) {
printf ("FILE={%lu,%lu}, OID={%lu,%lu} ",
statbuf.fileno[0], statbuf.fileno[1],
statbuf.objno[0], statbuf.objno[1]);
}
if ((obj=H5Dopen (group, name))>=0) {
hsize_t size[64];
hid_t space = H5Dget_space (obj);
@ -65,6 +74,11 @@ list (hid_t group, const char *name, void __unused__ *op_data)
} else if ((obj=H5Gopen (group, name))>=0) {
printf (" Group\n");
H5Gclose (obj);
} else if (H5Gget_linkval (group, name, sizeof(linkval), linkval)>=0) {
if (NULL==HDmemchr (linkval, 0, sizeof(linkval))) {
strcpy (linkval+sizeof(linkval)-4, "...");
}
printf (" -> %s\n", linkval);
} else {
printf (" Unknown Type\n");
}

View File

@ -3,7 +3,9 @@ testhdf5.o: \
testhdf5.h \
../src/H5private.h \
../src/H5public.h \
../src/H5config.h
../src/H5config.h \
../src/H5Eprivate.h \
../src/H5Epublic.h
tfile.o: \
tfile.c \
testhdf5.h \
@ -147,14 +149,13 @@ dtypes.o: \
../src/H5Iprivate.h \
../src/H5private.h \
../src/H5Tprivate.h \
../src/H5Gprivate.h
../src/H5Gprivate.h \
../src/H5Bprivate.h
hyperslab.o: \
hyperslab.c \
../src/H5private.h \
../src/H5public.h \
../src/H5config.h \
../src/H5MMprivate.h \
../src/H5MMpublic.h
../src/H5config.h
istore.o: \
istore.c \
../src/H5private.h \
@ -179,7 +180,8 @@ istore.o: \
../src/H5HGpublic.h \
../src/H5Tprivate.h \
../src/H5Tpublic.h \
../src/H5Sprivate.h
../src/H5Sprivate.h \
../src/H5Spublic.h
dsets.o: \
dsets.c \
../src/hdf5.h \
@ -218,8 +220,7 @@ cmpd_dset.o: \
../src/H5MMpublic.h \
../src/H5Opublic.h \
../src/H5Ppublic.h \
../src/H5Spublic.h \
../src/H5Tpublic.h
../src/H5Spublic.h
extend.o: \
extend.c \
../src/hdf5.h \
@ -332,4 +333,23 @@ big.o: \
../src/H5MMpublic.h \
../src/H5Opublic.h \
../src/H5Ppublic.h \
../src/H5Spublic.h
../src/H5Spublic.h \
../src/H5Tpublic.h
links.o: \
links.c \
../src/hdf5.h \
../src/H5public.h \
../src/H5config.h \
../src/H5ACpublic.h \
../src/H5Bpublic.h \
../src/H5Dpublic.h \
../src/H5Ipublic.h \
../src/H5Epublic.h \
../src/H5Fpublic.h \
../src/H5Gpublic.h \
../src/H5HGpublic.h \
../src/H5HLpublic.h \
../src/H5MFpublic.h \
../src/H5MMpublic.h \
../src/H5Opublic.h \
../src/H5Ppublic.h

View File

@ -12,9 +12,9 @@ CPPFLAGS=-I. -I../src @CPPFLAGS@
# These are our main targets. They should be listed in the order to be
# executed, generally most specific tests to least specific tests.
PROGS=testhdf5 gheap hyperslab istore dtypes dsets cmpd_dset extend external \
shtype iopipe big
shtype iopipe big links
TESTS=testhdf5 gheap hyperslab istore dtypes dsets cmpd_dset extend external \
shtype
shtype links
TIMINGS=iopipe
# Temporary files
@ -24,7 +24,7 @@ MOSTLYCLEAN=cmpd_dset.h5 dataset.h5 extend.h5 istore.h5 tfile1.h5 tfile2.h5 \
extern_2.raw extern_2b.raw extern_3.raw extern_3b.raw \
extern_4.raw extern_4b.raw iopipe.raw iopipe.h5 gheap0.h5 \
gheap1.h5 gheap2.h5 gheap3.h5 gheap4.h5 shtype0.h5 shtype1.h5 \
shtype2a.h5 shtype2b.h5 shtype3.h5
shtype2a.h5 shtype2b.h5 shtype3.h5 links.h5
# Source and object files for programs... The PROG_SRC list contains all the
# source files and is used for things like dependencies, archiving, etc. The
@ -32,7 +32,7 @@ MOSTLYCLEAN=cmpd_dset.h5 dataset.h5 extend.h5 istore.h5 tfile1.h5 tfile2.h5 \
# overlap with other tests.
PROG_SRC=testhdf5.c tfile.c theap.c tmeta.c tohdr.c tstab.c th5s.c dtypes.c \
hyperslab.c istore.c dsets.c cmpd_dset.c extend.c external.c \
iopipe.c gheap.c shtype.c big.c
iopipe.c gheap.c shtype.c big.c links.c
PROG_OBJ=$(PROG_SRC:.c=.o)
TESTHDF5_SRC=testhdf5.c tfile.c theap.c tmeta.c tohdr.c tstab.c th5s.c
@ -74,6 +74,9 @@ IOPIPE_OBJ=$(IOPIPE_SRC:.c=.o)
BIG_SRC=big.c
BIG_OBJ=$(BIG_SRC:.c=.o)
LINKS_SRC=links.c
LINKS_OBJ=$(LINKS_SRC:.c=.o)
# Private header files (not to be installed)...
PRIVATE_HDR=testhdf5.h
@ -127,4 +130,7 @@ grptime: $(GRPTIME_OBJ) ../src/libhdf5.a
big: $(BIG_OBJ) ../src/libhdf5.a
$(CC) $(CFLAGS) -o $@ $(BIG_OBJ) ../src/libhdf5.a $(LIBS)
links: $(LINKS_OBJ) ../src/libhdf5.a
$(CC) $(CFLAGS) -o $@ $(LINKS_OBJ) ../src/libhdf5.a $(LIBS)
@CONCLUDE@

View File

@ -6,7 +6,26 @@
* Wednesday, April 8, 1998
*/
#include <assert.h>
#include <ctype.h>
#include <hdf5.h>
#include <math.h>
#include <stdlib.h>
#include <H5private.h> /*needed for HDfprintf() */
#define FNAME "big%05d.h5"
#define WRT_N 50
#define WRT_SIZE 4*1024
static hsize_t
randll (hsize_t limit)
{
hsize_t acc = rand ();
acc *= rand ();
return acc % limit;
}
/*-------------------------------------------------------------------------
@ -25,12 +44,16 @@
*
*-------------------------------------------------------------------------
*/
int
main (void)
static void
writer (int wrt_n)
{
hsize_t size1[4] = {8, 1024, 1024, 1024};
hsize_t size2[1] = {8589934592LL};
hid_t plist, file, space1, space2, dset;
hssize_t hs_start[1];
hsize_t hs_size[1];
hid_t plist, file, space1, space2, mem_space, d1, d2;
int *buf = malloc (sizeof(int) * WRT_SIZE);
int i, j;
/*
* Make sure that `hsize_t' is large enough to represent the entire data
@ -44,20 +67,137 @@ main (void)
*/
plist = H5Pcreate (H5P_FILE_ACCESS);
H5Pset_family (plist, 30, H5P_DEFAULT);
file = H5Fcreate ("big%05d.h5", H5F_ACC_TRUNC, H5P_DEFAULT, plist);
file = H5Fcreate (FNAME, H5F_ACC_TRUNC, H5P_DEFAULT, plist);
/* Create simple data spaces according to the size specified above. */
space1 = H5Screate_simple (4, size1, size1);
space2 = H5Screate_simple (1, size2, size2);
/* Create the datasets */
dset = H5Dcreate (file, "d1", H5T_NATIVE_INT, space1, H5P_DEFAULT);
H5Dclose (dset);
dset = H5Dcreate (file, "d2", H5T_NATIVE_INT, space2, H5P_DEFAULT);
H5Dclose (dset);
d1 = H5Dcreate (file, "d1", H5T_NATIVE_INT, space1, H5P_DEFAULT);
d2 = H5Dcreate (file, "d2", H5T_NATIVE_INT, space2, H5P_DEFAULT);
/* Write some things to them randomly */
hs_size[0] = WRT_SIZE;
mem_space = H5Screate_simple (1, hs_size, hs_size);
for (i=0; i<wrt_n; i++) {
hs_start[0] = randll (size2[0]);
HDfprintf (stdout, "#%03d 0x%016Hx\n", i, hs_start[0]);
H5Sset_hyperslab (space2, hs_start, hs_size, NULL);
for (j=0; j<WRT_SIZE; j++) {
buf[j] = i+1;
}
H5Dwrite (d2, H5T_NATIVE_INT, mem_space, space2, H5P_DEFAULT, buf);
}
H5Dclose (d1);
H5Dclose (d2);
H5Sclose (mem_space);
H5Sclose (space1);
H5Sclose (space2);
H5Fclose (file);
exit (0);
free (buf);
}
/*-------------------------------------------------------------------------
* Function: reader
*
* Purpose: Reads some data from random locations in the dataset.
*
* Return: void
*
* Programmer: Robb Matzke
* Friday, April 10, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static void
reader (const char *script_name)
{
FILE *script;
hid_t plist, file, mspace, fspace, d2;
char ln[64], *s;
hssize_t hs_offset[1];
hsize_t hs_size[1] = {WRT_SIZE};
int *buf = malloc (sizeof(int) * WRT_SIZE);
int i, j, zero, wrong;
/* Open script file */
script = fopen (script_name, "r");
/* Open HDF5 file */
plist = H5Pcreate (H5P_FILE_ACCESS);
H5Pset_family (plist, 30, H5P_DEFAULT);
file = H5Fopen (FNAME, H5F_ACC_RDONLY, plist);
/* Open the dataset */
d2 = H5Dopen (file, "d2");
fspace = H5Dget_space (d2);
/* Describe `buf' */
mspace = H5Screate_simple (1, hs_size, hs_size);
/* Read each region */
while (fgets (ln, sizeof(ln), script)) {
if ('#'!=ln[0]) break;
i = strtol (ln+1, &s, 10);
hs_offset[0] = HDstrtoll (s, NULL, 0);
HDfprintf (stdout, "#%03d 0x%016Hx", i, hs_offset[0]);
fflush (stdout);
H5Sset_hyperslab (fspace, hs_offset, hs_size, NULL);
H5Dread (d2, H5T_NATIVE_INT, mspace, fspace, H5P_DEFAULT, buf);
/* Check */
for (j=zero=wrong=0; j<WRT_SIZE; j++) {
if (0==buf[j]) zero++;
else if (buf[j]!=i+1) wrong++;
}
if (zero) {
printf (" *FAILED* (%d zeros)\n", zero);
} else if (wrong) {
printf (" *SKIPPED* (possible overlap with another region)\n");
} else {
printf (" PASSED\n");
}
}
H5Dclose (d2);
H5Sclose (mspace);
H5Sclose (fspace);
H5Fclose (file);
fclose (script);
}
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose:
*
* Return: Success:
*
* Failure:
*
* Programmer: Robb Matzke
* Friday, April 10, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
int
main (int argc, char *argv[])
{
if (1==argc) {
writer (WRT_N);
} else if (isdigit (argv[1][0])) {
writer (strtol (argv[1], NULL, 0));
} else {
reader (argv[1]);
}
return 0;
}

63
test/links.c Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 1998 NCSA
* All rights reserved.
*
* Programmer: Robb Matzke <matzke@llnl.gov>
* Friday, April 10, 1998
*
* Purpose: Tests hard and soft (symbolic) links.
*/
#include <hdf5.h>
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Tests links.
*
* Return: Success: 0
*
* Failure: non-zero
*
* Programmer: Robb Matzke
* Friday, April 10, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
int
main (void)
{
hid_t file, scalar, grp, d1;
hsize_t size[1] = {1};
/* Create a file */
file = H5Fcreate ("links.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
scalar = H5Screate_simple (1, size, size);
/* Create a group */
grp = H5Gcreate (file, "grp1", 0);
H5Gclose (grp);
/* Create a dataset */
d1 = H5Dcreate (file, "d1", H5T_NATIVE_INT, scalar, H5P_DEFAULT);
H5Dclose (d1);
/* Create a hard link */
H5Glink (file, H5G_LINK_HARD, "d1", "grp1/hard");
/* Create a symbolic link */
H5Glink (file, H5G_LINK_SOFT, "/d1", "grp1/soft");
/* Create a symbolic link to something that doesn't exist */
H5Glink (file, H5G_LINK_SOFT, "foobar", "grp1/dangle");
/* Create a recursive symbolic link */
H5Glink (file, H5G_LINK_SOFT, "/grp1/recursive", "/grp1/recursive");
/* Close */
H5Sclose (scalar);
H5Fclose (file);
return 0;
}