diff options
author | James Laird <jlaird@hdfgroup.org> | 2006-08-02 23:41:53 (GMT) |
---|---|---|
committer | James Laird <jlaird@hdfgroup.org> | 2006-08-02 23:41:53 (GMT) |
commit | 3e755623cb24eb37c19fa645d74dc46948318253 (patch) | |
tree | 66e0a3807f37d50a8d6e5f3469864c604cd837c6 /test | |
parent | 71a4d0e9c48c4e02e5384cd3f6e38a2a530e9d22 (diff) | |
download | hdf5-3e755623cb24eb37c19fa645d74dc46948318253.zip hdf5-3e755623cb24eb37c19fa645d74dc46948318253.tar.gz hdf5-3e755623cb24eb37c19fa645d74dc46948318253.tar.bz2 |
[svn-r12528] Added User-Defined links to the library.
Users can create external links using H5L_create_external(). These links
point to an object in another HDF5 file. Users can alter the behavior of
external links or create new kinds of links by registering callbacks
using the H5L interface.
Added tests, tools support, etc.
Also a number of other, minor changes have been made (some restructuring of
the H5L interface, for instance).
Additional documentation and examples are forthcoming.
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile.am | 14 | ||||
-rw-r--r-- | test/Makefile.in | 73 | ||||
-rw-r--r-- | test/be_extlink1.h5 | bin | 0 -> 1120 bytes | |||
-rw-r--r-- | test/be_extlink2.h5 | bin | 0 -> 2840 bytes | |||
-rw-r--r-- | test/gen_udlinks.c | 81 | ||||
-rw-r--r-- | test/le_extlink1.h5 | bin | 0 -> 1120 bytes | |||
-rw-r--r-- | test/le_extlink2.h5 | bin | 0 -> 2840 bytes | |||
-rw-r--r-- | test/links.c | 3571 | ||||
-rw-r--r-- | test/mount.c | 24 | ||||
-rwxr-xr-x | test/objcopy.c | 195 | ||||
-rw-r--r-- | test/stab.c | 6 | ||||
-rw-r--r-- | test/testhdf5.c | 1 | ||||
-rw-r--r-- | test/testhdf5.h | 2 | ||||
-rw-r--r-- | test/th5o.c | 601 | ||||
-rw-r--r-- | test/titerate.c | 4 | ||||
-rw-r--r-- | test/tmisc.c | 50 | ||||
-rw-r--r-- | test/unlink.c | 322 |
17 files changed, 4682 insertions, 262 deletions
diff --git a/test/Makefile.am b/test/Makefile.am index afadd52..4e7818b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -58,16 +58,14 @@ check_PROGRAMS=$(TEST_PROG) error_test err_compat testmeta # --enable-build-all at configure time. # The gen_old_* files can only be compiled with older versions of the library # so do not appear in this list. +BUILD_ALL_PROGS=gen_deflate gen_filters gen_new_array gen_new_fill \ + gen_new_group gen_new_mtime gen_new_super gen_noencoder \ + gen_nullspace space_overflow gen_cross gen_udlinks + if BUILD_ALL_CONDITIONAL - BUILD_ALL_PROGS=gen_deflate gen_filters gen_new_array gen_new_fill \ - gen_new_group gen_new_mtime gen_new_super gen_noencoder \ - gen_nullspace space_overflow gen_cross -else - BUILD_ALL_PROGS= + noinst_PROGRAMS=$(BUILD_ALL_PROGS) endif -noinst_PROGRAMS=$(BUILD_ALL_PROGS) - # The libh5test library provides common support code for the tests. noinst_LTLIBRARIES=libh5test.la libh5test_la_SOURCES=h5test.c testframe.c cache_common.c @@ -118,7 +116,7 @@ CHECK_CLEANFILES+=cmpd_dset.h5 compact_dataset.h5 dataset.h5 extend.h5 istore.h5 # Sources for testhdf5 executable testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tconfig.c tfile.c tgenprop.c \ - th5s.c theap.c tid.c titerate.c tmeta.c tmisc.c ttime.c trefer.c trefstr.c \ + th5o.c th5s.c theap.c tid.c titerate.c tmeta.c tmisc.c ttime.c trefer.c trefstr.c \ tselect.c tskiplist.c ttst.c tunicode.c tvltypes.c tvlstr.c include $(top_srcdir)/config/conclude.am diff --git a/test/Makefile.in b/test/Makefile.in index 5339b48..7934415 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -31,7 +31,7 @@ # -SOURCES = $(libh5test_la_SOURCES) big.c bittests.c btree2.c cache.c cache_api.c cmpd_dset.c cross_read.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c enum.c err_compat.c error_test.c extend.c external.c fheap.c fillval.c flush1.c flush2.c gen_cross.c gen_deflate.c gen_filters.c gen_new_array.c gen_new_fill.c gen_new_group.c gen_new_mtime.c gen_new_super.c gen_noencoder.c gen_nullspace.c getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c mtime.c ntypes.c objcopy.c ohdr.c pool.c reserved.c set_extent.c space_overflow.c stab.c stream_test.c $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c +SOURCES = $(libh5test_la_SOURCES) big.c bittests.c btree2.c cache.c cache_api.c cmpd_dset.c cross_read.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c enum.c err_compat.c error_test.c extend.c external.c fheap.c fillval.c flush1.c flush2.c gen_cross.c gen_deflate.c gen_filters.c gen_new_array.c gen_new_fill.c gen_new_group.c gen_new_mtime.c gen_new_super.c gen_noencoder.c gen_nullspace.c gen_udlinks.c getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c mtime.c ntypes.c objcopy.c ohdr.c pool.c reserved.c set_extent.c space_overflow.c stab.c stream_test.c $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -60,7 +60,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/config/conclude.am check_PROGRAMS = $(am__EXEEXT_1) error_test$(EXEEXT) \ err_compat$(EXEEXT) testmeta$(EXEEXT) -noinst_PROGRAMS = $(am__EXEEXT_2) +@BUILD_ALL_CONDITIONAL_TRUE@noinst_PROGRAMS = $(am__EXEEXT_2) subdir = test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in @@ -85,17 +85,12 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \ getname$(EXEEXT) vfd$(EXEEXT) ntypes$(EXEEXT) dangle$(EXEEXT) \ dtransform$(EXEEXT) reserved$(EXEEXT) cross_read$(EXEEXT) \ fheap$(EXEEXT) btree2$(EXEEXT) -@BUILD_ALL_CONDITIONAL_TRUE@am__EXEEXT_2 = gen_deflate$(EXEEXT) \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_filters$(EXEEXT) \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_new_array$(EXEEXT) \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_new_fill$(EXEEXT) \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_new_group$(EXEEXT) \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_new_mtime$(EXEEXT) \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_new_super$(EXEEXT) \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_noencoder$(EXEEXT) \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_nullspace$(EXEEXT) \ -@BUILD_ALL_CONDITIONAL_TRUE@ space_overflow$(EXEEXT) \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_cross$(EXEEXT) +am__EXEEXT_2 = gen_deflate$(EXEEXT) gen_filters$(EXEEXT) \ + gen_new_array$(EXEEXT) gen_new_fill$(EXEEXT) \ + gen_new_group$(EXEEXT) gen_new_mtime$(EXEEXT) \ + gen_new_super$(EXEEXT) gen_noencoder$(EXEEXT) \ + gen_nullspace$(EXEEXT) space_overflow$(EXEEXT) \ + gen_cross$(EXEEXT) gen_udlinks$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) big_SOURCES = big.c big_OBJECTS = big.$(OBJEXT) @@ -222,6 +217,10 @@ gen_nullspace_SOURCES = gen_nullspace.c gen_nullspace_OBJECTS = gen_nullspace.$(OBJEXT) gen_nullspace_LDADD = $(LDADD) gen_nullspace_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1) +gen_udlinks_SOURCES = gen_udlinks.c +gen_udlinks_OBJECTS = gen_udlinks.$(OBJEXT) +gen_udlinks_LDADD = $(LDADD) +gen_udlinks_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1) getname_SOURCES = getname.c getname_OBJECTS = getname.$(OBJEXT) getname_LDADD = $(LDADD) @@ -292,12 +291,12 @@ stream_test_LDADD = $(LDADD) stream_test_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1) am_testhdf5_OBJECTS = testhdf5.$(OBJEXT) tarray.$(OBJEXT) \ tattr.$(OBJEXT) tconfig.$(OBJEXT) tfile.$(OBJEXT) \ - tgenprop.$(OBJEXT) th5s.$(OBJEXT) theap.$(OBJEXT) \ - tid.$(OBJEXT) titerate.$(OBJEXT) tmeta.$(OBJEXT) \ - tmisc.$(OBJEXT) ttime.$(OBJEXT) trefer.$(OBJEXT) \ - trefstr.$(OBJEXT) tselect.$(OBJEXT) tskiplist.$(OBJEXT) \ - ttst.$(OBJEXT) tunicode.$(OBJEXT) tvltypes.$(OBJEXT) \ - tvlstr.$(OBJEXT) + tgenprop.$(OBJEXT) th5o.$(OBJEXT) th5s.$(OBJEXT) \ + theap.$(OBJEXT) tid.$(OBJEXT) titerate.$(OBJEXT) \ + tmeta.$(OBJEXT) tmisc.$(OBJEXT) ttime.$(OBJEXT) \ + trefer.$(OBJEXT) trefstr.$(OBJEXT) tselect.$(OBJEXT) \ + tskiplist.$(OBJEXT) ttst.$(OBJEXT) tunicode.$(OBJEXT) \ + tvltypes.$(OBJEXT) tvlstr.$(OBJEXT) testhdf5_OBJECTS = $(am_testhdf5_OBJECTS) testhdf5_LDADD = $(LDADD) testhdf5_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1) @@ -336,22 +335,24 @@ SOURCES = $(libh5test_la_SOURCES) big.c bittests.c btree2.c cache.c \ error_test.c extend.c external.c fheap.c fillval.c flush1.c \ flush2.c gen_cross.c gen_deflate.c gen_filters.c \ gen_new_array.c gen_new_fill.c gen_new_group.c gen_new_mtime.c \ - gen_new_super.c gen_noencoder.c gen_nullspace.c getname.c \ - gheap.c hyperslab.c istore.c lheap.c links.c mount.c mtime.c \ - ntypes.c objcopy.c ohdr.c pool.c reserved.c set_extent.c \ - space_overflow.c stab.c stream_test.c $(testhdf5_SOURCES) \ - testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c + gen_new_super.c gen_noencoder.c gen_nullspace.c gen_udlinks.c \ + getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c \ + mtime.c ntypes.c objcopy.c ohdr.c pool.c reserved.c \ + set_extent.c space_overflow.c stab.c stream_test.c \ + $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ + vfd.c DIST_SOURCES = $(libh5test_la_SOURCES) big.c bittests.c btree2.c \ cache.c cache_api.c cmpd_dset.c cross_read.c dangle.c dsets.c \ dt_arith.c dtransform.c dtypes.c enum.c err_compat.c \ error_test.c extend.c external.c fheap.c fillval.c flush1.c \ flush2.c gen_cross.c gen_deflate.c gen_filters.c \ gen_new_array.c gen_new_fill.c gen_new_group.c gen_new_mtime.c \ - gen_new_super.c gen_noencoder.c gen_nullspace.c getname.c \ - gheap.c hyperslab.c istore.c lheap.c links.c mount.c mtime.c \ - ntypes.c objcopy.c ohdr.c pool.c reserved.c set_extent.c \ - space_overflow.c stab.c stream_test.c $(testhdf5_SOURCES) \ - testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c + gen_new_super.c gen_noencoder.c gen_nullspace.c gen_udlinks.c \ + getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c \ + mtime.c ntypes.c objcopy.c ohdr.c pool.c reserved.c \ + set_extent.c space_overflow.c stab.c stream_test.c \ + $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ + vfd.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -629,7 +630,6 @@ TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api \ getname vfd ntypes dangle dtransform reserved cross_read \ fheap btree2 -@BUILD_ALL_CONDITIONAL_FALSE@BUILD_ALL_PROGS = # These programs generate test files for the tests. They don't need to be # compiled every time we want to test the library. However, putting @@ -638,9 +638,9 @@ TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api \ # --enable-build-all at configure time. # The gen_old_* files can only be compiled with older versions of the library # so do not appear in this list. -@BUILD_ALL_CONDITIONAL_TRUE@BUILD_ALL_PROGS = gen_deflate gen_filters gen_new_array gen_new_fill \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_new_group gen_new_mtime gen_new_super gen_noencoder \ -@BUILD_ALL_CONDITIONAL_TRUE@ gen_nullspace space_overflow gen_cross +BUILD_ALL_PROGS = gen_deflate gen_filters gen_new_array gen_new_fill \ + gen_new_group gen_new_mtime gen_new_super gen_noencoder \ + gen_nullspace space_overflow gen_cross gen_udlinks # The libh5test library provides common support code for the tests. @@ -658,7 +658,7 @@ VFD_LIST = sec2 stdio core split multi family # Sources for testhdf5 executable testhdf5_SOURCES = testhdf5.c tarray.c tattr.c tconfig.c tfile.c tgenprop.c \ - th5s.c theap.c tid.c titerate.c tmeta.c tmisc.c ttime.c trefer.c trefstr.c \ + th5o.c th5s.c theap.c tid.c titerate.c tmeta.c tmisc.c ttime.c trefer.c trefstr.c \ tselect.c tskiplist.c ttst.c tunicode.c tvltypes.c tvlstr.c @@ -829,6 +829,9 @@ gen_noencoder$(EXEEXT): $(gen_noencoder_OBJECTS) $(gen_noencoder_DEPENDENCIES) gen_nullspace$(EXEEXT): $(gen_nullspace_OBJECTS) $(gen_nullspace_DEPENDENCIES) @rm -f gen_nullspace$(EXEEXT) $(LINK) $(gen_nullspace_LDFLAGS) $(gen_nullspace_OBJECTS) $(gen_nullspace_LDADD) $(LIBS) +gen_udlinks$(EXEEXT): $(gen_udlinks_OBJECTS) $(gen_udlinks_DEPENDENCIES) + @rm -f gen_udlinks$(EXEEXT) + $(LINK) $(gen_udlinks_LDFLAGS) $(gen_udlinks_OBJECTS) $(gen_udlinks_LDADD) $(LIBS) getname$(EXEEXT): $(getname_OBJECTS) $(getname_DEPENDENCIES) @rm -f getname$(EXEEXT) $(LINK) $(getname_LDFLAGS) $(getname_OBJECTS) $(getname_LDADD) $(LIBS) @@ -934,6 +937,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_new_super.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_noencoder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_nullspace.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_udlinks.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getname.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gheap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h5test.Plo@am__quote@ @@ -960,6 +964,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testmeta.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tgenprop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/th5o.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/th5s.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/theap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tid.Po@am__quote@ diff --git a/test/be_extlink1.h5 b/test/be_extlink1.h5 Binary files differnew file mode 100644 index 0000000..dedd0a5 --- /dev/null +++ b/test/be_extlink1.h5 diff --git a/test/be_extlink2.h5 b/test/be_extlink2.h5 Binary files differnew file mode 100644 index 0000000..d6f9921 --- /dev/null +++ b/test/be_extlink2.h5 diff --git a/test/gen_udlinks.c b/test/gen_udlinks.c new file mode 100644 index 0000000..1230ffe --- /dev/null +++ b/test/gen_udlinks.c @@ -0,0 +1,81 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: James Laird <jlaird@hdfgroup.org> + * Tuesday, June 6, 2006 + * + * This program creates HDF5 files with user-defined links. These files + * should be created on a little-endian and a big-endian machine. + * They will be named according to the platform and should + * be placed in the hdf5/test directory so that the links test can use them. + */ + +#include "hdf5.h" +#include <string.h> + +#define NAME_LE_1 "le_extlink1.h5" +#define NAME_LE_2 "le_extlink2.h5" +#define NAME_BE_1 "be_extlink1.h5" +#define NAME_BE_2 "be_extlink2.h5" +#define NAME_BUF_SIZE 25 + +int +main (void) +{ + hid_t fid1=-1; + hid_t fid2=-1; + hid_t gid=-1; + char filename1[NAME_BUF_SIZE]; + char filename2[NAME_BUF_SIZE]; + + /* Name the files differently depending on the endianness of this platform */ + + switch(H5Tget_order(H5T_NATIVE_INT)) + { + case H5T_ORDER_LE: + strcpy(filename1, NAME_LE_1); + strcpy(filename2, NAME_LE_2); + break; + case H5T_ORDER_BE: + strcpy(filename1, NAME_BE_1); + strcpy(filename2, NAME_BE_2); + break; + default: + goto error; + } + + /* Create the two files */ + if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) goto error; + if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) goto error; + + /* Create two groups in the second file */ + if((gid = H5Gcreate(fid2, "group", 0)) < 0) goto error; + if((H5Gclose(gid)) < 0) goto error; + if((gid = H5Gcreate(fid2, "group/subgroup", 0)) < 0) goto error; + if((H5Gclose(gid)) < 0) goto error; + + /* Create an external link in the first file pointing to the group in the second file */ + if(H5Lcreate_external(filename2, "group", fid1, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) goto error; + + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(fid1); + H5Fclose(fid2); + H5Gclose(gid); + } H5E_END_TRY + return 1; +} diff --git a/test/le_extlink1.h5 b/test/le_extlink1.h5 Binary files differnew file mode 100644 index 0000000..877ba37 --- /dev/null +++ b/test/le_extlink1.h5 diff --git a/test/le_extlink2.h5 b/test/le_extlink2.h5 Binary files differnew file mode 100644 index 0000000..d6f9921 --- /dev/null +++ b/test/le_extlink2.h5 diff --git a/test/links.c b/test/links.c index 0e4f680..92f4984 100644 --- a/test/links.c +++ b/test/links.c @@ -16,34 +16,23 @@ * Programmer: Robb Matzke <matzke@llnl.gov> * Friday, April 10, 1998 * - * Purpose: Tests hard and soft (symbolic) links. + * Purpose: Tests hard, soft (symbolic) & external links. */ -#define H5G_PACKAGE /*suppress error about including H5Gpkg */ - -/* Define this macro to indicate that the testing APIs should be available */ -#define H5G_TESTING +#include "H5Lprivate.h" #include "h5test.h" -#include "H5Gpkg.h" /* Groups */ const char *FILENAME[] = { "links0", "links1", "links2", "links3", - "links4", + "links4a", + "links4b", + "links4c", + "links4d", "links5", - "links6", - "links7", - "links8", - "links9", - "links10", - "links11", - "links12", - "links13", - "links14", - "links15", NULL }; @@ -51,6 +40,27 @@ const char *FILENAME[] = { #define NAME_BUF_SIZE 1024 #define MAX_NAME_LEN ((64*1024)+1024) +/* Link type IDs */ +#define UD_HARD_TYPE 201 +#define UD_CB_TYPE H5L_LINK_MAX +#define UD_PLIST_TYPE 128 +#define UD_CBFAIL_TYPE UD_PLIST_TYPE +#define UD_ERROR_TYPE 189 +#define UD_BAD_TYPE1 H5G_LINK_HARD +#define UD_BAD_TYPE2 (H5L_LINK_UD_MIN - 5) +#define UD_BAD_VERS (H5L_LINK_CLASS_T_VERS + 1) + +#define DEST_PROP_NAME "destination_group" +#define REREG_TARGET_NAME "rereg_target" + +#define UD_CB_LINK_NAME "ud_callback_link" +#define NEW_UD_CB_LINK_NAME "ud_callback_link2" +#define UD_CB_TARGET "ud_target" +#define UD_CB_TARGET_LEN 10 + +#define LE_FILENAME "le_extlink1.h5" +#define BE_FILENAME "be_extlink1.h5" + #define H5L_DIM1 100 #define H5L_DIM2 100 @@ -94,16 +104,16 @@ mklinks(hid_t fapl) if (H5Dclose (d1)<0) TEST_ERROR; /* Create a hard link */ - if (H5Lcreate_hard (file, "d1", H5L_SAME_LOC, "grp1/hard", H5P_DEFAULT)<0) TEST_ERROR; + if (H5Lcreate_hard (file, "d1", H5L_SAME_LOC, "grp1/hard", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Create a symbolic link */ - if (H5Lcreate_soft ("/d1", file, "grp1/soft", H5P_DEFAULT)<0) TEST_ERROR; + if (H5Lcreate_soft ("/d1", file, "grp1/soft", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Create a symbolic link to something that doesn't exist */ - if (H5Lcreate_soft ("foobar", file, "grp1/dangle", H5P_DEFAULT)<0) TEST_ERROR; + if (H5Lcreate_soft ("foobar", file, "grp1/dangle", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Create a recursive symbolic link */ - if (H5Lcreate_soft ("/grp1/recursive", file, "/grp1/recursive", H5P_DEFAULT)<0) TEST_ERROR; + if (H5Lcreate_soft ("/grp1/recursive", file, "/grp1/recursive", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Close */ if (H5Sclose (scalar)<0) TEST_ERROR; @@ -167,22 +177,22 @@ new_links(hid_t fapl) /* Create links within a file. Both of source and destination use * H5L_SAME_LOC. Both hard and soft links should fail. */ H5E_BEGIN_TRY { - if(H5Lcreate_hard(H5L_SAME_LOC, "dataset1", H5L_SAME_LOC, "hard", H5P_DEFAULT)!=FAIL) TEST_ERROR; + if(H5Lcreate_hard(H5L_SAME_LOC, "dataset1", H5L_SAME_LOC, "hard", H5P_DEFAULT, H5P_DEFAULT)!=FAIL) TEST_ERROR; } H5E_END_TRY; H5E_BEGIN_TRY { - if(H5Lcreate_soft("dataset1", H5L_SAME_LOC, "soft", H5P_DEFAULT)!=FAIL) TEST_ERROR; + if(H5Lcreate_soft("dataset1", H5L_SAME_LOC, "soft", H5P_DEFAULT, H5P_DEFAULT)!=FAIL) TEST_ERROR; } H5E_END_TRY; /* Create links across files with hard link. Should fail. */ H5E_BEGIN_TRY { - if(H5Lcreate_hard(file_a, "dataset1", file_b, "hard", H5P_DEFAULT)!=FAIL) TEST_ERROR; + if(H5Lcreate_hard(file_a, "dataset1", file_b, "hard", H5P_DEFAULT, H5P_DEFAULT)!=FAIL) TEST_ERROR; } H5E_END_TRY; /* Create hard link to test H5L_SAME_LOC */ - if(H5Lcreate_hard(grp1_a, "dataset2", H5L_SAME_LOC, "hard1", H5P_DEFAULT)<0) TEST_ERROR; + if(H5Lcreate_hard(grp1_a, "dataset2", H5L_SAME_LOC, "hard1", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Create links to test hard links across different locations */ - if(H5Lcreate_hard(grp1_a, "dataset2", grp2_a, "hard2", H5P_DEFAULT)<0) TEST_ERROR; + if(H5Lcreate_hard(grp1_a, "dataset2", grp2_a, "hard2", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Close dataspace and files */ if (H5Sclose (scalar)<0) TEST_ERROR; @@ -274,7 +284,7 @@ cklinks(hid_t fapl) puts(" expected file location."); TEST_ERROR; } - if (H5Gget_linkval(file, "grp1/soft", sizeof linkval, linkval)<0) TEST_ERROR; + if (H5Lget_linkval(file, "grp1/soft", sizeof linkval, linkval, H5P_DEFAULT)<0) TEST_ERROR; if (HDstrcmp(linkval, "/d1")) { H5_FAILED(); puts(" Soft link test failed. Wrong link value"); @@ -431,7 +441,7 @@ long_links(hid_t fapl) TESTING("long names for objects & links"); /* Create files */ - h5_fixname(FILENAME[13], fapl, filename, sizeof filename); + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; /* Create group with short name in file (used as target for hard links) */ @@ -444,11 +454,11 @@ long_links(hid_t fapl) objname[MAX_NAME_LEN] = '\0'; /* Create hard link to existing object */ - if(H5Lcreate_hard(fid, "grp1", fid, objname, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "grp1", fid, objname, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; /* Create soft link to existing object */ objname[0] = 'b'; - if(H5Lcreate_soft("grp1", fid, objname, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("grp1", fid, objname, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; /* Create group with long name in existing group */ if((gid2=H5Gcreate(gid, objname, (size_t)0))<0) TEST_ERROR; @@ -495,8 +505,7 @@ static int toomany(hid_t fapl) { hid_t fid = (-1); /* File ID */ - hid_t gid = (-1); /* Group ID */ - hid_t gid2 = (-1); /* Datatype ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ char objname[NAME_BUF_SIZE]; /* Object name */ ssize_t name_len; /* Length of object name */ char filename[NAME_BUF_SIZE]; @@ -509,54 +518,54 @@ toomany(hid_t fapl) */ HDassert(H5G_NLINKS == 16); - /* Create files */ - h5_fixname(FILENAME[14], fapl, filename, sizeof filename); + /* Create file */ + h5_fixname(FILENAME[1], fapl, filename, sizeof filename); if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; /* Create group with short name in file (used as target for hard links) */ if((gid=H5Gcreate (fid, "final", (size_t)0))<0) TEST_ERROR; /* Create chain of hard links to existing object (no limit on #) */ - if(H5Lcreate_hard(fid, "final", fid, "hard1", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard1", fid, "hard2", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard2", fid, "hard3", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard3", fid, "hard4", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard4", fid, "hard5", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard5", fid, "hard6", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard6", fid, "hard7", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard7", fid, "hard8", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard8", fid, "hard9", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard9", fid, "hard10", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard10", fid, "hard11", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard11", fid, "hard12", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard12", fid, "hard13", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard13", fid, "hard14", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard14", fid, "hard15", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard15", fid, "hard16", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard16", fid, "hard17", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard17", fid, "hard18", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard18", fid, "hard19", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard19", fid, "hard20", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_hard(fid, "hard20", fid, "hard21", H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "final", fid, "hard1", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard1", fid, "hard2", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard2", fid, "hard3", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard3", fid, "hard4", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard4", fid, "hard5", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard5", fid, "hard6", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard6", fid, "hard7", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard7", fid, "hard8", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard8", fid, "hard9", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard9", fid, "hard10", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard10", fid, "hard11", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard11", fid, "hard12", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard12", fid, "hard13", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard13", fid, "hard14", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard14", fid, "hard15", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard15", fid, "hard16", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard16", fid, "hard17", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard17", fid, "hard18", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard18", fid, "hard19", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard19", fid, "hard20", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(fid, "hard20", fid, "hard21", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; /* Create chain of soft links to existing object (limited) */ - if(H5Lcreate_soft("final", fid, "soft1", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft1", fid, "soft2", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft2", fid, "soft3", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft3", fid, "soft4", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft4", fid, "soft5", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft5", fid, "soft6", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft6", fid, "soft7", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft7", fid, "soft8", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft8", fid, "soft9", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft9", fid, "soft10", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft10", fid, "soft11", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft11", fid, "soft12", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft12", fid, "soft13", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft13", fid, "soft14", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft14", fid, "soft15", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft15", fid, "soft16", H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Lcreate_soft("soft16", fid, "soft17", H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("final", fid, "soft1", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft1", fid, "soft2", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft2", fid, "soft3", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft3", fid, "soft4", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft4", fid, "soft5", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft5", fid, "soft6", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft6", fid, "soft7", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft7", fid, "soft8", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft8", fid, "soft9", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft9", fid, "soft10", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft10", fid, "soft11", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft11", fid, "soft12", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft12", fid, "soft13", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft13", fid, "soft14", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft14", fid, "soft15", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft15", fid, "soft16", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_soft("soft16", fid, "soft17", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; /* Close objects */ if(H5Gclose(gid)<0) TEST_ERROR; @@ -598,16 +607,14 @@ toomany(hid_t fapl) if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR if(HDstrcmp(objname, "/soft16")) TEST_ERROR - /* Create object in external file */ + /* Create object using soft links */ if((gid2 = H5Gcreate(gid, "new_soft", (size_t)0)) < 0) TEST_ERROR - /* Close group in external file */ + /* Close groups */ if(H5Gclose(gid2) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR - /* Close external object */ - if(H5Gclose(gid) < 0) TEST_ERROR; - - /* Close first file */ + /* Close file */ if(H5Fclose(fid)<0) TEST_ERROR; PASSED(); @@ -642,7 +649,6 @@ toomany(hid_t fapl) static int test_h5l_create(hid_t fapl) { - hid_t fapl_id=-1; hid_t file_id=-1; hid_t group_id=-1; hid_t space_id=-1; @@ -654,13 +660,12 @@ test_h5l_create(hid_t fapl) int i, n, j; int wdata[H5L_DIM1][H5L_DIM2]; int rdata[H5L_DIM1][H5L_DIM2]; - TESTING("H5Lcreate"); + TESTING("H5Llink"); /* Create file */ - fapl_id = h5_fileaccess(); - h5_fixname(FILENAME[3], fapl_id, filename, sizeof filename); + h5_fixname(FILENAME[3], fapl, filename, sizeof filename); - if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id))<0) TEST_ERROR; + if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; /* Create and commit a datatype with no name */ if((type_id =H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR; @@ -672,7 +677,7 @@ test_h5l_create(hid_t fapl) dims[1] = H5L_DIM2; if((space_id=H5Screate_simple(2 ,dims, NULL))<0) TEST_ERROR; /* Create a dataset with no name using the committed datatype*/ - if ((dset_id = H5Dcreate_expand(file_id, type_id, space_id, H5P_DEFAULT)) <0) TEST_ERROR; + if ((dset_id = H5Dcreate_expand(file_id, type_id, space_id, H5P_DEFAULT, H5P_DEFAULT)) <0) TEST_ERROR; /* Verify that we can write to and read from the dataset */ /* Initialize the dataset */ @@ -699,14 +704,14 @@ test_h5l_create(hid_t fapl) if((group_id = H5Gcreate_expand(file_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR; /* Link nameless datatype into nameless group */ - if(H5Llink(group_id, "datatype", type_id, H5P_DEFAULT)<0) TEST_ERROR; + if(H5Llink(group_id, "datatype", type_id, H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Create LCPL with intermediate group creation flag set */ if((lcpl_id = H5Pcreate(H5P_LINK_CREATE)) <0) TEST_ERROR; if(H5Pset_create_intermediate_group(lcpl_id, TRUE) <0) TEST_ERROR; /* Link nameless dataset into nameless group with intermediate group */ - if(H5Llink(group_id, "inter_group/dataset", dset_id, lcpl_id)<0) TEST_ERROR; + if(H5Llink(group_id, "inter_group/dataset", dset_id, lcpl_id, H5P_DEFAULT)<0) TEST_ERROR; /* Close IDs for dataset and datatype */ if(H5Dclose(dset_id)<0) TEST_ERROR; @@ -716,7 +721,7 @@ test_h5l_create(hid_t fapl) if((type_id = H5Topen(group_id, "datatype"))<0) TEST_ERROR; /* Link nameless group to root group and close the group ID*/ - if(H5Llink(file_id, "/group", group_id, H5P_DEFAULT)<0) TEST_ERROR; + if(H5Llink(file_id, "/group", group_id, H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; if(H5Gclose(group_id)<0) TEST_ERROR; /* Open dataset through root group and verify its data */ @@ -738,7 +743,6 @@ test_h5l_create(hid_t fapl) if(H5Pclose(lcpl_id)<0) TEST_ERROR; if(H5Sclose(space_id)<0) TEST_ERROR; if(H5Fclose(file_id)<0) TEST_ERROR; - if(H5Pclose(fapl_id)<0) TEST_ERROR; PASSED(); return 0; @@ -750,7 +754,6 @@ error: H5Pclose(lcpl_id); H5Sclose(space_id); H5Fclose(file_id); - H5Pclose(fapl_id); } H5E_END_TRY; return 1; } /* end test_h5l_create() */ @@ -791,27 +794,27 @@ test_lcpl(hid_t fapl) /* Create file */ fapl_id = h5_fileaccess(); - h5_fixname(FILENAME[12], fapl_id, filename, sizeof filename); + h5_fixname(FILENAME[0], fapl_id, filename, sizeof filename); if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id))<0) TEST_ERROR; /* Create and link a group with the default LCPL */ if((group_id = H5Gcreate_expand(file_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR; - if(H5Llink(file_id, "/group", group_id, H5P_DEFAULT)<0) TEST_ERROR; + if(H5Llink(file_id, "/group", group_id, H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; if(H5Gclose(group_id)<0) TEST_ERROR; /* Check that its character encoding is the default */ - if(H5Lget_linkinfo(file_id, "group", &linfo) < 0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "group", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; if(linfo.cset != H5F_CRT_DEFAULT_CSET) TEST_ERROR; /* Create and commit a datatype with the default LCPL */ if((type_id =H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR; if(H5Tcommit_expand(file_id, type_id, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Llink(file_id, "/type", type_id, H5P_DEFAULT)<0) TEST_ERROR; + if(H5Llink(file_id, "/type", type_id, H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; if(H5Tclose(type_id)<0) TEST_ERROR; /* Check that its character encoding is the default */ - if(H5Lget_linkinfo(file_id, "type", &linfo) < 0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "type", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; if(linfo.cset != H5F_CRT_DEFAULT_CSET) TEST_ERROR; /* Create a dataspace */ @@ -820,12 +823,12 @@ test_lcpl(hid_t fapl) if((space_id=H5Screate_simple(2 ,dims, NULL))<0) TEST_ERROR; /* Create a dataset using the default LCPL */ - if ((dset_id = H5Dcreate_expand(file_id, H5T_NATIVE_INT, space_id, H5P_DEFAULT)) <0) TEST_ERROR; - if(H5Llink(file_id, "/dataset", dset_id, H5P_DEFAULT)<0) TEST_ERROR; + if ((dset_id = H5Dcreate_expand(file_id, H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT)) <0) TEST_ERROR; + if(H5Llink(file_id, "/dataset", dset_id, H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; if(H5Dclose(dset_id)<0) TEST_ERROR; /* Check that its character encoding is the default */ - if(H5Lget_linkinfo(file_id, "dataset", &linfo) < 0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "dataset", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; if(linfo.cset != H5F_CRT_DEFAULT_CSET) TEST_ERROR; /* Create a link creation property list with the UTF-8 character encoding */ @@ -834,30 +837,30 @@ test_lcpl(hid_t fapl) /* Create and link a group with the new LCPL */ if((group_id = H5Gcreate_expand(file_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR; - if(H5Llink(file_id, "/group2", group_id, lcpl_id)<0) TEST_ERROR; + if(H5Llink(file_id, "/group2", group_id, lcpl_id, H5P_DEFAULT)<0) TEST_ERROR; if(H5Gclose(group_id)<0) TEST_ERROR; /* Check that its character encoding is UTF-8 */ - if(H5Lget_linkinfo(file_id, "group2", &linfo) < 0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "group2", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; if(linfo.cset != H5T_CSET_UTF8) TEST_ERROR; /* Create and commit a datatype with the new LCPL */ if((type_id =H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR; if(H5Tcommit_expand(file_id, type_id, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; - if(H5Llink(file_id, "/type2", type_id, lcpl_id)<0) TEST_ERROR; + if(H5Llink(file_id, "/type2", type_id, lcpl_id, H5P_DEFAULT)<0) TEST_ERROR; if(H5Tclose(type_id)<0) TEST_ERROR; /* Check that its character encoding is UTF-8 */ - if(H5Lget_linkinfo(file_id, "type2", &linfo) < 0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "type2", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; if(linfo.cset != H5T_CSET_UTF8) TEST_ERROR; /* Create a dataset using the new LCPL */ - if ((dset_id = H5Dcreate_expand(file_id, H5T_NATIVE_INT, space_id, H5P_DEFAULT)) <0) TEST_ERROR; - if(H5Llink(file_id, "/dataset2", dset_id, lcpl_id)<0) TEST_ERROR; + if ((dset_id = H5Dcreate_expand(file_id, H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT)) <0) TEST_ERROR; + if(H5Llink(file_id, "/dataset2", dset_id, lcpl_id, H5P_DEFAULT)<0) TEST_ERROR; if(H5Dclose(dset_id)<0) TEST_ERROR; /* Check that its character encoding is UTF-8 */ - if(H5Lget_linkinfo(file_id, "dataset2", &linfo) < 0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "dataset2", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; if(linfo.cset != H5T_CSET_UTF8) TEST_ERROR; /* Create a new link to the dataset with a different character encoding. */ @@ -865,15 +868,46 @@ test_lcpl(hid_t fapl) if((lcpl_id = H5Pcreate(H5P_LINK_CREATE)) <0) TEST_ERROR; if(H5Pset_char_encoding(lcpl_id, H5T_CSET_ASCII) < 0) TEST_ERROR; - if(H5Lcreate_hard(file_id, "/dataset2", file_id, "/dataset2_link", lcpl_id) < 0) TEST_ERROR; + if(H5Lcreate_hard(file_id, "/dataset2", file_id, "/dataset2_link", lcpl_id, H5P_DEFAULT) < 0) TEST_ERROR; /* Check that its character encoding is ASCII */ - if(H5Lget_linkinfo(file_id, "/dataset2_link", &linfo) < 0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "/dataset2_link", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; if(linfo.cset != H5T_CSET_ASCII) TEST_ERROR; /* Check that the first link's encoding hasn't changed */ - if(H5Lget_linkinfo(file_id, "/dataset2", &linfo) < 0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "/dataset2", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; + if(linfo.cset != H5T_CSET_UTF8) TEST_ERROR; + + +/* JAMES: these tests don't work because the character set encoding is + * not stored in the symbol table. + * Quincey says this will be fixed someday. + */ +#ifdef NOTYET + /* Make sure that LCPLs work properly for other API calls: */ + /* H5Lcreate_soft */ + if(H5Pset_char_encoding(lcpl_id, H5T_CSET_UTF8) < 0) TEST_ERROR + if(H5Lcreate_soft("dataset2", file_id, "slink_to_dset2", lcpl_id, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Lget_linkinfo(file_id, "slink_to_dset2", &linfo, H5P_DEFAULT) < 0) TEST_ERROR + if(linfo.cset != H5T_CSET_UTF8) TEST_ERROR + + /* H5Lmove */ + if(H5Pset_char_encoding(lcpl_id, H5T_CSET_ASCII) < 0) TEST_ERROR + if(H5Lmove(file_id, "slink_to_dset2", file_id, "moved_slink", lcpl_id, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Lget_linkinfo(file_id, "moved_slink", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; + if(linfo.cset != H5T_CSET_ASCII) TEST_ERROR; + + /* H5Lcopy */ + if(H5Pset_char_encoding(lcpl_id, H5T_CSET_UTF8) < 0) TEST_ERROR; + if(H5Lcopy(file_id, "moved_slink", file_id, "copied_slink", lcpl_id, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Lget_linkinfo(file_id, "copied_slink", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; + if(linfo.cset != H5T_CSET_UTF8) TEST_ERROR; + + /* H5Lcreate_external */ + if(H5Lcreate_external("filename", "path", file_id, "extlink", lcpl_id, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Lget_linkinfo(file_id, "extlink", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; if(linfo.cset != H5T_CSET_UTF8) TEST_ERROR; +#endif /* NOTYET */ /* Close open IDs */ if(H5Pclose(lcpl_id)<0) TEST_ERROR; @@ -924,10 +958,10 @@ test_move(hid_t fapl) TESTING("H5Lmove"); /* Create two new files */ - h5_fixname(FILENAME[8], fapl, filename, sizeof filename); + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); if ((file_a=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; - h5_fixname(FILENAME[9], fapl, filename, sizeof filename); + h5_fixname(FILENAME[1], fapl, filename, sizeof filename); if ((file_b=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; @@ -937,26 +971,26 @@ test_move(hid_t fapl) if((grp_move=H5Gcreate(grp_1, "group_move", 0))<0) TEST_ERROR; /* Create hard and soft links. */ - if(H5Lcreate_hard(grp_1, "group_move", H5L_SAME_LOC, "hard", H5P_DEFAULT)<0) + if(H5Lcreate_hard(grp_1, "group_move", H5L_SAME_LOC, "hard", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; - if(H5Lcreate_soft("/group1/group_move", grp_2, "soft", H5P_DEFAULT)<0) + if(H5Lcreate_soft("/group1/group_move", grp_2, "soft", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Move a group within the file. Both of source and destination use * H5L_SAME_LOC. Should fail. */ H5E_BEGIN_TRY { - if(H5Lmove(H5L_SAME_LOC, "group_move", H5L_SAME_LOC, "group_new_name", H5P_DEFAULT) + if(H5Lmove(H5L_SAME_LOC, "group_move", H5L_SAME_LOC, "group_new_name", H5P_DEFAULT, H5P_DEFAULT) !=FAIL) TEST_ERROR; } H5E_END_TRY; /* Move a group across files. Should fail. */ H5E_BEGIN_TRY { - if(H5Lmove(grp_1, "group_move", file_b, "group_new_name", H5P_DEFAULT) + if(H5Lmove(grp_1, "group_move", file_b, "group_new_name", H5P_DEFAULT, H5P_DEFAULT) !=FAIL) TEST_ERROR; } H5E_END_TRY; /* Move a group across groups in the same file while renaming it. */ - if(H5Lmove(grp_1, "group_move", grp_2, "group_new_name", H5P_DEFAULT)<0) + if(H5Lmove(grp_1, "group_move", grp_2, "group_new_name", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Open the group just moved to the new location. */ @@ -972,7 +1006,7 @@ test_move(hid_t fapl) } H5E_END_TRY; /* Use H5Lmove to rename a group without moving it. */ - if(H5Lmove(grp_2, "group_new_name", H5L_SAME_LOC, "group_newer_name", H5P_DEFAULT)<0) + if(H5Lmove(grp_2, "group_new_name", H5L_SAME_LOC, "group_newer_name", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Open the group. */ @@ -982,7 +1016,7 @@ test_move(hid_t fapl) TEST_ERROR; /* Use H5Lmove to move a group without renaming it. */ - if(H5Lmove(grp_2, "group_newer_name", grp_1, "group_newer_name", H5P_DEFAULT)<0) + if(H5Lmove(grp_2, "group_newer_name", grp_1, "group_newer_name", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Open the group . */ @@ -992,7 +1026,7 @@ test_move(hid_t fapl) TEST_ERROR; /* Move the group while giving long paths. */ - if(H5Lmove(file_a, "/group1/group_newer_name", grp_2, "/group2/group_newest_name", H5P_DEFAULT)<0) + if(H5Lmove(file_a, "/group1/group_newer_name", grp_2, "/group2/group_newest_name", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Open the group just moved to the new location. */ @@ -1063,10 +1097,10 @@ test_copy(hid_t fapl) TESTING("H5Lcopy"); /* Create two new files */ - h5_fixname(FILENAME[8], fapl, filename, sizeof filename); + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); if ((file_a=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; - h5_fixname(FILENAME[9], fapl, filename, sizeof filename); + h5_fixname(FILENAME[1], fapl, filename, sizeof filename); if ((file_b=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; @@ -1076,26 +1110,26 @@ test_copy(hid_t fapl) if((grp_move=H5Gcreate(grp_1, "group_copy", 0))<0) TEST_ERROR; /* Create hard and soft links. */ - if(H5Lcreate_hard(grp_1, "group_copy", H5L_SAME_LOC, "hard", H5P_DEFAULT)<0) + if(H5Lcreate_hard(grp_1, "group_copy", H5L_SAME_LOC, "hard", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; - if(H5Lcreate_soft("/group1/group_copy", grp_2, "soft", H5P_DEFAULT)<0) + if(H5Lcreate_soft("/group1/group_copy", grp_2, "soft", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Copy a group within the file. Both of source and destination use * H5L_SAME_LOC. Should fail. */ H5E_BEGIN_TRY { - if(H5Lcopy(H5L_SAME_LOC, "group_copy", H5L_SAME_LOC, "group_new_name", H5P_DEFAULT) + if(H5Lcopy(H5L_SAME_LOC, "group_copy", H5L_SAME_LOC, "group_new_name", H5P_DEFAULT, H5P_DEFAULT) !=FAIL) TEST_ERROR; } H5E_END_TRY; /* Copy a group across files. Should fail. */ H5E_BEGIN_TRY { - if(H5Lcopy(grp_1, "group_copy", file_b, "group_new_name", H5P_DEFAULT) + if(H5Lcopy(grp_1, "group_copy", file_b, "group_new_name", H5P_DEFAULT, H5P_DEFAULT) !=FAIL) TEST_ERROR; } H5E_END_TRY; /* Move a group across groups in the same file while renaming it. */ - if(H5Lcopy(grp_1, "group_copy", grp_2, "group_new_name", H5P_DEFAULT)<0) + if(H5Lcopy(grp_1, "group_copy", grp_2, "group_new_name", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Open the group just moved to the new location. */ @@ -1111,7 +1145,7 @@ test_copy(hid_t fapl) TEST_ERROR; /* Use H5Lcopy to create a group in the same location with a different name. */ - if(H5Lcopy(grp_2, "group_new_name", H5L_SAME_LOC, "group_newer_name", H5P_DEFAULT)<0) + if(H5Lcopy(grp_2, "group_new_name", H5L_SAME_LOC, "group_newer_name", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Open the group. */ @@ -1126,7 +1160,7 @@ test_copy(hid_t fapl) TEST_ERROR; /* Use H5Lcopy to copy to a different location with the same name. */ - if(H5Lcopy(grp_2, "group_newer_name", grp_1, "group_newer_name", H5P_DEFAULT)<0) + if(H5Lcopy(grp_2, "group_newer_name", grp_1, "group_newer_name", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Open the group . */ @@ -1141,7 +1175,7 @@ test_copy(hid_t fapl) TEST_ERROR; /* Copy the group while giving long paths. */ - if(H5Lcopy(file_a, "/group1/group_newer_name", grp_2, "/group2/group_newest_name", H5P_DEFAULT)<0) + if(H5Lcopy(file_a, "/group1/group_newer_name", grp_2, "/group2/group_newest_name", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR; /* Open the group just moved to the new location. */ @@ -1224,7 +1258,7 @@ test_move_preserves(hid_t fapl_id) TESTING("moving and copying links preserves their properties"); /* Create file */ - h5_fixname(FILENAME[11], fapl_id, filename, sizeof filename); + h5_fixname(FILENAME[0], fapl_id, filename, sizeof filename); if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id))<0) TEST_ERROR; @@ -1233,11 +1267,11 @@ test_move_preserves(hid_t fapl_id) if(H5Pset_char_encoding(lcpl_id, H5T_CSET_UTF8) < 0) TEST_ERROR; /* Create a group with that lcpl */ if((group_id = H5Gcreate_expand(file_id, H5P_DEFAULT, H5P_DEFAULT)) <0) TEST_ERROR; - if(H5Llink(file_id, "group", group_id, lcpl_id) < 0) TEST_ERROR; + if(H5Llink(file_id, "group", group_id, lcpl_id, H5P_DEFAULT) < 0) TEST_ERROR; if(H5Gclose(group_id) < 0) TEST_ERROR; /* Get the group's link's creation time */ - if(H5Lget_linkinfo(file_id, "group", &linfo) < 0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "group", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; if(H5Gget_objinfo(file_id, "group", TRUE, &statbuf) <0) TEST_ERROR; old_create_time = linfo.ctime; old_modification_time = statbuf.mtime; @@ -1251,33 +1285,33 @@ test_move_preserves(hid_t fapl_id) if((file_id = H5Fopen(filename, H5F_ACC_RDWR, fapl_id)) <0) TEST_ERROR; /* Get the group's link's creation time. The times should be unchanged */ - if(H5Lget_linkinfo(file_id, "group", &linfo) < 0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "group", &linfo, H5P_DEFAULT) < 0) TEST_ERROR; if(H5Gget_objinfo(file_id, "group", TRUE, &statbuf) <0) TEST_ERROR; if(old_modification_time != statbuf.mtime) TEST_ERROR; if(old_create_time != linfo.ctime) TEST_ERROR; /* Create a new link to the group. It should have a different creation time but the same modification time */ - if(H5Lcreate_hard(file_id, "group", file_id, "group2", H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_hard(file_id, "group", file_id, "group2", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; if(H5Gget_objinfo(file_id, "group2", TRUE, &statbuf) <0) TEST_ERROR; if(old_modification_time != statbuf.mtime) TEST_ERROR; - if(H5Lget_linkinfo(file_id, "group2", &linfo) <0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "group2", &linfo, H5P_DEFAULT) <0) TEST_ERROR; if(old_create_time == linfo.ctime) TEST_ERROR; /* Copy the first link to a UTF-8 name. Its creation time and modification time should not change. */ - if(H5Lcopy(file_id, "group", file_id, "group_copied", lcpl_id) <0) TEST_ERROR; + if(H5Lcopy(file_id, "group", file_id, "group_copied", lcpl_id, H5P_DEFAULT) <0) TEST_ERROR; if(H5Gget_objinfo(file_id, "group_copied", TRUE, &statbuf) <0) TEST_ERROR; if(old_modification_time != statbuf.mtime) TEST_ERROR; - if(H5Lget_linkinfo(file_id, "group_copied", &linfo) <0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "group_copied", &linfo, H5P_DEFAULT) <0) TEST_ERROR; if(old_create_time != linfo.ctime) TEST_ERROR; /* Check that its character encoding is UTF-8 */ if(linfo.cset != H5T_CSET_UTF8) TEST_ERROR; /* Move the link with the default property list. */ - if(H5Lmove(file_id, "group_copied", file_id, "group_copied2", H5P_DEFAULT) <0) TEST_ERROR; + if(H5Lmove(file_id, "group_copied", file_id, "group_copied2", H5P_DEFAULT, H5P_DEFAULT) <0) TEST_ERROR; if(H5Gget_objinfo(file_id, "group_copied2", TRUE, &statbuf) <0) TEST_ERROR; if(old_modification_time != statbuf.mtime) TEST_ERROR; - if(H5Lget_linkinfo(file_id, "group_copied2", &linfo) <0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "group_copied2", &linfo, H5P_DEFAULT) <0) TEST_ERROR; if(old_create_time != linfo.ctime) TEST_ERROR; /* Check that its character encoding is not UTF-8 */ @@ -1286,25 +1320,25 @@ test_move_preserves(hid_t fapl_id) /* Check that the original link is unchanged */ if(H5Gget_objinfo(file_id, "group", TRUE, &statbuf) <0) TEST_ERROR; if(old_modification_time != statbuf.mtime) TEST_ERROR; - if(H5Lget_linkinfo(file_id, "group", &linfo) <0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "group", &linfo, H5P_DEFAULT) <0) TEST_ERROR; if(old_create_time != linfo.ctime) TEST_ERROR; if(linfo.cset != H5T_CSET_UTF8) TEST_ERROR; /* Move the first link to a UTF-8 name. Its creation time and modification time should not change. */ - if(H5Lmove(file_id, "group", file_id, "group_moved", lcpl_id) <0) TEST_ERROR; + if(H5Lmove(file_id, "group", file_id, "group_moved", lcpl_id, H5P_DEFAULT) <0) TEST_ERROR; if(H5Gget_objinfo(file_id, "group_moved", TRUE, &statbuf) <0) TEST_ERROR; if(old_modification_time != statbuf.mtime) TEST_ERROR; - if(H5Lget_linkinfo(file_id, "group_moved", &linfo) <0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "group_moved", &linfo, H5P_DEFAULT) <0) TEST_ERROR; if(old_create_time != linfo.ctime) TEST_ERROR; /* Check that its character encoding is UTF-8 */ if(linfo.cset != H5T_CSET_UTF8) TEST_ERROR; /* Move the link again using the default property list. */ - if(H5Lmove(file_id, "group_moved", file_id, "group_moved_again", H5P_DEFAULT) <0) TEST_ERROR; + if(H5Lmove(file_id, "group_moved", file_id, "group_moved_again", H5P_DEFAULT, H5P_DEFAULT) <0) TEST_ERROR; if(H5Gget_objinfo(file_id, "group_moved_again", TRUE, &statbuf) <0) TEST_ERROR; if(old_modification_time != statbuf.mtime) TEST_ERROR; - if(H5Lget_linkinfo(file_id, "group_moved_again", &linfo) <0) TEST_ERROR; + if(H5Lget_linkinfo(file_id, "group_moved_again", &linfo, H5P_DEFAULT) <0) TEST_ERROR; if(old_create_time != linfo.ctime) TEST_ERROR; /* Check that its character encoding is not UTF-8 */ @@ -1357,7 +1391,7 @@ test_compat(hid_t fapl) TESTING("backwards compatibility"); /* Create file */ - h5_fixname(FILENAME[15], fapl, filename, sizeof filename); + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; @@ -1439,6 +1473,3222 @@ error: /*------------------------------------------------------------------------- + * Function: external_link_root + * + * Purpose: Build a file with external link to root group in external file + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Wednesday, May 25, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +external_link_root(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + H5G_stat_t sb; /* Object information */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + char filename1[NAME_BUF_SIZE]; + char filename2[NAME_BUF_SIZE]; + char *file; /* File from external link */ + char *path; /* Path from external link */ + + TESTING("external link to root"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + + /* Create file to point to */ + if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + /* Check that external links are registered with the library */ + if(H5Lis_registered(H5L_LINK_EXTERNAL) != TRUE) TEST_ERROR + + /* Create file with link to first file */ + if((fid=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create external link to object in first file */ + if(H5Lcreate_external(filename1, "/", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Check information for external link */ + if (H5Gget_objinfo(fid, "ext_link", FALSE, &sb)<0) goto error; + if (H5G_UDLINK!=sb.type) { + H5_FAILED(); + puts(" Unexpected object type - should have been an external link"); + goto error; + } + if(H5Lget_linkval(fid, "ext_link", sizeof(objname), objname, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Lunpack_elink_val(objname, &file, &path) < 0) TEST_ERROR + if(HDstrcmp(file, filename1)) + { + H5_FAILED(); + puts(" External link file name incorrect"); + goto error; + } + if(HDstrcmp(path, "/")) + { + H5_FAILED(); + puts(" External link path incorrect"); + goto error; + } + + /* Close and re-open file to ensure that data is written to disk */ + if(H5Fclose(fid) < 0) TEST_ERROR; + if((fid = H5Fopen(filename2, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) TEST_ERROR; + + + /* Open object through external link */ + if((gid = H5Gopen(fid, "ext_link")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in external file */ + if((gid2 = H5Gcreate(gid, "new_group", (size_t)0)) < 0) TEST_ERROR + + /* Close group in external file */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close external object (lets first file close) */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Close second file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Open first file again and check on object created */ + if((fid = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) TEST_ERROR + + /* Open object created through external link */ + if((gid = H5Gopen(fid, "new_group")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(HDstrcmp(objname, "/new_group")) TEST_ERROR + + /* Close opened object */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Close first file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Fclose (gid2); + H5Fclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end external_link_root() */ + + +/*------------------------------------------------------------------------- + * Function: external_link_path + * + * Purpose: Build a file with external link to object down a path in the + * external file + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, July 26, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +external_link_path(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + char filename1[NAME_BUF_SIZE]; + char filename2[NAME_BUF_SIZE]; + + TESTING("external link to object on path"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + + /* Create file to point to */ + if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create object down a path */ + if((gid = H5Gcreate(fid, "A", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + if((gid = H5Gcreate(fid, "A/B", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + if((gid = H5Gcreate(fid, "A/B/C", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Create file with link to first file */ + if((fid=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create external link to object in first file */ + if(H5Lcreate_external(filename1, "/A/B/C", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Open object through external link */ + if((gid = H5Gopen(fid, "ext_link")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in external file */ + if((gid2 = H5Gcreate(gid, "new_group", (size_t)0)) < 0) TEST_ERROR + + /* Close group in external file */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close external object (lets first file close) */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Close second file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Open first file again and check on object created */ + if((fid = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) TEST_ERROR + + /* Open object created through external link */ + if((gid = H5Gopen(fid, "/A/B/C/new_group")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(HDstrcmp(objname, "/A/B/C/new_group")) TEST_ERROR + + /* Close opened object */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Close first file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose (gid2); + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end external_link_path() */ + + +/*------------------------------------------------------------------------- + * Function: external_link_mult + * + * Purpose: Build a file with external link to object that crossed several + * external file links + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, July 26, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +external_link_mult(hid_t fapl) +{ + hid_t fid = (-1), fid2 = (-1); /* File IDs */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE], + filename3[NAME_BUF_SIZE], + filename4[NAME_BUF_SIZE]; /* Names of files to externally link across */ + + TESTING("external links across multiple files"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + h5_fixname(FILENAME[5], fapl, filename3, sizeof filename3); + h5_fixname(FILENAME[6], fapl, filename4, sizeof filename4); + + /* Create first file to point to */ + if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create object down a path */ + if((gid = H5Gcreate(fid, "A", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + if((gid = H5Gcreate(fid, "A/B", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + if((gid = H5Gcreate(fid, "A/B/C", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + /* Create second file to point to */ + if((fid=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create external link down a path */ + if((gid = H5Gcreate(fid, "D", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + if((gid = H5Gcreate(fid, "D/E", (size_t)0)) < 0) TEST_ERROR + + /* Create external link to object in first file */ + if(H5Lcreate_external(filename1, "/A/B/C", gid, "F", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + /* Create third file to point to */ + if((fid=H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create external link down a path */ + if((gid = H5Gcreate(fid, "G", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + if((gid = H5Gcreate(fid, "G/H", (size_t)0)) < 0) TEST_ERROR + + /* Create external link to object in second file */ + if(H5Lcreate_external(filename2, "/D/E/F", gid, "I", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Create file with link to third file */ + if((fid=H5Fcreate(filename4, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create external link to object in first file */ + if(H5Lcreate_external(filename3, "/G/H/I", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Open object through external link */ + if((gid = H5Gopen(fid, "ext_link")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in external file */ + if((gid2 = H5Gcreate(gid, "new_group", (size_t)0)) < 0) TEST_ERROR + + /* Close group in external file */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close external object (lets first file close) */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Close second file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Open first file again and check on object created */ + if((fid = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) TEST_ERROR + + /* Open object created through external link */ + if((gid = H5Gopen(fid, "/A/B/C/new_group")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(HDstrcmp(objname, "/A/B/C/new_group")) TEST_ERROR + + /* Close opened object */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close first file */ + if(H5Fclose(fid)<0) TEST_ERROR + + + /* Open an object through external links */ + if((fid = H5Fopen(filename4, H5F_ACC_RDONLY, H5P_DEFAULT)) <0) TEST_ERROR + if((gid = H5Gopen(fid, "ext_link")) < 0) TEST_ERROR + + /* The intermediate files should not stay open. Replace one of them with a new file. */ + if((fid2=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + if(H5Fclose(fid2)<0) TEST_ERROR + + /* Open the other with write access and delete the external link in it */ + if((fid2=H5Fopen(filename3, H5F_ACC_RDWR, fapl))<0) TEST_ERROR + if(H5Lunlink(fid2, "G/H/I", H5P_DEFAULT) < 0) TEST_ERROR + + if(H5Fclose(fid2)<0) TEST_ERROR + + /* Cleanup */ + if(H5Gclose(gid) < 0) TEST_ERROR + if(H5Fclose(fid)<0) TEST_ERROR + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose (gid2); + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end external_link_mult() */ + + +/*------------------------------------------------------------------------- + * Function: external_link_self + * + * Purpose: Build a file with external link to itself + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: James Laird + * Wednesday, July 12, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifdef H5_GROUP_REVISION +static int +external_link_self(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + hid_t lcpl_id = (-1); /* Link Creation Property List ID */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + char filename1[NAME_BUF_SIZE]; + char filename2[NAME_BUF_SIZE]; + char filename3[NAME_BUF_SIZE]; + + TESTING("external link to self"); + + /* Set up filename */ + h5_fixname(FILENAME[1], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[2], fapl, filename2, sizeof filename1); + h5_fixname(FILENAME[3], fapl, filename3, sizeof filename1); + + /* Create file */ + if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create an lcpl with intermediate group creation set */ + if((lcpl_id=H5Pcreate(H5P_LINK_CREATE))<0) TEST_ERROR + if(H5Pset_create_intermediate_group(lcpl_id, TRUE) < 0) TEST_ERROR + + /* Create a series of groups within the file: /A/B and /X/Y/Z */ + if((gid=H5Gcreate_expand(fid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Llink(fid, "A/B", gid, lcpl_id, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + if((gid=H5Gcreate_expand(fid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Llink(fid, "X/Y", gid, lcpl_id, H5P_DEFAULT) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + if(H5Pclose (lcpl_id) <0) TEST_ERROR + + /* Create external link to own root group*/ + if(H5Lcreate_external(filename1, "/X", fid, "A/B/C", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Open object through external link */ + if((gid = H5Gopen(fid, "A/B/C/")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object through external link */ + if((gid2 = H5Gcreate(gid, "new_group", (size_t)0)) < 0) TEST_ERROR + + /* Close created group */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close object opened through external link */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Check on object created */ + if((gid = H5Gopen(fid, "X/new_group")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(HDstrcmp(objname, "/X/new_group")) TEST_ERROR + + /* Close opened object */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Close first file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Complicate things. Use this file as an intermediate file in a chain + * of external links that will go: file2 -> file1 -> file1 -> file3 + */ + + /* Create file2 with an external link to file1 */ + if((fid=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR + + if(H5Lcreate_external(filename1, "/A", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Close file2 */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Create file3 as a target */ + if((fid=H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR + if((gid=H5Gcreate(fid, "end", 0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Open file1 and create an extlink pointing to file3 */ + if((fid=H5Fopen(filename1, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) TEST_ERROR + + if(H5Lcreate_external(filename3, "/", fid, "/X/Y/Z", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Close file1 */ + if(H5Fclose(fid) < 0) TEST_ERROR + + + /* Re-open file2 and traverse through file1 (with its recursive extlink) to file3 */ + if((fid=H5Fopen(filename2, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) TEST_ERROR + + if((gid=H5Gopen(fid, "ext_link/B/C/Y/Z/end")) < 0) TEST_ERROR + + /* Create object through external link */ + if((gid2 = H5Gcreate(gid, "newer_group", 0)) < 0) TEST_ERROR + + /* Cleanup */ + if(H5Gclose(gid2) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Open up file3 and make sure the object was created successfully */ + if((fid=H5Fopen(filename3, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) TEST_ERROR + + if((gid=H5Gopen(fid, "end/newer_group")) < 0) TEST_ERROR + + /* Cleanup */ + if(H5Gclose(gid) < 0) TEST_ERROR + if(H5Fclose(fid) < 0) TEST_ERROR + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Fclose (gid2); + H5Fclose (gid); + H5Pclose (lcpl_id); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end external_link_self() */ +#endif /* H5_GROUP_REVISION */ + + +/*------------------------------------------------------------------------- + * Function: external_link_pingpong + * + * Purpose: Build a file with external link to object that goes back and + * force between two files a couple of times: + * + * file1:/link1 -> file2: /link2 + * file2:/link2 -> file1: /link3 + * file1:/link3 -> file2: /link4 + * file2:/link4 -> file1: /link5 + * file1:/link5 -> file2: /link6 + * file2:/link6 -> file1: /final + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, July 26, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +external_link_pingpong(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE]; /* Names of files to externally link across */ + + TESTING("external links back and forth"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + + /* Create first file */ + if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create external links for chain */ + if(H5Lcreate_external(filename2, "/link2", fid, "link1", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/link4", fid, "link3", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/link6", fid, "link5", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Create final object */ + if((gid = H5Gcreate(fid, "final", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + /* Create second file */ + if((fid=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create external links for chain */ + if(H5Lcreate_external(filename1, "/link3", fid, "link2", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename1, "/link5", fid, "link4", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename1, "/final", fid, "link6", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Open first file */ + if((fid=H5Fopen(filename1, H5F_ACC_RDWR, fapl))<0) TEST_ERROR; + + /* Open object through external link */ + if((gid = H5Gopen(fid, "link1")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in external file */ + if((gid2 = H5Gcreate(gid, "new_group", (size_t)0)) < 0) TEST_ERROR + + /* Close group in external file */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close external object (lets first file close) */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Close first file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Open first file again and check on object created */ + if((fid = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) TEST_ERROR + + /* Open object created through external link */ + if((gid = H5Gopen(fid, "/final/new_group")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(HDstrcmp(objname, "/final/new_group")) TEST_ERROR + + /* Close opened object */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Close first file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose (gid2); + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end external_link_pingpong() */ + + +/*------------------------------------------------------------------------- + * Function: external_link_toomany + * + * Purpose: Build a file with too many external links to objects (i.e. + * more than H5G_NLINKS. Use a "back & forth" style of + * linking (like the "ping pong" test above) to minimize the + * number of files involved: + * + * file1:/link1 -> file2: /link2 + * file2:/link2 -> file1: /link3 + * file1:/link3 -> file2: /link4 + * file2:/link4 -> file1: /link5 + * file1:/link5 -> file2: /link6 + * file2:/link6 -> file1: /link7 + * file1:/link7 -> file2: /link8 + * file2:/link8 -> file1: /link9 + * file1:/link9 -> file2: /link10 + * file2:/link10 -> file1: /link11 + * file1:/link11 -> file2: /link12 + * file2:/link12 -> file1: /link13 + * file1:/link13 -> file2: /link14 + * file2:/link14 -> file1: /link15 + * file1:/link15 -> file2: /link16 + * file2:/link16 -> file1: /link17 + * file1:/link17 -> file2: /final + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Monday, August 8, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +external_link_toomany(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE]; /* Names of files to externally link across */ + + TESTING("too many external links"); + + /* Make certain test is valid */ + /* XXX: should probably make a "generic" test that creates the proper + * # of links based on this value - QAK + */ + HDassert(H5G_NLINKS == 16); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + + /* Create first file */ + if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create external links for chain */ + if(H5Lcreate_external(filename2, "/link2", fid, "link1", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/link4", fid, "link3", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/link6", fid, "link5", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/link8", fid, "link7", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/link10", fid, "link9", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/link12", fid, "link11", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/link14", fid, "link13", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/link16", fid, "link15", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/final", fid, "link17", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + /* Create second file */ + if((fid=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create external links for chain */ + if(H5Lcreate_external(filename1, "/link3", fid, "link2", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename1, "/link5", fid, "link4", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename1, "/link7", fid, "link6", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename1, "/link9", fid, "link8", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename1, "/link11", fid, "link10", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename1, "/link13", fid, "link12", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename1, "/link15", fid, "link14", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename1, "/link17", fid, "link16", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Create final object */ + if((gid = H5Gcreate(fid, "final", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Open first file */ + if((fid=H5Fopen(filename1, H5F_ACC_RDWR, fapl))<0) TEST_ERROR; + + /* Open object through external link */ + H5E_BEGIN_TRY { + gid = H5Gopen(fid, "link1"); + } H5E_END_TRY; + if (gid >= 0) { + H5_FAILED(); + puts(" Should have failed for sequence of too many nested links."); + goto error; + } + + /* Open object through external link */ + if((gid = H5Gopen(fid, "link3")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in external file */ + if((gid2 = H5Gcreate(gid, "new_group", (size_t)0)) < 0) TEST_ERROR + + /* Close group in external file */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close external object */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Close first file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose (gid2); + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end external_link_toomany() */ + + +/*------------------------------------------------------------------------- + * Function: external_link_dangling + * + * Purpose: Build a file with "dangling" external links: with both + * missing files and missing objects. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, August 9, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +external_link_dangling(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1); /* Group IDs */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE]; /* Names of files to externally link across */ + + TESTING("dangling external links"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + + /* Create first file */ + if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create dangling external links */ + if(H5Lcreate_external("missing", "/missing", fid, "no_file", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external(filename2, "/missing", fid, "no_object", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + /* Create second file (for dangling object test) */ + if((fid=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Open first file */ + if((fid=H5Fopen(filename1, H5F_ACC_RDWR, fapl))<0) TEST_ERROR; + + /* Open object through dangling file external link */ + H5E_BEGIN_TRY { + gid = H5Gopen(fid, "no_file"); + } H5E_END_TRY; + if (gid >= 0) { + H5_FAILED(); + puts(" Should have failed for sequence of too many nested links."); + goto error; + } + + /* Open object through dangling object external link */ + H5E_BEGIN_TRY { + gid = H5Gopen(fid, "no_object"); + } H5E_END_TRY; + if (gid >= 0) { + H5_FAILED(); + puts(" Should have failed for sequence of too many nested links."); + goto error; + } + + /* Close first file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end external_link_dangling() */ + + +/*------------------------------------------------------------------------- + * Function: external_link_recursive + * + * Purpose: Build a file with "recursive" external link + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Monday, August 15, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +external_link_recursive(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1); /* Group IDs */ + char filename1[NAME_BUF_SIZE]; /* Names of files to externally link across */ + + TESTING("recursive external links"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + + /* Create first file */ + if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create recursive external links */ + if(H5Lcreate_external(filename1, "/recursive", fid, "recursive", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + /* Open file */ + if((fid=H5Fopen(filename1, H5F_ACC_RDONLY, fapl))<0) TEST_ERROR; + + /* Open object through dangling file external link */ + H5E_BEGIN_TRY { + gid = H5Gopen(fid, "recursive"); + } H5E_END_TRY; + if (gid >= 0) { + H5_FAILED(); + puts(" Should have failed for recursive external links."); + goto error; + } + + /* Close first file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end external_link_recursive() */ + + +/*------------------------------------------------------------------------- + * Function: external_link_query + * + * Purpose: Query file & object names for external links, as well as + * information from H5Gget_obj_info + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Monday, August 15, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +external_link_query(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1); /* Group IDs */ + char *file_name; /* Name of the file the external link points to */ + char *object_name; /* Name of the object the external link points to */ + H5G_stat_t sb; /* Object information */ + H5L_linkinfo_t li; /* Link information */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE], /* Names of files to externally link across */ + query_buf[NAME_BUF_SIZE]; /* Buffer to hold query result */ + + + TESTING("query aspects of external link"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + + /* Create first file, with external link to object in second file */ + if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR + + /* Create external link */ + if(H5Lcreate_external(filename2, "/dst", fid, "src", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Get size of buffer for external link */ + if(H5Lget_linkinfo(fid, "src", &li, H5P_DEFAULT) < 0) TEST_ERROR + if(li.u.link_size != (HDstrlen(filename2) + HDstrlen("/dst") + 2)) TEST_ERROR + if (H5L_LINK_EXTERNAL != li.linkclass) { + H5_FAILED(); + puts(" Unexpected link class - should have been an external link"); + goto error; + } + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + /* Create second file to point to */ + if((fid=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR + + /* Create object to link to */ + if((gid = H5Gcreate(fid, "dst", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR + + + /* Open first file */ + if((fid=H5Fopen(filename1, H5F_ACC_RDONLY, fapl))<0) TEST_ERROR + + /* Get size of buffer for external link */ + if(H5Lget_linkinfo(fid, "src", &li, H5P_DEFAULT) < 0) TEST_ERROR + if(li.u.link_size != (HDstrlen(filename2) + HDstrlen("/dst") + 2)) TEST_ERROR + if (H5L_LINK_EXTERNAL != li.linkclass) { + H5_FAILED(); + puts(" Unexpected link class - should have been an external link"); + goto error; + } + + /* Get information for external link. It should be two strings right after each other */ + if(H5Lget_linkval(fid, "src", NAME_BUF_SIZE, query_buf, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Extract the file and object names from the buffer */ + if(H5Lunpack_elink_val(query_buf, &file_name, &object_name) < 0) TEST_ERROR + + /* Compare the file and object names */ + if(strcmp(file_name, filename2)) TEST_ERROR; + if(strcmp(object_name, "/dst")) TEST_ERROR + + /* Query information about object that external link points to */ + if (H5Gget_objinfo(fid, "src", TRUE, &sb)<0) goto error; + if (H5G_GROUP != sb.type) { + H5_FAILED(); + puts(" Unexpected object type - should have been a group"); + goto error; + } + + /* Close first file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + /* Make sure that passing in NULLs to H5Lunpack_elink_val works */ + if(H5Lunpack_elink_val(query_buf, NULL, NULL) < 0) TEST_ERROR + + /* Make sure that bogus cases trigger errors in H5Lunpack_elink_val */ + H5E_BEGIN_TRY { + if(H5Lunpack_elink_val(NULL, NULL, NULL) >= 0) TEST_ERROR + } H5E_END_TRY + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end external_link_query() */ + + +/*------------------------------------------------------------------------- + * Function: external_link_unlink_compact + * + * Purpose: Remove an external link (from a compact group) + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Wednesday, January 18, 2006 + * + *------------------------------------------------------------------------- + */ +static int +external_link_unlink_compact(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE]; /* Names of files to externally link across */ + + TESTING("unlinking external link in compact group"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + + /* Create first file, with external link to object in second file */ + if((fid = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Create external link */ + if(H5Lcreate_external(filename2, "/dst", fid, "src", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Create second file to point to */ + if((fid = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Create object to link to */ + if((gid = H5Gcreate(fid, "dst", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + +/* Unlink external link */ + + /* Open first file */ + if((fid = H5Fopen(filename1, H5F_ACC_RDWR, fapl)) < 0) TEST_ERROR + + /* Unlink external link */ + if(H5Gunlink(fid, "src") < 0) TEST_ERROR + + /* Close first file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Open second file */ + if((fid = H5Fopen(filename2, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + + /* Open group for external link */ + if((gid = H5Gopen(fid, "dst")) < 0) TEST_ERROR + + /* Close group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gid2); + H5Gclose(gid); + H5Fclose(fid); + } H5E_END_TRY; + return -1; +} /* end external_link_unlink_compact() */ + + +/*------------------------------------------------------------------------- + * Function: external_link_unlink_dense + * + * Purpose: Remove an external link (from a dense group) + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Wednesday, January 18, 2006 + * + *------------------------------------------------------------------------- + */ +#ifdef H5_GROUP_REVISION +static int +external_link_unlink_dense(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gcpl = (-1); /* Group creation property list ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + char objname[NAME_BUF_SIZE]; /* Object name */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE]; /* Names of files to externally link across */ + unsigned nmsgs; /* Number of messages in group's header */ + unsigned max_compact; /* Maximum # of links to store in group compactly */ + unsigned min_dense; /* Minimum # of links to store in group "densely" */ + unsigned u; /* Local index variable */ + + TESTING("unlinking external link in dense group"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + + /* Create first file, with external link to object in second file */ + if((fid = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Open root group */ + if((gid = H5Gopen(fid, "/")) < 0) TEST_ERROR + + /* Check on root group's status */ + if(H5G_is_empty_test(gid) != TRUE) TEST_ERROR + + /* Query the group creation properties */ + if((gcpl = H5Gget_create_plist(gid)) < 0) TEST_ERROR + if(H5Pget_link_phase_change(gcpl, &max_compact, &min_dense) < 0) TEST_ERROR + + /* Create external link */ + /* (This also covers the case of having an external link in a compact group that's converted to a dense group) */ + if(H5Lcreate_external(filename2, "/dst", gid, "src", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Check on root group's status */ + if(H5G_is_empty_test(gid) == TRUE) TEST_ERROR; + if(H5G_has_links_test(gid, &nmsgs) != TRUE) TEST_ERROR; + if(nmsgs != 1) TEST_ERROR; + if(H5G_has_stab_test(gid) == TRUE) TEST_ERROR; + + /* Create enough objects in the root group to change it into a "dense" group */ + for(u = 0; u < max_compact; u++) { + sprintf(objname, "filler %u\n", u); + if((gid2 = H5Gcreate(gid, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid2) < 0) TEST_ERROR + } /* end for */ + + /* Check on root group's status */ + if(H5G_is_empty_test(gid) == TRUE) TEST_ERROR; + if(H5G_has_links_test(gid, NULL) == TRUE) TEST_ERROR; + if(H5G_has_stab_test(gid) != TRUE) TEST_ERROR; + + /* Close group creation property list */ + if(H5Pclose(gcpl) < 0) TEST_ERROR + + /* Close root group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Create second file to point to */ + if((fid = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Create object to link to */ + if((gid = H5Gcreate(fid, "dst", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + +/* Unlink external link */ + + /* Open first file */ + if((fid = H5Fopen(filename1, H5F_ACC_RDWR, fapl)) < 0) TEST_ERROR + + /* Open root group */ + if((gid = H5Gopen(fid, "/")) < 0) TEST_ERROR + + /* Unlink external link */ + if(H5Gunlink(fid, "src") < 0) TEST_ERROR + + /* Remove enough objects in the root group to change it into a "compact" group */ + for(u = 0; u < ((max_compact - min_dense) + 1); u++) { + sprintf(objname, "filler %u\n", u); + if(H5Gunlink(gid, objname) < 0) TEST_ERROR + } /* end for */ + + /* Check on root group's status */ + if(H5G_is_empty_test(gid) == TRUE) TEST_ERROR; + if(H5G_has_links_test(gid, &nmsgs) != TRUE) TEST_ERROR; + if(nmsgs != (min_dense - 1)) TEST_ERROR; + if(H5G_has_stab_test(gid) == TRUE) TEST_ERROR; + + /* Close root group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close first file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Open second file */ + if((fid = H5Fopen(filename2, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + + /* Open group for external link (should be unaffected) */ + if((gid = H5Gopen(fid, "dst")) < 0) TEST_ERROR + + /* Close group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gid2); + H5Gclose(gid); + H5Fclose(fid); + } H5E_END_TRY; + return -1; +} /* end external_link_unlink_dense() */ +#endif /* H5_GROUP_REVISION */ + + +/*------------------------------------------------------------------------- + * Function: external_link_move + * + * Purpose: Move/rename external link + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Monday, December 5, 2005 + * + *------------------------------------------------------------------------- + */ +static int +external_link_move(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE]; /* Names of files to externally link across */ + + TESTING("move external link"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + + /* Create first file, with external link to object in second file */ + if((fid = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Create external link */ + if(H5Lcreate_external(filename2, "/dst", fid, "src", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Create second file to point to */ + if((fid = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Create object to link to */ + if((gid = H5Gcreate(fid, "dst", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + +/* Move external link to different name within same group */ + + /* Open first file */ + if((fid = H5Fopen(filename1, H5F_ACC_RDWR, fapl)) < 0) TEST_ERROR + + /* Move external link within same group */ + if(H5Gmove(fid, "src", "src2") < 0) TEST_ERROR + + /* Open object through external link */ + if((gid = H5Gopen(fid, "src2")) < 0) TEST_ERROR + + /* Check name */ + if((name_len = H5Iget_name(gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in external file */ + if((gid2 = H5Gcreate(gid, "new_group", (size_t)0)) < 0) TEST_ERROR + + /* Close group in external file */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close external object */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close first file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Open second file */ + if((fid = H5Fopen(filename2, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + + /* Open group created through external link */ + if((gid = H5Gopen(fid, "dst/new_group")) < 0) TEST_ERROR + + /* Close group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + +/* Move external link to different group */ + + /* Open first file */ + if((fid = H5Fopen(filename1, H5F_ACC_RDWR, fapl)) < 0) TEST_ERROR + + /* Create another group, to move the external link into */ + if((gid = H5Gcreate(fid, "group2", (size_t)0)) < 0) TEST_ERROR + + /* Move external link to different group */ + if(H5Gmove2(fid, "src2", gid, "src3") < 0) TEST_ERROR + + /* Close new group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Open object through external link */ + if((gid = H5Gopen(fid, "/group2/src3")) < 0) TEST_ERROR + + /* Check name */ + if((name_len = H5Iget_name(gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in external file */ + if((gid2 = H5Gcreate(gid, "new_group2", (size_t)0)) < 0) TEST_ERROR + + /* Close group in external file */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close external object */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close first file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Open second file */ + if((fid = H5Fopen(filename2, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + + /* Open group created through external link */ + if((gid = H5Gopen(fid, "dst/new_group2")) < 0) TEST_ERROR + + /* Close group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + +/* Move external link back to original group */ + + /* Open first file */ + if((fid = H5Fopen(filename1, H5F_ACC_RDWR, fapl)) < 0) TEST_ERROR + + /* Open object through external link */ + if((gid = H5Gopen(fid, "/group2/src3")) < 0) TEST_ERROR + + /* Check name */ + if((name_len = H5Iget_name(gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Move external link back to original location */ + if(H5Gmove(fid, "/group2/src3", "/src") < 0) TEST_ERROR + + /* Check name */ + if((name_len = H5Iget_name(gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in external file */ + if((gid2 = H5Gcreate(gid, "new_group3", (size_t)0)) < 0) TEST_ERROR + + /* Close group in external file */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close external object */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close first file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Open second file */ + if((fid = H5Fopen(filename2, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + + /* Open group created through external link */ + if((gid = H5Gopen(fid, "dst/new_group3")) < 0) TEST_ERROR + + /* Close group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gid2); + H5Gclose(gid); + H5Fclose(fid); + } H5E_END_TRY; + return -1; +} /* end external_link_move() */ + + +#ifdef H5_GROUP_REVISION +/*------------------------------------------------------------------------- + * Function: external_link_ride + * + * Purpose: Let an external link "come along for the ride" when a group is + * converted between compact & dense forms. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Wednesday, January 18, 2006 + * + *------------------------------------------------------------------------- + */ +static int +external_link_ride(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gcpl = (-1); /* Group creation property list ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE]; /* Names of files to externally link across */ + unsigned nmsgs; /* Number of messages in group's header */ + unsigned max_compact; /* Maximum # of links to store in group compactly */ + unsigned min_dense; /* Minimum # of links to store in group "densely" */ + unsigned u; /* Local index variable */ + + TESTING("external link along for the ride"); + + /* Set up filenames */ + h5_fixname(FILENAME[3], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[4], fapl, filename2, sizeof filename2); + + /* Create first file, with external link to object in second file */ + if((fid = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Open root group */ + if((gid = H5Gopen(fid, "/")) < 0) TEST_ERROR + + /* Check on root group's status */ + if(H5G_is_empty_test(gid) != TRUE) TEST_ERROR + + /* Query the group creation properties */ + if((gcpl = H5Gget_create_plist(gid)) < 0) TEST_ERROR + if(H5Pget_link_phase_change(gcpl, &max_compact, &min_dense) < 0) TEST_ERROR + + /* Create enough objects in the root group to change it into a "dense" group */ + for(u = 0; u < (max_compact + 1); u++) { + sprintf(objname, "filler %u\n", u); + if((gid2 = H5Gcreate(gid, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid2) < 0) TEST_ERROR + } /* end for */ + + /* Check on root group's status */ + if(H5G_is_empty_test(gid) == TRUE) TEST_ERROR; + if(H5G_has_links_test(gid, NULL) == TRUE) TEST_ERROR; + if(H5G_has_stab_test(gid) != TRUE) TEST_ERROR; + + /* Create external link */ + /* (This also covers the case of adding an external link to a dense group) */ + if(H5Lcreate_external(filename2, "/dst", gid, "src", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Check on root group's status */ + if(H5G_is_empty_test(gid) == TRUE) TEST_ERROR; + if(H5G_has_links_test(gid, NULL) == TRUE) TEST_ERROR; + if(H5G_has_stab_test(gid) != TRUE) TEST_ERROR; + + /* Close group creation property list */ + if(H5Pclose(gcpl) < 0) TEST_ERROR + + /* Close root group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Create second file to point to */ + if((fid = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Create object to link to */ + if((gid = H5Gcreate(fid, "dst", (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + +/* Remove enough objects to convert group containing external link back into compact form */ + + /* Open first file */ + if((fid = H5Fopen(filename1, H5F_ACC_RDWR, fapl)) < 0) TEST_ERROR + + /* Open object through external link */ + if((gid = H5Gopen(fid, "src")) < 0) TEST_ERROR + + /* Check name */ + if((name_len = H5Iget_name(gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in external file */ + if((gid2 = H5Gcreate(gid, "new_group", (size_t)0)) < 0) TEST_ERROR + + /* Close group in external file */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close external object */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Open root group */ + if((gid = H5Gopen(fid, "/")) < 0) TEST_ERROR + + /* Remove enough objects in the root group to change it into a "compact" group */ + for(u = 0; u < ((max_compact - min_dense) + 3); u++) { + sprintf(objname, "filler %u\n", u); + if(H5Gunlink(gid, objname) < 0) TEST_ERROR + } /* end for */ + + /* Check on root group's status */ + if(H5G_is_empty_test(gid) == TRUE) TEST_ERROR; + if(H5G_has_links_test(gid, &nmsgs) != TRUE) TEST_ERROR; + if(nmsgs != (min_dense - 1)) TEST_ERROR; + if(H5G_has_stab_test(gid) == TRUE) TEST_ERROR; + + /* Close root group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Open object through external link */ + if((gid = H5Gopen(fid, "src")) < 0) TEST_ERROR + + /* Check name */ + if((name_len = H5Iget_name(gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in external file */ + if((gid2 = H5Gcreate(gid, "new_group2", (size_t)0)) < 0) TEST_ERROR + + /* Close group in external file */ + if(H5Gclose(gid2) < 0) TEST_ERROR + + /* Close external object */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close first file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + /* Open second file */ + if((fid = H5Fopen(filename2, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR + + /* Open group created through external link */ + if((gid = H5Gopen(fid, "dst/new_group")) < 0) TEST_ERROR + + /* Close group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Open group created through external link */ + if((gid = H5Gopen(fid, "dst/new_group2")) < 0) TEST_ERROR + + /* Close group */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Pclose(gcpl); + H5Gclose(gid2); + H5Gclose(gid); + H5Fclose(fid); + } H5E_END_TRY; + return -1; +} /* end external_link_ride() */ +#endif /* H5_GROUP_REVISION */ + + +/*------------------------------------------------------------------------- + * Function: ext_link_endian + * + * Purpose: Check that external links work properly when they are + * moved from big-endian to little-endian systems and + * vice versa. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: James Laird + * Tuesday, June 6, 2006 + * + *------------------------------------------------------------------------- + */ +static int +ext_link_endian(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + hid_t lapl_id = (-1); /* Prop List ID */ + char * srcdir = getenv("srcdir"); /* The source directory */ + char pathbuf[NAME_BUF_SIZE]; /* Path to the files */ + char namebuf[NAME_BUF_SIZE]; + + TESTING("endianness of external links"); + + /* + * Create the name of the file to open (in case we are using the --srcdir + * option and the file is in a different directory from this test). + */ + if (srcdir && ((HDstrlen(srcdir) + 2) < sizeof(pathbuf)) ) + { + HDstrcpy(pathbuf, srcdir); + HDstrcat(pathbuf, "/"); + } + else + HDstrcpy(pathbuf, ""); + + /* Create a link access property list with the path to the srcdir */ + if((lapl_id = H5Pcreate(H5P_LINK_ACCESS)) < 0) TEST_ERROR; + if(H5Pinsert(lapl_id, H5L_ELINK_PREFIX_PROP, strlen(pathbuf) + 1, pathbuf, + NULL, NULL, NULL, NULL, NULL, NULL) < 0) TEST_ERROR; + + if(HDstrlen(pathbuf) + HDstrlen(LE_FILENAME) >= sizeof(namebuf)) TEST_ERROR; + + HDstrcpy(namebuf, pathbuf); + HDstrcat(namebuf, LE_FILENAME); + + /* Test LE file; try to open a group through the external link */ + if((fid = H5Fopen(namebuf, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR; + if((gid = H5Oopen(fid, "ext_link", lapl_id)) < 0) TEST_ERROR; + + /* Open a group in the external file using that group ID */ + if((gid2 = H5Gopen(gid, "subgroup")) < 0) TEST_ERROR; + + /* Close the IDs */ + if(H5Gclose(gid2) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + if(H5Fclose(fid) < 0) TEST_ERROR; + + if(HDstrlen(pathbuf) + HDstrlen(BE_FILENAME) >= sizeof(namebuf)) TEST_ERROR; + + HDstrcpy(namebuf, pathbuf); + HDstrcat(namebuf, BE_FILENAME); + + /* Test BE file; try to open a group through the external link */ + if((fid = H5Fopen(namebuf, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR; + if((gid = H5Oopen(fid, "ext_link", lapl_id)) < 0) TEST_ERROR; + + /* Open a group in the external file using that group ID */ + if((gid2 = H5Gopen(gid, "subgroup")) < 0) TEST_ERROR; + + /* Close the IDs */ + if(H5Gclose(gid2) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + if(H5Fclose(fid) < 0) TEST_ERROR; + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gid2); + H5Gclose(gid); + H5Fclose(fid); + } H5E_END_TRY; + return -1; +} + +/*------------------------------------------------------------------------- + * Function: ud_hard_links + * + * Purpose: Check that the functionality of hard links can be duplicated + * with user-defined links. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: James Laird + * Tuesday, June 6, 2006 + * + *------------------------------------------------------------------------- + */ +/* Callback functions for UD hard links. */ +/* UD_hard_create increments the object's reference count */ +static herr_t UD_hard_create(const char UNUSED * link_name, hid_t loc_group, void * udata, size_t udata_size, hid_t UNUSED lcpl_id) +{ + haddr_t addr; + hid_t target_obj = -1; + herr_t ret_value = 0; + + if(udata_size != sizeof(haddr_t)) + { + ret_value = -1; + goto done; + } + + addr = *((haddr_t *) udata); + + /* Open the object this link points to */ + target_obj= H5Oopen_by_addr(loc_group, addr); + if(target_obj < 0) + { + ret_value = -1; + goto done; + } + + /* Increment the reference count of the target object */ + if(H5Oincr_refcount(target_obj) < 0) + { + ret_value = -1; + goto done; + } + +done: + /* Close the target object if we opened it */ + if(target_obj >= 0) + { + switch(H5Iget_type(target_obj)) + { + case H5I_GROUP: + if(H5Gclose(target_obj) <0) + ret_value = -1; + break; + case H5I_DATASET: + if(H5Dclose(target_obj) <0) + ret_value = -1; + break; + case H5I_DATATYPE: + if(H5Tclose(target_obj) <0) + ret_value = -1; + break; + default: + return -1; + } + } + + return ret_value; +} + +/* UD_hard_delete decrements the object's reference count */ +static herr_t UD_hard_delete(const char UNUSED * link_name, hid_t loc_group, void * udata, size_t udata_size) +{ + haddr_t addr; + hid_t target_obj = -1; + herr_t ret_value = 0; + + if(udata_size != sizeof(haddr_t)) + { + ret_value = -1; + goto done; + } + + addr = *((haddr_t *) udata); + + /* Open the object this link points to */ + target_obj= H5Oopen_by_addr(loc_group, addr); + if(target_obj < 0) + { + ret_value = -1; + goto done; + } + + /* Decrement the reference count of the target object */ + if(H5Odecr_refcount(target_obj) < 0) + { + ret_value = -1; + goto done; + } + +done: + /* Close the target object if we opened it */ + if(target_obj >= 0) + { + switch(H5Iget_type(target_obj)) + { + case H5I_GROUP: + if(H5Gclose(target_obj) <0) + ret_value = -1; + break; + case H5I_DATASET: + if(H5Dclose(target_obj) <0) + ret_value = -1; + break; + case H5I_DATATYPE: + if(H5Tclose(target_obj) <0) + ret_value = -1; + break; + default: + return -1; + } + } + + return ret_value; +} + +static hid_t UD_hard_traverse(const char UNUSED *link_name, hid_t cur_group, void * udata, size_t udata_size, hid_t UNUSED lapl_id) +{ + haddr_t addr; + hid_t ret_value = -1; + + if(udata_size != sizeof(haddr_t)) + return -1; + + addr = *((haddr_t *) udata); + + ret_value = H5Oopen_by_addr(cur_group, addr); /* If this fails, our return value will be negative. */ + + return ret_value; +} + +const H5L_link_class_t UD_hard_class[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + UD_HARD_TYPE, /* Link type id number */ + "UD_hard_link", /* Link class name for debugging */ + UD_hard_create, /* Creation callback */ + NULL, /* Move/rename callback */ + NULL, /* Copy callback */ + UD_hard_traverse, /* The actual traversal function */ + UD_hard_delete, /* Deletion callback */ + NULL /* Query callback */ +}}; + +static int +ud_hard_links(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + H5L_linkinfo_t li; /* Link information */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + h5_stat_size_t empty_size; /* Size of an empty file */ + char filename[NAME_BUF_SIZE]; + + TESTING("user-defined hard link"); + + /* Set up filename and create file*/ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Get the size of the empty file for reference */ + if(H5Fclose(fid) < 0) TEST_ERROR; + if((empty_size=h5_get_file_size(filename))==0) TEST_ERROR; + + if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Check that external links are registered and UD hard links are not */ + if(H5Lis_registered(H5L_LINK_EXTERNAL) != TRUE) TEST_ERROR + if(H5Lis_registered(UD_HARD_TYPE) != 0) TEST_ERROR + + /* Register "user-defined hard links" with the library */ + if(H5Lregister(UD_hard_class) < 0) TEST_ERROR; + + /* Check that UD hard links are now registered */ + if(H5Lis_registered(H5L_LINK_EXTERNAL) != TRUE) TEST_ERROR + if(H5Lis_registered(UD_HARD_TYPE) != TRUE) TEST_ERROR + + /* Create a group for the UD hard link to point to */ + if((gid = H5Gcreate(fid, "group", 0)) <0) TEST_ERROR; + + /* Get address for the group to give to the hard link */ + if (H5Lget_linkinfo(fid, "group", &li, H5P_DEFAULT)<0) TEST_ERROR; + + if(H5Gclose(gid) < 0) TEST_ERROR; + + + /* Create a user-defined "hard link" to the group using the address we got + * from H5Lget_linkinfo */ + if(H5Lcreate_ud(fid, "ud_link", UD_HARD_TYPE, &(li.u.address), sizeof(haddr_t), H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Close and re-open file to ensure that data is written to disk */ + if(H5Fclose(fid) < 0) TEST_ERROR; + if((fid = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) TEST_ERROR; + + /* Open group through UD link */ + if((gid = H5Gopen(fid, "ud_link")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in group */ + if((gid2 = H5Gcreate(gid, "new_group", (size_t)0)) < 0) TEST_ERROR + + /* Close groups*/ + if(H5Gclose(gid2) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Re-open group without using ud link to check that it was created properly */ + if((gid = H5Gopen(fid, "group/new_group")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(HDstrcmp(objname, "/group/new_group")) TEST_ERROR + + /* Close opened object */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Check that H5Gget_objinfo works on the hard link */ + if(H5Lget_linkinfo(fid, "ud_link", &li, H5P_DEFAULT) < 0) TEST_ERROR + /* UD hard links have no query function, thus return a "link length" of 0 */ + if(li.u.link_size != 0) TEST_ERROR + if (UD_HARD_TYPE != li.linkclass) { + H5_FAILED(); + puts(" Unexpected link class - should have been a UD hard link"); + goto error; + } + + /* Unlink the group pointed to by the UD link. It shouldn't be + * deleted because of the UD link. */ + if(H5Gunlink(fid, "/group") < 0) TEST_ERROR; + + /* Ensure we can open the group through the UD link */ + if((gid = H5Gopen(fid, "ud_link")) < 0) TEST_ERROR; + + /* Unlink the group contained within it. */ + if(H5Gunlink(gid, "new_group") < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Now delete the UD link. This should cause the group to be + * deleted, too. */ + if(H5Gunlink(fid, "ud_link")<0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + /* The file should be empty again. */ + if(empty_size!=h5_get_file_size(filename)) TEST_ERROR; + + if(H5Lunregister(UD_HARD_TYPE) < 0) TEST_ERROR + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose (gid2); + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end ud_hard_links() */ + + +/*------------------------------------------------------------------------- + * Function: ext_link_endian + * + * Purpose: Check that user defined link types can be unregistered and + * reregistered properly. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: James Laird + * Tuesday, June 6, 2006 + * + *------------------------------------------------------------------------- + */ + /* A traversal function that ignores any udata and simply opens an object + * in the current group named REREG_TARGET_NAME + */ +static hid_t UD_rereg_traverse(const char UNUSED * link_name, hid_t cur_group, void UNUSED * udata, size_t UNUSED udata_size, hid_t lapl_id) +{ + hid_t ret_value; + + if((ret_value = H5Oopen(cur_group, REREG_TARGET_NAME, lapl_id)) < 0) TEST_ERROR; + + return ret_value; + +error: + return -1; +} + +/* This link class has the same ID number as the UD hard links but + * has a very different traversal function */ +const H5L_link_class_t UD_rereg_class[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + UD_HARD_TYPE, /* Link type id number */ + "UD_reregistered_type", /* Link class name for debugging */ + NULL, /* Creation callback */ + NULL, /* Move/rename callback */ + NULL, /* Copy callback */ + UD_rereg_traverse, /* The actual traversal function */ + NULL, /* Deletion callback */ + NULL /* Query callback */ +}}; + +static int +ud_link_reregister(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + H5L_linkinfo_t li; /* Link information */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + char filename[NAME_BUF_SIZE]; + h5_stat_size_t empty_size; /* Size of an empty file */ + + TESTING("registering a new class for existing UD links"); + + /* Set up filename and create file*/ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Get the size of the empty file for reference */ + if(H5Fclose(fid) < 0) TEST_ERROR; + if((empty_size=h5_get_file_size(filename))==0) TEST_ERROR; + + if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Check that UD hard links are not registered */ + if(H5Lis_registered(UD_HARD_TYPE) != 0) TEST_ERROR + + /* Register "user-defined hard links" with the library */ + if(H5Lregister(UD_hard_class) < 0) TEST_ERROR; + + /* Check that UD hard links are registered */ + if(H5Lis_registered(UD_HARD_TYPE) != TRUE) TEST_ERROR + + /* Point a UD defined hard link to a group in the same way as the previous test */ + if((gid = H5Gcreate(fid, "group", 0)) <0) TEST_ERROR; + if (H5Lget_linkinfo(fid, "group", &li, H5P_DEFAULT)<0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + if(H5Lcreate_ud(fid, "ud_link", UD_HARD_TYPE, &(li.u.address), + sizeof(li.u.address), H5P_DEFAULT, H5P_DEFAULT) < 0) + TEST_ERROR; + + /* Create a group named REREG_TARGET_NAME in the same group as the ud link */ + if((gid = H5Gcreate(fid, REREG_TARGET_NAME, 0)) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Now unregister UD hard links */ + if(H5Lunregister(UD_HARD_TYPE) < 0) TEST_ERROR; + + /* Check that UD hard links are no longer registered */ + if(H5Lis_registered(UD_HARD_TYPE) != 0) TEST_ERROR + + /* Verify that we can't traverse the ud link anymore */ + H5E_BEGIN_TRY { + if((gid = H5Gopen(fid, "ud_link")) >= 0) TEST_ERROR; + } H5E_END_TRY + + /* Verify that we can't create any new links of this type */ + H5E_BEGIN_TRY { + if(H5Lcreate_ud(fid, "ud_link2", UD_HARD_TYPE, &(li.u.address), + sizeof(li.u.address), H5P_DEFAULT, H5P_DEFAULT) >= 0) + TEST_ERROR; + } H5E_END_TRY + + /* Register a new kind of link with the same ID number */ + if(H5Lregister(UD_rereg_class) < 0) TEST_ERROR; + + /* Check that UD hard links are registered again */ + if(H5Lis_registered(UD_HARD_TYPE) != TRUE) TEST_ERROR + + /* Open a group through the ud link (now a different class of link). + * It should be a different group + * than the UD hard link pointed to */ + if((gid = H5Gopen(fid, "ud_link")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(name_len != 0) TEST_ERROR + + /* Create object in group */ + if((gid2 = H5Gcreate(gid, "new_group", (size_t)0)) < 0) TEST_ERROR + + /* Close groups*/ + if(H5Gclose(gid2) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Re-open group without using ud link to check that it was created properly */ + if((gid = H5Gopen(fid, "rereg_target/new_group")) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(HDstrcmp(objname, "/rereg_target/new_group")) TEST_ERROR + + /* Close opened object */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Unlink the group pointed to by the UD hard link. It shouldn't be + * deleted because the UD link incremented its reference count. */ + if(H5Gunlink(fid, "/group") < 0) TEST_ERROR; + + /* What a mess! Re-register user-defined links to clean up the + * reference counts. We shouldn't actually need to unregister the + * other link type */ + if(H5Lregister(UD_hard_class) < 0) TEST_ERROR; + if(H5Lis_registered(UD_HARD_TYPE) != TRUE) TEST_ERROR + + /* Ensure we can open the group through the UD link (now that UD hard + * links have been registered) */ + if((gid = H5Gopen(fid, "ud_link")) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Delete the UD hard link. This should cause the group to be + * deleted, too. */ + if(H5Gunlink(fid, "ud_link")<0) TEST_ERROR; + + /* Unlink the other two groups so that we can make sure the file is empty */ + if(H5Gunlink(fid, "/rereg_target/new_group")<0) TEST_ERROR; + if(H5Gunlink(fid, REREG_TARGET_NAME)<0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + /* The file should be empty again. */ + if(empty_size!=h5_get_file_size(filename)) TEST_ERROR; + + if(H5Lunregister(UD_HARD_TYPE) < 0) TEST_ERROR + if(H5Lis_registered(UD_HARD_TYPE) != 0) TEST_ERROR + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose (gid2); + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end ud_link_reregister() */ + + +/*------------------------------------------------------------------------- + * Function: ud_callbacks + * + * Purpose: Check that all callbacks are called and are given the correct + * information. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: James Laird + * Tuesday, June 6, 2006 + * + *------------------------------------------------------------------------- + */ +/* Callback functions for UD "callback" links. */ +/* Creation callback. Called during move as well. */ +herr_t UD_cb_create(const char * link_name, hid_t loc_group, void * udata, size_t udata_size, hid_t lcpl_id) +{ + if(!link_name) TEST_ERROR; + if(loc_group < 0) TEST_ERROR; + if(udata_size > 0 && !udata) TEST_ERROR; + if(lcpl_id < 0) TEST_ERROR; + + if(strcmp(link_name, UD_CB_LINK_NAME) && strcmp(link_name, NEW_UD_CB_LINK_NAME)) TEST_ERROR; + if(strcmp(udata, UD_CB_TARGET)) TEST_ERROR; + if(udata_size != UD_CB_TARGET_LEN) TEST_ERROR; + + return 0; + +error: + return -1; +} +static hid_t UD_cb_traverse(const char * link_name, hid_t cur_group, void * udata, size_t udata_size, hid_t lapl_id) +{ + const char *target = (char *) udata; + hid_t ret_value; + + if(!link_name) TEST_ERROR; + if(cur_group < 0) TEST_ERROR; + if(udata_size > 0 && !udata) TEST_ERROR; + + if(strcmp(link_name, UD_CB_LINK_NAME) && strcmp(link_name, NEW_UD_CB_LINK_NAME)) TEST_ERROR; + if(strcmp(udata, UD_CB_TARGET)) TEST_ERROR; + if(udata_size != UD_CB_TARGET_LEN) TEST_ERROR; + + if((ret_value = H5Oopen(cur_group, target, lapl_id)) < 0) + TEST_ERROR; + + return ret_value; + +error: + return -1; +} +/* Callback for when the link is moved or renamed */ +herr_t UD_cb_move(const char * new_name, hid_t new_loc, void * udata, size_t udata_size) +{ + const char *target = (char *) udata; + + if(!new_name) TEST_ERROR; + if(new_loc < 0) TEST_ERROR; + if(udata_size > 0 && !udata) TEST_ERROR; + + if(strcmp(new_name, NEW_UD_CB_LINK_NAME)) TEST_ERROR; + if(strcmp(udata, UD_CB_TARGET)) TEST_ERROR; + if(udata_size != UD_CB_TARGET_LEN) TEST_ERROR; + + return 0; + +error: + return -1; +} +/* Callback for when the link is deleted. Also called during move */ +herr_t UD_cb_delete(const char * link_name, hid_t loc_group, void * udata, size_t udata_size) +{ + if(!link_name) TEST_ERROR; + if(loc_group < 0) TEST_ERROR; + if(udata_size > 0 && !udata) TEST_ERROR; + + if(strcmp(link_name, UD_CB_LINK_NAME) && strcmp(link_name, NEW_UD_CB_LINK_NAME)) TEST_ERROR; + if(strcmp(udata, UD_CB_TARGET)) TEST_ERROR; + if(udata_size != UD_CB_TARGET_LEN) TEST_ERROR; + + return 0; + +error: + return -1; +} +/* Callback for when the link is queried */ +ssize_t UD_cb_query(const char * link_name, void * udata, size_t udata_size, void* buf, size_t buf_size) +{ + if(!link_name) TEST_ERROR; + if(udata_size > 0 && !udata) TEST_ERROR; + + if(strcmp(link_name, UD_CB_LINK_NAME)) TEST_ERROR; + if(strcmp(udata, UD_CB_TARGET)) TEST_ERROR; + if(udata_size != UD_CB_TARGET_LEN) TEST_ERROR; + + if(buf) + { + if(buf_size < 16) TEST_ERROR; + strcpy(buf, "query succeeded"); + } + + /* There are 15 characters and a NULL in "query succeeded" */ + return 16; + +error: + return -1; +} + +const H5L_link_class_t UD_cb_class[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + UD_CB_TYPE, /* Link type id number */ + NULL, /* NULL name (to make sure this doesn't break anything */ + UD_cb_create, /* Creation callback */ + UD_cb_move, /* Move/rename callback */ + UD_cb_move, /* Copy callback */ + UD_cb_traverse, /* The actual traversal function */ + UD_cb_delete, /* Deletion callback */ + UD_cb_query /* Query callback */ +}}; + +static int +ud_callbacks(fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1); /* Group ID */ + hid_t lcpl = (-1); /* Link Creation PL */ + H5G_stat_t sb; /* Object information */ + H5L_linkinfo_t li; /* Link information */ + char ud_target_name[] = UD_CB_TARGET; /* Link target name */ + char filename[NAME_BUF_SIZE]; + char query_buf[NAME_BUF_SIZE]; + + TESTING("user-defined link callbacks"); + + /* Set up filename and create file*/ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Check that registered link classes are, and unregistered ones aren't */ + if(H5Lis_registered(H5L_LINK_EXTERNAL) != TRUE) TEST_ERROR + if(H5Lis_registered(UD_HARD_TYPE) != 0) TEST_ERROR + if(H5Lis_registered(UD_CB_TYPE) != 0) TEST_ERROR + + /* Hit two birds with one stone: register UD hard links from previous + * test to check that having two UD links registered at once presents + * no problems. */ + if(H5Lregister(UD_hard_class) < 0) TEST_ERROR; + + /* Register user-defined link class. This is the one we'll actually + * be using. */ + if(H5Lregister(UD_cb_class) < 0) TEST_ERROR; + + /* Check that registered link classes are, and unregistered ones aren't */ + if(H5Lis_registered(H5L_LINK_EXTERNAL) != TRUE) TEST_ERROR + if(H5Lis_registered(UD_HARD_TYPE) != TRUE) TEST_ERROR + if(H5Lis_registered(UD_CB_TYPE) != TRUE) TEST_ERROR + + /* Create a group for the UD link to point to */ + if((gid = H5Gcreate(fid, UD_CB_TARGET, 0)) <0) TEST_ERROR; + + /* Create a user-defined link to the group. These UD links behave like soft links. */ + if(H5Lcreate_ud(fid, UD_CB_LINK_NAME, UD_CB_TYPE, ud_target_name, UD_CB_TARGET_LEN, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Try opening group through UD link */ + if((gid = H5Gopen(fid, UD_CB_LINK_NAME)) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Query the link to test its query callback */ + if (H5Lget_linkinfo(fid, UD_CB_LINK_NAME, &li, H5P_DEFAULT)<0) TEST_ERROR; + if(li.u.link_size != 16) TEST_ERROR; + if (UD_CB_TYPE != li.linkclass) { + H5_FAILED(); + puts(" Unexpected link class - should have been a UD hard link"); + goto error; + } + + /* Fill the query buffer */ + if(H5Gget_linkval(fid, UD_CB_LINK_NAME, NAME_BUF_SIZE, query_buf) < 0) TEST_ERROR; + if(strcmp(query_buf, "query succeeded") != 0) TEST_ERROR; + + /* Move the link */ + if(H5Gmove(fid, UD_CB_LINK_NAME, NEW_UD_CB_LINK_NAME) < 0) TEST_ERROR; + + /* Re-open group to ensure that move worked */ + if((gid = H5Gopen(fid, NEW_UD_CB_LINK_NAME)) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Remove UD link */ + if(H5Gunlink(fid, NEW_UD_CB_LINK_NAME) < 0) TEST_ERROR; + + + /* Test that the callbacks don't work if the link class is not registered */ + + /* Create a new link. Just for fun, give it a non-default character + * encoding (to test that LAPLs work) */ + if((lcpl = H5Pcreate(H5P_LINK_CREATE)) < 0) TEST_ERROR +#ifdef H5_GROUP_REVISION + if(H5Pset_char_encoding(lcpl, H5T_CSET_UTF8) < 0) TEST_ERROR +#endif /* H5_GROUP_REVISION */ + if(H5Lcreate_ud(fid, UD_CB_LINK_NAME, UD_CB_TYPE, ud_target_name, UD_CB_TARGET_LEN, lcpl, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Pclose(lcpl)<0) TEST_ERROR + + /* Check its character encoding */ +#ifdef H5_GROUP_REVISION + if(H5Lget_linkinfo(fid, UD_CB_LINK_NAME, &li, H5P_DEFAULT) < 0) TEST_ERROR; + if(li.cset != H5T_CSET_UTF8) TEST_ERROR; +#endif /* H5_GROUP_REVISION */ + + /* Unregister the link class so the library forgets what its callbacks do */ + if(H5Lunregister(UD_CB_TYPE) < 0) TEST_ERROR; + + /* Now test that each of the callbacks fails */ + H5E_BEGIN_TRY { + if(H5Lcreate_ud(fid, NEW_UD_CB_LINK_NAME, UD_CB_TYPE, ud_target_name, UD_CB_TARGET_LEN, H5P_DEFAULT, H5P_DEFAULT) >= 0) TEST_ERROR; + if(H5Gmove(fid, UD_CB_LINK_NAME, NEW_UD_CB_LINK_NAME) >= 0) TEST_ERROR; + if(H5Gunlink(fid, UD_CB_LINK_NAME) >= 0) TEST_ERROR; + if((gid = H5Gopen(gid, UD_CB_LINK_NAME)) >= 0) TEST_ERROR; + if(H5Gunlink(fid, UD_CB_LINK_NAME) >= 0) TEST_ERROR; + } H5E_END_TRY + + /* The query callback should NOT fail, but should be unable to give a linklen */ + if(H5Lget_linkinfo(fid, UD_CB_LINK_NAME, &li, H5P_DEFAULT) <0) TEST_ERROR; + if(li.u.link_size != 0) TEST_ERROR; + if(li.linkclass != UD_CB_TYPE) TEST_ERROR; + if(H5Gget_objinfo(fid, UD_CB_LINK_NAME, FALSE, &sb) <0) TEST_ERROR; + if(sb.type != H5G_UDLINK) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Pclose (lcpl); + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end ud_callbacks() */ + + +/*------------------------------------------------------------------------- + * Function: lapl_udata + * + * Purpose: Check that information can be passed to UD links using the + * Link Access Property List. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: James Laird + * Tuesday, June 6, 2006 + * + *------------------------------------------------------------------------- + */ +static hid_t +UD_plist_traverse(const char UNUSED * link_name, hid_t cur_group, void UNUSED * udata, size_t udata_size, hid_t lapl_id) +{ + char target[NAME_BUF_SIZE]; + hid_t ret_value; + + if(udata_size != 0) TEST_ERROR; + + /* Get the name of the target from the property list. */ + if(H5Pget(lapl_id, DEST_PROP_NAME, target) < 0) TEST_ERROR; + + if((ret_value = H5Oopen(cur_group, target, lapl_id)) < 0) + TEST_ERROR; + + return ret_value; + +error: + return -1; +} +const H5L_link_class_t UD_plist_class[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + UD_PLIST_TYPE, /* Link type id number */ + "UD_plist_link", /* Link class name for debugging */ + NULL, /* Creation callback */ + NULL, /* Move/rename callback */ + NULL, /* Copy callback */ + UD_plist_traverse, /* The actual traversal function */ + NULL, /* Deletion callback */ + NULL /* Query callback */ +}}; + +static int +lapl_udata(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + hid_t plist_id = (-1); /* Property List ID */ + char group_a_name[NAME_BUF_SIZE]; + char group_b_name[NAME_BUF_SIZE]; + char filename[NAME_BUF_SIZE]; + + TESTING("user data passed through lapl"); + + /* Set up filename and create file*/ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Register UD link types from previous tests to check that having + * multiple types registered at once presents no problems. */ + if(H5Lregister(UD_cb_class) < 0) TEST_ERROR; + + /* Register the link class. We'll actually be using for this test. */ + if(H5Lregister(UD_plist_class) < 0) TEST_ERROR; + + /* Another link class from a previous test */ + if(H5Lregister(UD_hard_class) < 0) TEST_ERROR; + + /* Unregister the first link type registered to make sure this doesn't + * break anything. */ + if(H5Lunregister(UD_CB_TYPE) < 0) TEST_ERROR; + + /* Create two groups for the UD link to point to */ + if((gid = H5Gcreate(fid, "group_a", 0)) <0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + if((gid = H5Gcreate(fid, "group_b", 0)) <0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Create a user-defined link to the group. These UD links have no udata. */ + if(H5Lcreate_ud(fid, "ud_link", UD_PLIST_TYPE, NULL, 0, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Create a non-default lapl with a new property pointing to group a*/ + if((plist_id = H5Pcreate(H5P_LINK_ACCESS)) < 0) TEST_ERROR; + strcpy(group_a_name, "group_a"); + if(H5Pinsert(plist_id, DEST_PROP_NAME, NAME_BUF_SIZE, group_a_name, NULL, NULL, NULL, NULL, NULL, NULL) < 0) TEST_ERROR; + + /* Try opening group through UD link */ + if((gid = H5Oopen(fid, "ud_link", plist_id)) < 0) TEST_ERROR; + if((gid2 = H5Gcreate(gid, "subgroup_a", 0)) < 0) TEST_ERROR; + if(H5Gclose(gid2) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Verify that we can open the new group without using the ud link */ + if((gid2 = H5Gopen(fid, "/group_a/subgroup_a")) < 0) TEST_ERROR; + if(H5Gclose(gid2) < 0) TEST_ERROR; + + /* Now use the same ud link to access group_b */ + strcpy(group_b_name, "group_b"); + if(H5Pset(plist_id, DEST_PROP_NAME, group_b_name)<0) TEST_ERROR; + + /* Create a subgroup */ + if((gid = H5Oopen(fid, "ud_link", plist_id)) < 0) TEST_ERROR; + if((gid2 = H5Gcreate(gid, "subgroup_b", 0)) < 0) TEST_ERROR; + if(H5Gclose(gid2) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Verify that we can open the new group without using the ud link */ + if((gid2 = H5Gopen(fid, "/group_b/subgroup_b")) < 0) TEST_ERROR; + if(H5Gclose(gid2) < 0) TEST_ERROR; + + /* Close property list */ + if(H5Pclose(plist_id) < 0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Pclose (plist_id); + H5Gclose (gid); + H5Gclose (gid2); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end lapl_udata() */ + + +/*------------------------------------------------------------------------- + * Function: ud_link_errors + * + * Purpose: Create error conditions in callbacks and ensure that the + * errors propagate correctly. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: James Laird + * Tuesday, June 6, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t UD_cbsucc_create(const char * link_name, hid_t loc_group, void * udata, size_t udata_size, hid_t lcpl_id) +{ + /* Check to make sure that this "soft link" has a target */ + if(udata_size < 1 || !udata) + return -1; + + return 0; +} +static hid_t UD_cbsucc_traverse(const char * link_name, hid_t cur_group, void * udata, size_t udata_size, hid_t lapl_id) +{ + const char *target = (char *) udata; + hid_t ret_value; + + if(!target) goto error; + + if((ret_value = H5Oopen(cur_group, target, lapl_id)) < 0) goto error; + + return ret_value; + +error: + return -1; +} +/* Failure callback for when the link is moved or renamed */ +herr_t UD_cbfail_move(const char * new_name, hid_t new_loc, void * udata, size_t udata_size) +{ + /* This traversal function will always fail. */ + return -1; +} +/* SuccessCallback for when the link is moved or renamed */ +herr_t UD_cbsucc_move(const char * new_name, hid_t new_loc, void * udata, size_t udata_size) +{ + /* This traversal function will always succeed. */ + return 0; +} +/* Callback for when the link is deleted. Also called during move */ +herr_t UD_cbsucc_delete(const char * link_name, hid_t loc_group, void * udata, size_t udata_size) +{ + /* This callback will always succeed */ + return 0; +} +/* Callback for when the link is deleted. Also called during move */ +herr_t UD_cbfail_delete(const char * link_name, hid_t loc_group, void * udata, size_t udata_size) +{ + /* This traversal function will always fail. */ + /* Note: un-deletable links are in general a very bad idea! */ + return -1; +} +/* Callback for when the link is queried */ +ssize_t UD_cbfail_query(const char * link_name, void * udata, size_t udata_size, void *buf, size_t buf_size) +{ + /* This traversal function will always fail. */ + return -1; +} +/* Callback for when the link is queried */ +ssize_t UD_cbfail_on_write_query(const char * link_name, void * udata, size_t udata_size, void *buf, size_t buf_size) +{ + /* This traversal function will return a buffer size, + * but will fail when a buffer is passed in ("writing to the buffer" + * fails + */ + + if(buf != NULL) + return -1; + + return 0; +} +/* Callback for when the link is queried */ +ssize_t UD_cbsucc_query(const char * link_name, void * udata, size_t udata_size, void *buf, size_t buf_size) +{ + /* This traversal function will return a buffer size, + * but will fail when a buffer is passed in ("writing to the buffer" + * fails + */ + + if(buf != NULL && buf_size >= 8) + strcpy(buf, "succeed"); + + return 8; +} + +/* This class is full of failing callbacks */ +const H5L_link_class_t UD_cbfail_class1[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + UD_CBFAIL_TYPE, /* Link type id number */ + "UD_cbfail_link1", /* Link class name for debugging */ + UD_cbsucc_create, /* Creation callback */ + UD_cbfail_move, /* Move/rename callback */ + UD_cbfail_move, /* Copy callback */ + UD_cbsucc_traverse, /* The actual traversal function */ + UD_cbfail_delete, /* Deletion callback */ + UD_cbfail_query /* Query callback */ +}}; + +/* This class is has two failing callbacks, move and query */ +const H5L_link_class_t UD_cbfail_class2[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + UD_CBFAIL_TYPE, /* Link type id number */ + "UD_cbfail_link2", /* Link class name for debugging */ + UD_cbsucc_create, /* Creation callback */ + UD_cbfail_move, /* Move/rename callback */ + UD_cbsucc_move, /* Copy callback */ + UD_cbsucc_traverse, /* The actual traversal function */ + UD_cbsucc_delete, /* Deletion callback */ + UD_cbfail_on_write_query /* Query callback */ +}}; + +/* All of these callbacks will succeed */ +const H5L_link_class_t UD_cbfail_class3[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + UD_CBFAIL_TYPE, /* Link type id number */ + "UD_cbfail_link3", /* Link class name for debugging */ + UD_cbsucc_create, /* Creation callback */ + UD_cbsucc_move, /* Move/rename callback */ + UD_cbsucc_move, /* Copy callback */ + UD_cbsucc_traverse, /* The actual traversal function */ + UD_cbsucc_delete, /* Deletion callback */ + UD_cbsucc_query /* Query callback */ +}}; + +/* Link classes that are invalid for various reasons */ +const H5L_link_class_t UD_error1_class[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + UD_ERROR_TYPE, /* Link type id number */ + "UD_error_link", /* Link class name for debugging */ + NULL, /* Creation callback */ + NULL, /* Move/rename callback */ + NULL, /* Copy callback */ + NULL, /* This class has no traversal function */ + NULL, /* Deletion callback */ + NULL /* Query callback */ +}}; +const H5L_link_class_t UD_error2_class[1] = {{ + UD_BAD_VERS, /* Invalid H5L_link_class_t version */ + UD_ERROR_TYPE, /* Link type id number */ + "UD_error_link", /* Link class name for debugging */ + NULL, /* Creation callback */ + NULL, /* Move/rename callback */ + NULL, /* Copy callback */ + UD_cbsucc_traverse, /* Traversal function */ + NULL, /* Deletion callback */ + NULL /* Query callback */ +}}; +const H5L_link_class_t UD_error3_class[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + UD_BAD_TYPE1, /* Invalid Link type id number */ + "UD_error_link", /* Link class name for debugging */ + NULL, /* Creation callback */ + NULL, /* Move/rename callback */ + NULL, /* Copy callback */ + UD_cbsucc_traverse, /* Traversal function */ + NULL, /* Deletion callback */ + NULL /* Query callback */ +}}; +const H5L_link_class_t UD_error4_class[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + UD_BAD_TYPE2, /* Invalid Link type id number */ + "UD_error_link", /* Link class name for debugging */ + NULL, /* Creation callback */ + NULL, /* Move/rename callback */ + NULL, /* Copy callback */ + UD_cbsucc_traverse, /* Traversal function */ + NULL, /* Deletion callback */ + NULL /* Query callback */ +}}; + +static int +ud_link_errors(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1); /* Group IDs */ + char group_name[NAME_BUF_SIZE]; + char filename[NAME_BUF_SIZE]; + char query_buf[NAME_BUF_SIZE]; + H5L_linkinfo_t li; /* Link information */ + + TESTING("user-defined link error conditions"); + + /* Set up filename and create file*/ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Try to register some invalid link classes */ + H5E_BEGIN_TRY { + if(H5Lregister(UD_error1_class) >= 0) TEST_ERROR; + if(H5Lregister(UD_error2_class) >= 0) TEST_ERROR; + if(H5Lregister(UD_error3_class) >= 0) TEST_ERROR; + if(H5Lregister(UD_error4_class) >= 0) TEST_ERROR; + } H5E_END_TRY + + /* Register the UD plist class. */ + if(H5Lregister(UD_plist_class) < 0) TEST_ERROR; + /* Now register the first class we'll be using. + * It has the same ID as the plist class, and should replace it. */ + if(H5Lregister(UD_cbfail_class1) < 0) TEST_ERROR; + + /* Create a group for the UD link to point to */ + if((gid = H5Gcreate(fid, "group", 0)) <0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Create a user-defined link to the group. */ + strcpy(group_name, "/group"); + if(H5Lcreate_ud(fid, "/ud_link", UD_CBFAIL_TYPE, &group_name, strlen(group_name) + 1, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Open the group through the ud link */ + if((gid = H5Gopen(fid, "ud_link")) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Now test that each of the callbacks will cause a failure if it returns -1 */ + H5E_BEGIN_TRY { + /* The create callback will fail if we pass in no udata */ + if(H5Lcreate_ud(fid, "fail", UD_CBFAIL_TYPE, NULL, 0, H5P_DEFAULT, H5P_DEFAULT) >= 0) TEST_ERROR; + /* The move and copy callbacks will fail */ + if(H5Gmove(fid, "ud_link", "move_fail") >= 0) TEST_ERROR; + if(H5Lcopy(fid, "ud_link", fid, "copy_fail", H5P_DEFAULT, H5P_DEFAULT) >= 0) TEST_ERROR; + /* The traversal callback will fail if we remove its target */ + if(H5Gunlink(fid, "group") < 0) TEST_ERROR; + if((gid = H5Gopen(gid, "ud_link")) >= 0) TEST_ERROR; + /* The deletion callback will always fail */ + if(H5Gunlink(fid, "ud_link") >= 0) TEST_ERROR; + /* The query callback will fail */ + if(H5Lget_linkinfo(fid, "ud_link", &li, H5P_DEFAULT) >=0) TEST_ERROR; + } H5E_END_TRY + + /* Now use a class with different callback functions */ + if(H5Lregister(UD_cbfail_class2) < 0) TEST_ERROR; + + /* Moving should still fail, but copying will succeed */ + H5E_BEGIN_TRY { + if(H5Gmove(fid, "ud_link", "move_fail") >= 0) TEST_ERROR + } H5E_END_TRY + if(H5Lcopy(fid, "ud_link", fid, "copy_succ", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* The query callback will succeed when we only want to get the size of the buffer... */ + if(H5Lget_linkinfo(fid, "ud_link", &li, H5P_DEFAULT) <0) TEST_ERROR; + if(li.u.link_size != 0) TEST_ERROR; + /* ...but fail when we try to write data to the buffer itself*/ + H5E_BEGIN_TRY { + if(H5Lget_linkval(fid, "ud_link", NAME_BUF_SIZE, query_buf, H5P_DEFAULT) >=0) TEST_ERROR; + } H5E_END_TRY + + /* Register a new class */ + if(H5Lregister(UD_cbfail_class3) < 0) TEST_ERROR; + + /* Now querying should succeed */ + if(H5Lget_linkinfo(fid, "ud_link", &li, H5P_DEFAULT) <0) TEST_ERROR; + if(li.u.link_size != 8) TEST_ERROR; + if(H5Lget_linkval(fid, "ud_link", NAME_BUF_SIZE, query_buf, H5P_DEFAULT) <0) TEST_ERROR; + if(HDstrcmp(query_buf, "succeed") != 0) TEST_ERROR; + + /* Moving and copying should both succeed */ + if(H5Gmove(fid, "copy_succ", "move_succ") < 0) TEST_ERROR + if(H5Lcopy(fid, "ud_link", fid, "copy_succ2", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Delete link (this callback should work now) */ + if(H5Gunlink(fid, "ud_link") <0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} + + + +/*------------------------------------------------------------------------- + * Function: lapl_nlinks + * + * Purpose: Check that the maximum number of soft links can be adjusted + * by the user using the Link Access Property List. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: James Laird + * Tuesday, June 6, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +lapl_nlinks(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1), gid2 = (-1); /* Group IDs */ + hid_t plist = (-1); /* lapl ID */ + hid_t tid = (-1), sid = (-1), did = (-1); /* Other IDs */ + hid_t gapl = (-1), dapl = (-1), tapl = (-1); /* Other property lists */ + char objname[NAME_BUF_SIZE]; /* Object name */ + ssize_t name_len; /* Length of object name */ + char filename[NAME_BUF_SIZE]; + size_t nlinks; /* nlinks for H5Pset_nlinks */ + hsize_t dims[2]; + + TESTING("adjusting nlinks with LAPL"); + + /* Make certain test is valid */ + /* XXX: should probably make a "generic" test that creates the proper + * # of links based on this value - QAK + */ + HDassert(H5G_NLINKS == 16); + + /* Create file */ + h5_fixname(FILENAME[1], fapl, filename, sizeof filename); + if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create group with short name in file (used as target for links) */ + if((gid=H5Gcreate (fid, "final", (size_t)0))<0) TEST_ERROR; + + /* Create chain of soft links to existing object (limited) */ + if(H5Glink2(fid, "final", H5G_LINK_SOFT, fid, "soft1") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft1", H5G_LINK_SOFT, fid, "soft2") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft2", H5G_LINK_SOFT, fid, "soft3") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft3", H5G_LINK_SOFT, fid, "soft4") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft4", H5G_LINK_SOFT, fid, "soft5") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft5", H5G_LINK_SOFT, fid, "soft6") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft6", H5G_LINK_SOFT, fid, "soft7") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft7", H5G_LINK_SOFT, fid, "soft8") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft8", H5G_LINK_SOFT, fid, "soft9") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft9", H5G_LINK_SOFT, fid, "soft10") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft10", H5G_LINK_SOFT, fid, "soft11") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft11", H5G_LINK_SOFT, fid, "soft12") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft12", H5G_LINK_SOFT, fid, "soft13") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft13", H5G_LINK_SOFT, fid, "soft14") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft14", H5G_LINK_SOFT, fid, "soft15") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft15", H5G_LINK_SOFT, fid, "soft16") < 0) TEST_ERROR; + if(H5Glink2(fid, "soft16", H5G_LINK_SOFT, fid, "soft17") < 0) TEST_ERROR; + + /* Close objects */ + if(H5Gclose(gid)<0) TEST_ERROR; + if(H5Fclose(fid)<0) TEST_ERROR; + + /* Open file */ + if((fid=H5Fopen(filename, H5F_ACC_RDWR, fapl))<0) TEST_ERROR; + + /* Create LAPL with higher-than-usual nlinks value */ + /* Create a non-default lapl with udata set to point to the first group */ + if((plist = H5Pcreate(H5P_LINK_ACCESS)) < 0) TEST_ERROR; + nlinks = 20; + if(H5Pset_nlinks(plist, nlinks)<0) TEST_ERROR; + + /* Ensure that nlinks was set successfully */ + nlinks = 0; + if(H5Pget_nlinks(plist, &nlinks)<0) TEST_ERROR + if(nlinks != 20) TEST_ERROR + + /* Open object through what is normally too many soft links using + * new property list */ + if((gid = H5Oopen(fid, "soft17", plist)) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(HDstrcmp(objname, "/soft17")) TEST_ERROR + + /* Create group using soft link */ + if((gid2 = H5Gcreate(gid, "new_soft", (size_t)0)) < 0) TEST_ERROR + + /* Close groups */ + if(H5Gclose(gid2) < 0) TEST_ERROR + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Set nlinks to a smaller number */ + nlinks = 4; + if(H5Pset_nlinks(plist, nlinks)<0) TEST_ERROR; + + /* Ensure that nlinks was set successfully */ + nlinks = 0; + if(H5Pget_nlinks(plist, &nlinks)<0) TEST_ERROR; + if(nlinks != 4) TEST_ERROR; + + /* Try opening through what is now too many soft links */ + H5E_BEGIN_TRY { + gid = H5Oopen(fid, "soft5", plist); + } H5E_END_TRY; + if (gid >= 0) { + H5_FAILED(); + puts(" Should have failed for sequence of too many nested links."); + goto error; + } + + /* Open object through lesser soft link */ + if((gid = H5Oopen(fid, "soft4", plist)) < 0) TEST_ERROR; + + /* Check name */ + if((name_len = H5Iget_name( gid, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR + if(HDstrcmp(objname, "/soft4")) TEST_ERROR + + + /* Test other functions that should use a LAPL */ + nlinks = 20; + if(H5Pset_nlinks(plist, nlinks)<0) TEST_ERROR; + + /* Try copying and moving when both src and dst cotain many soft links + * using a non-default LAPL + */ + if(H5Lcopy(fid, "soft17", fid, "soft17/newer_soft", H5P_DEFAULT, plist) < 0) TEST_ERROR + if(H5Lmove(fid, "soft17/newer_soft", fid, "soft17/newest_soft", H5P_DEFAULT, plist) < 0) TEST_ERROR + + /* H5Llink */ + if(H5Llink(fid, "soft17/link_to_group", gid, H5P_DEFAULT, plist) < 0) TEST_ERROR + + /* H5Lcreate_hard and H5Lcreate_soft */ + if(H5Lcreate_hard(fid, "soft17", fid, "soft17/link2_to_group", H5P_DEFAULT, plist) < 0) TEST_ERROR + if(H5Lcreate_soft("/soft4", fid, "soft17/soft_link", H5P_DEFAULT, plist) < 0) TEST_ERROR + + /* H5Lunlink */ + if(H5Lunlink(fid, "soft17/soft_link", plist) < 0) TEST_ERROR + + /* H5Lget_linkval and H5Lget_linkinfo */ + if(H5Lget_linkval(fid, "soft17", 0, NULL, plist) < 0) TEST_ERROR + if(H5Lget_linkinfo(fid, "soft17", NULL, plist) < 0) TEST_ERROR + + /* H5Lcreate_external and H5Lcreate_ud */ + if(H5Lcreate_external("filename", "path", fid, "soft17/extlink", H5P_DEFAULT, plist) <0) TEST_ERROR + if(H5Lregister(UD_rereg_class) < 0) TEST_ERROR + if(H5Lcreate_ud(fid, "soft17/udlink", UD_HARD_TYPE, NULL, 0, H5P_DEFAULT, plist) < 0) TEST_ERROR + + /* Close plist */ + if(H5Pclose(plist) < 0) TEST_ERROR; + + + /* Create a datatype and dataset as targets inside the group */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR + if(H5Tcommit(gid, "datatype", tid) < 0) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + + dims[0] = 2; + dims[1] = 2; + if((sid = H5Screate_simple(2, dims, NULL)) < 0) TEST_ERROR + if((did = H5Dcreate(gid, "dataset", H5T_NATIVE_INT, sid, H5P_DEFAULT)) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR; + + /* Close group */ + if(H5Gclose(gid) < 0) TEST_ERROR; + + /* Try to open the objects using too many symlinks with default *APLs */ + H5E_BEGIN_TRY { + if((gid = H5Gopen_expand(fid, "soft17", H5P_DEFAULT)) >=0) { + H5_FAILED(); + puts(" Should have failed for too many nested links."); + TEST_ERROR; + } + if((tid = H5Topen_expand(fid, "soft17/datatype", H5P_DEFAULT)) >=0) { + H5_FAILED(); + puts(" Should have failed for too many nested links."); + TEST_ERROR; + } + if((did = H5Dopen_expand(fid, "soft17/dataset", H5P_DEFAULT)) >=0) { + H5_FAILED(); + puts(" Should have failed for too many nested links."); + TEST_ERROR; + } + } H5E_END_TRY + + /* Create property lists with nlinks set */ + if((gapl = H5Pcreate(H5P_GROUP_ACCESS)) < 0) TEST_ERROR + if((tapl = H5Pcreate(H5P_DATATYPE_ACCESS)) < 0) TEST_ERROR + if((dapl = H5Pcreate(H5P_DATASET_ACCESS)) < 0) TEST_ERROR + + nlinks = 20; + if(H5Pset_nlinks(gapl, nlinks) < 0) TEST_ERROR + if(H5Pset_nlinks(tapl, nlinks) < 0) TEST_ERROR + if(H5Pset_nlinks(dapl, nlinks) < 0) TEST_ERROR + + /* We should now be able to use these property lists to open each kind + * of object. + */ + if((gid = H5Gopen_expand(fid, "soft17", gapl)) <0) TEST_ERROR + if((tid = H5Topen_expand(fid, "soft17/datatype", tapl)) <0) TEST_ERROR + if((did = H5Dopen_expand(fid, "soft17/dataset", dapl)) <0) TEST_ERROR + + /* Close objects */ + if(H5Gclose(gid) < 0) TEST_ERROR + if(H5Tclose(tid) < 0) TEST_ERROR + if(H5Dclose(did) < 0) TEST_ERROR + + /* Close plists */ + if(H5Pclose(gapl) < 0) TEST_ERROR; + if(H5Pclose(tapl) < 0) TEST_ERROR; + if(H5Pclose(dapl) < 0) TEST_ERROR; + + /* Close file */ + if(H5Fclose(fid)<0) TEST_ERROR; + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Pclose(gapl); + H5Pclose(dapl); + H5Pclose(tapl); + H5Dclose(did); + H5Sclose(sid); + H5Tclose(tid); + H5Gclose(gid2); + H5Gclose(gid); + H5Pclose(plist); + H5Fclose(fid); + } H5E_END_TRY; + return -1; +} /* end lapl_nlinks() */ + +/*------------------------------------------------------------------------- + * Function: objinfo_linkclass + * + * Purpose: Check that the link class is returned correctly when queried. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: James Laird + * Tuesday, June 6, 2006 + * + *------------------------------------------------------------------------- + */ +static int +linkinfo(hid_t fapl) +{ + hid_t fid = (-1); /* File ID */ + hid_t gid = (-1); /* Group ID */ + hid_t tid = (-1); /* Type ID */ + hid_t sid = (-1), did = -(1); /* Dataspace and dataset IDs */ + H5L_linkinfo_t li; /* Link information */ + char filename[NAME_BUF_SIZE]; + + TESTING("linkclass field in H5Gget_objinfo"); + + /* Set up filename and create file*/ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Register a couple of user-defined link classes with the library */ + if(H5Lregister(UD_plist_class) < 0) TEST_ERROR; + + /* Create an object of each type */ + if((tid = H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR; + if(H5Tcommit(fid, "datatype", tid) < 0) TEST_ERROR; + if((gid = H5Gcreate(fid, "group", 0)) < 0) TEST_ERROR; + if(H5Glink(fid, H5G_LINK_SOFT, "group", "softlink") < 0) TEST_ERROR; + + if((sid = H5Screate(H5S_SCALAR)) < 0) TEST_ERROR; + if((did = H5Dcreate(fid, "dataset", H5T_NATIVE_INT, sid, H5P_DEFAULT)) < 0) TEST_ERROR; + + if(H5Lcreate_ud(fid, "ud_link", UD_PLIST_TYPE, NULL, 0, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lcreate_external("file_name", "obj_path", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Close all objects */ + if(H5Tclose(tid) < 0) TEST_ERROR; + if(H5Gclose(gid) < 0) TEST_ERROR; + if(H5Dclose(did) < 0) TEST_ERROR; + + /* Make sure that linkclass is correct when objects are queried */ + if(H5Lget_linkinfo(fid, "datatype", &li, H5P_DEFAULT) < 0) TEST_ERROR; + if(li.linkclass != H5L_LINK_HARD) TEST_ERROR; + if(H5Lget_linkinfo(fid, "group", &li, H5P_DEFAULT) < 0) TEST_ERROR; + if(li.linkclass != H5L_LINK_HARD) TEST_ERROR; + if(H5Lget_linkinfo(fid, "dataset", &li, H5P_DEFAULT) < 0) TEST_ERROR; + if(li.linkclass != H5L_LINK_HARD) TEST_ERROR; + + if(H5Lget_linkinfo(fid, "ext_link", &li, H5P_DEFAULT) < 0) TEST_ERROR; + if(li.linkclass != H5L_LINK_EXTERNAL) TEST_ERROR; + if(H5Lget_linkinfo(fid, "softlink", &li, H5P_DEFAULT) < 0) TEST_ERROR; + if(li.linkclass != H5G_LINK_SOFT) TEST_ERROR; + if(H5Lget_linkinfo(fid, "ud_link", &li, H5P_DEFAULT) < 0) TEST_ERROR; + if(li.linkclass != UD_PLIST_TYPE) TEST_ERROR; + + /* Ensure that passing a NULL pointer doesn't cause an error */ + if(H5Lget_linkinfo(fid, "group", NULL, H5P_DEFAULT) < 0) TEST_ERROR; + + if(H5Fclose(fid) < 0) TEST_ERROR; + + PASSED(); + return 0; + + error: + H5E_BEGIN_TRY { + H5Tclose (tid); + H5Dclose (did); + H5Gclose (gid); + H5Fclose (fid); + } H5E_END_TRY; + return -1; +} /* end ud_hard_links() */ + + + +/*------------------------------------------------------------------------- * Function: main * * Purpose: Test links @@ -1467,7 +4717,6 @@ main(void) if (HDstrcmp(envval, "core") && HDstrcmp(envval, "split")) { h5_reset(); fapl = h5_fileaccess(); - /* The tests... */ nerrors += mklinks(fapl) < 0 ? 1 : 0; nerrors += cklinks(fapl) < 0 ? 1 : 0; @@ -1488,6 +4737,39 @@ main(void) #endif nerrors += test_compat(fapl); + nerrors += external_link_root(fapl) < 0 ? 1 : 0; + nerrors += external_link_path(fapl) < 0 ? 1 : 0; + nerrors += external_link_mult(fapl) < 0 ? 1 : 0; +#ifdef H5_GROUP_REVISION + nerrors += external_link_self(fapl) < 0 ? 1 : 0; +#endif + nerrors += external_link_pingpong(fapl) < 0 ? 1 : 0; + nerrors += external_link_toomany(fapl) < 0 ? 1 : 0; + nerrors += external_link_dangling(fapl) < 0 ? 1 : 0; + nerrors += external_link_recursive(fapl) < 0 ? 1 : 0; + nerrors += external_link_query(fapl) < 0 ? 1 : 0; + nerrors += external_link_unlink_compact(fapl) < 0 ? 1 : 0; +#ifdef H5_GROUP_REVISION + nerrors += external_link_unlink_dense(fapl) < 0 ? 1 : 0; +#endif /* H5_GROUP_REVISION */ + nerrors += external_link_move(fapl) < 0 ? 1 : 0; +#ifdef H5_GROUP_REVISION + nerrors += external_link_ride(fapl) < 0 ? 1 : 0; +#endif /* H5_GROUP_REVISION */ + nerrors += ext_link_endian(fapl) < 0 ? 1 : 0; + + /* These tests assume that external links are a form of UD links, + * so assume that everything that passed for external links + * above has already been tested for UD links. + */ + nerrors += ud_hard_links(fapl) < 0 ? 1 : 0; + nerrors += ud_link_reregister(fapl) < 0 ? 1 : 0; + nerrors += ud_callbacks(fapl) < 0 ? 1 : 0; + nerrors += ud_link_errors(fapl) < 0 ? 1 : 0; + nerrors += lapl_udata(fapl) < 0 ? 1 : 0; + nerrors += lapl_nlinks(fapl) < 0 ? 1 : 0; + nerrors += linkinfo(fapl) < 0 ? 1 : 0; + /* Results */ if (nerrors) { printf("***** %d LINK TEST%s FAILED! *****\n", @@ -1505,3 +4787,4 @@ main(void) } + diff --git a/test/mount.c b/test/mount.c index 8e5a903..cfd99dc 100644 --- a/test/mount.c +++ b/test/mount.c @@ -71,8 +71,8 @@ setup(hid_t fapl) if (H5Gclose(H5Gcreate(file, "/mnt1/file1", (size_t)0))<0) goto error; if (H5Gclose(H5Gcreate(file, "/mnt_unlink", (size_t)0))<0) goto error; if (H5Gclose(H5Gcreate(file, "/mnt_move_a", (size_t)0))<0) goto error; - if (H5Glink(file, H5G_LINK_HARD, "/mnt1/file1", "/file1")<0) goto error; - if (H5Glink(file, H5G_LINK_HARD, "/mnt1", "/mnt1_link")<0) goto error; + if (H5Glink(file, H5L_LINK_HARD, "/mnt1/file1", "/file1")<0) goto error; + if (H5Glink(file, H5L_LINK_HARD, "/mnt1", "/mnt1_link")<0) goto error; if (H5Fclose(file)<0) goto error; /* file 2 */ @@ -486,9 +486,9 @@ test_move(hid_t fapl) if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error; /* First rename an object in the mounted file, then try it across files */ - if (H5Gmove(file1, "/mnt1/rename_a/x", "/mnt1/rename_b/y")<0) goto error; + if (H5Lmove(file1, "/mnt1/rename_a/x", H5L_SAME_LOC, "/mnt1/rename_b/y", H5P_DEFAULT, H5P_DEFAULT)<0) goto error; H5E_BEGIN_TRY { - status = H5Gmove(file1, "/mnt1/rename_b/y", "/y"); + status = H5Lmove(file1, "/mnt1/rename_b/y", H5L_SAME_LOC, "/y", H5P_DEFAULT, H5P_DEFAULT); } H5E_END_TRY; if (status>=0) { H5_FAILED(); @@ -796,7 +796,7 @@ test_mvmpt(hid_t fapl) if (H5Fmount(file1, "/mnt_move_a", file2, H5P_DEFAULT)<0) TEST_ERROR /* Rename the mount point */ - if (H5Gmove(file1, "/mnt_move_a", "/mnt_move_b")<0) TEST_ERROR + if (H5Lmove(file1, "/mnt_move_a", H5L_SAME_LOC, "/mnt_move_b", H5P_DEFAULT, H5P_DEFAULT)<0) TEST_ERROR /* Access something under the new name */ if (H5Gget_objinfo(file1, "/mnt_move_b/file2", TRUE, NULL)<0) TEST_ERROR @@ -854,7 +854,7 @@ test_interlink(hid_t fapl) /* Try an interfile hard link directly */ H5E_BEGIN_TRY { - status = H5Glink(file1, H5G_LINK_HARD, "/mnt1/file2", "/file2"); + status = H5Glink(file1, H5L_LINK_HARD, "/mnt1/file2", "/file2"); } H5E_END_TRY; if (status>=0) { H5_FAILED(); @@ -864,7 +864,7 @@ test_interlink(hid_t fapl) /* Try an interfile hard link by renaming something */ H5E_BEGIN_TRY { - status = H5Gmove(file1, "/mnt1/file2", "/file2"); + status = H5Lmove(file1, "/mnt1/file2", H5L_SAME_LOC, "/file2", H5P_DEFAULT, H5P_DEFAULT); } H5E_END_TRY; if (status>=0) { H5_FAILED(); @@ -1108,9 +1108,9 @@ test_mount_after_close(hid_t fapl) TEST_ERROR if((gidABM = H5Gcreate(gidAB , "M", (size_t)0)) < 0) /* Mount point */ TEST_ERROR - if(H5Glink(gidAB, H5G_LINK_SOFT, "./M/X/Y", "C") < 0) /* Soft link */ + if(H5Glink(gidAB, H5L_LINK_SOFT, "./M/X/Y", "C") < 0) /* Soft link */ TEST_ERROR - if(H5Glink(gidAB, H5G_LINK_SOFT, "/A", "T") < 0) /* Soft link */ + if(H5Glink(gidAB, H5L_LINK_SOFT, "/A", "T") < 0) /* Soft link */ TEST_ERROR /* Close groups and file */ @@ -1144,7 +1144,7 @@ test_mount_after_close(hid_t fapl) TEST_ERROR if((did = H5Dcreate(gidXY, "D", H5T_NATIVE_INT, sid, H5P_DEFAULT)) < 0) TEST_ERROR - if(H5Glink(gidX, H5G_LINK_SOFT, "./Y", "T") < 0) /* Soft link */ + if(H5Glink(gidX, H5L_LINK_SOFT, "./Y", "T") < 0) /* Soft link */ TEST_ERROR /* Write data to the dataset. */ @@ -1450,7 +1450,7 @@ test_mount_after_unmount(hid_t fapl) /* Rename object in file #3 that is "disconnected" from name hiearchy */ /* (It is "disconnected" because it's parent file has been unmounted) */ - if(H5Gmove2(gidAMX,"M/Y",gidAMX,"M/Z") < 0) + if(H5Lmove(gidAMX,"M/Y",gidAMX,"M/Z", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR /* Close group in file #3 */ @@ -3686,7 +3686,7 @@ test_symlink(hid_t fapl) TEST_ERROR /* Create soft link to mounted object */ - if(H5Glink(fid1, H5G_LINK_SOFT, "./A/D/H", "L") < 0) /* Soft link */ + if(H5Glink(fid1, H5L_LINK_SOFT, "./A/D/H", "L") < 0) /* Soft link */ TEST_ERROR if(H5Fclose(fid1) < 0) diff --git a/test/objcopy.c b/test/objcopy.c index a96d5b0..7efef50 100755 --- a/test/objcopy.c +++ b/test/objcopy.c @@ -25,6 +25,7 @@ const char *FILENAME[] = { "objcopy_src", "objcopy_dst", + "objcopy_ext", NULL }; @@ -63,6 +64,7 @@ const char *FILENAME[] = { #define NAME_LINK_HARD "/g_links/hard_link_to_dataset_simple" #define NAME_LINK_SOFT "/g_links/soft_link_to_dataset_simple" #define NAME_LINK_SOFT2 "/g_links2/soft_link_to_dataset_simple" +#define NAME_LINK_EXTERN "/g_links/external_link_to_dataset_simple" #define NAME_LINK_SOFT_DANGLE "/g_links/soft_link_to_nowhere" #define NAME_LINK_SOFT_DANGLE2 "/g_links2/soft_link_to_nowhere" @@ -817,6 +819,8 @@ compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth) H5G_obj_t objtype2; /* Type of object in group */ H5G_stat_t objstat; /* Object info */ H5G_stat_t objstat2; /* Object info */ + H5L_linkinfo_t linfo; /* Link information */ + H5L_linkinfo_t linfo2; /* Link information */ hid_t oid, oid2; /* IDs of objects within group */ /* Loop over contents of groups */ @@ -835,12 +839,16 @@ compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth) if(H5Gget_objinfo(gid, objname, FALSE, &objstat) < 0) TEST_ERROR; if(H5Gget_objinfo(gid2, objname2, FALSE, &objstat2) < 0) TEST_ERROR; if(objstat.type != objstat2.type) TEST_ERROR; - if(objstat.type != H5G_LINK) { + if(objstat.type != H5G_LINK && objstat.type != H5G_UDLINK) { if(objstat.nlink != objstat2.nlink) TEST_ERROR; if(objstat.ohdr.nmesgs != objstat2.ohdr.nmesgs) TEST_ERROR; if(objstat.ohdr.nchunks != objstat2.ohdr.nchunks) TEST_ERROR; } /* end if */ + /* Get link info */ + if(H5Lget_linkinfo(gid, objname, &linfo, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lget_linkinfo(gid2, objname2, &linfo2, H5P_DEFAULT) < 0) TEST_ERROR; + /* Check for object already having been compared */ if(addr_lookup(&objstat)) continue; @@ -855,8 +863,8 @@ compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth) char linkname2[NAME_BUF_SIZE]; /* Link value */ /* Check link values */ - if(H5Gget_linkval(gid, objname, NAME_BUF_SIZE, linkname) < 0) TEST_ERROR; - if(H5Gget_linkval(gid2, objname2, NAME_BUF_SIZE, linkname2) < 0) TEST_ERROR; + if(H5Lget_linkval(gid, objname, NAME_BUF_SIZE, linkname, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lget_linkval(gid2, objname2, NAME_BUF_SIZE, linkname2, H5P_DEFAULT) < 0) TEST_ERROR; if(HDstrcmp(linkname, linkname2)) TEST_ERROR; } break; @@ -900,6 +908,24 @@ compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth) if(H5Tclose(oid2) < 0) TEST_ERROR; break; + case H5G_UDLINK: + { + char linkval[NAME_BUF_SIZE]; /* Link value */ + char linkval2[NAME_BUF_SIZE]; /* Link value */ + + /* Check that both links are the same type and the same size */ + if(linfo.linkclass != linfo2.linkclass) TEST_ERROR; + if(linfo.u.link_size != linfo2.u.link_size) TEST_ERROR; + + /* Get link udata */ + if(H5Lget_linkval(gid, objname, NAME_BUF_SIZE, linkval, H5P_DEFAULT) < 0) TEST_ERROR; + if(H5Lget_linkval(gid2, objname2, NAME_BUF_SIZE, linkval2, H5P_DEFAULT) < 0) TEST_ERROR; + + /* Compare link udata */ + if(HDmemcmp(linkval, linkval2, objstat.linklen)) TEST_ERROR; + } + break; + default: HDassert(0 && "Unknown type of object"); break; @@ -4102,7 +4128,7 @@ test_copy_group_loop(hid_t fapl) if ( (gid_sub2 = H5Gcreate(gid, NAME_GROUP_SUB_SUB, (size_t)0)) < 0) TEST_ERROR; /* Create link to top group */ - if ( H5Glink2(gid, ".", H5G_LINK_HARD, gid_sub2, NAME_GROUP_LOOP) < 0) TEST_ERROR; + if ( H5Glink2(gid, ".", H5L_LINK_HARD, gid_sub2, NAME_GROUP_LOOP) < 0) TEST_ERROR; /* close sub sub group */ if( H5Gclose(gid_sub2) < 0) TEST_ERROR; @@ -4223,13 +4249,13 @@ test_copy_group_wide_loop(hid_t fapl) if ( (gid_sub2 = H5Gcreate(gid_sub, objname, (size_t)0)) < 0) TEST_ERROR; /* Create link to top group */ - if ( H5Glink2(gid, ".", H5G_LINK_HARD, gid_sub2, NAME_GROUP_LOOP) < 0) TEST_ERROR; + if ( H5Glink2(gid, ".", H5L_LINK_HARD, gid_sub2, NAME_GROUP_LOOP) < 0) TEST_ERROR; /* Create link to sub-group */ - if ( H5Glink2(gid_sub, ".", H5G_LINK_HARD, gid_sub2, NAME_GROUP_LOOP2) < 0) TEST_ERROR; + if ( H5Glink2(gid_sub, ".", H5L_LINK_HARD, gid_sub2, NAME_GROUP_LOOP2) < 0) TEST_ERROR; /* Create link to self :-) */ - if ( H5Glink2(gid_sub2, ".", H5G_LINK_HARD, gid_sub2, NAME_GROUP_LOOP3) < 0) TEST_ERROR; + if ( H5Glink2(gid_sub2, ".", H5L_LINK_HARD, gid_sub2, NAME_GROUP_LOOP3) < 0) TEST_ERROR; /* close sub sub group */ if( H5Gclose(gid_sub2) < 0) TEST_ERROR; @@ -4364,13 +4390,16 @@ test_copy_group_links(hid_t fapl) if (H5Dclose(did) < 0) TEST_ERROR; /* make a hard link to the dataset */ - if (H5Glink(fid_src, H5G_LINK_HARD, NAME_LINK_DATASET, NAME_LINK_HARD) < 0) TEST_ERROR; + if (H5Glink(fid_src, H5L_LINK_HARD, NAME_LINK_DATASET, NAME_LINK_HARD) < 0) TEST_ERROR; /* make a soft link to the dataset */ - if (H5Glink(fid_src, H5G_LINK_SOFT, NAME_LINK_DATASET, NAME_LINK_SOFT) < 0) TEST_ERROR; + if (H5Glink(fid_src, H5L_LINK_SOFT, NAME_LINK_DATASET, NAME_LINK_SOFT) < 0) TEST_ERROR; /* make a soft link to nowhere */ - if (H5Glink(fid_src, H5G_LINK_SOFT, "nowhere", NAME_LINK_SOFT_DANGLE) < 0) TEST_ERROR; + if (H5Glink(fid_src, H5L_LINK_SOFT, "nowhere", NAME_LINK_SOFT_DANGLE) < 0) TEST_ERROR; + + /* make a dangling external link */ + if (H5Lcreate_external("filename", "obj_name", fid_src, NAME_LINK_EXTERN, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; /* close the group */ if ( H5Gclose(gid) < 0) TEST_ERROR; @@ -4496,7 +4525,7 @@ test_copy_soft_link(hid_t fapl) if (H5Dclose(did) < 0) TEST_ERROR; /* make a soft link to the dataset */ - if (H5Glink(fid_src, H5G_LINK_SOFT, NAME_LINK_DATASET, NAME_LINK_SOFT) < 0) TEST_ERROR; + if (H5Glink(fid_src, H5L_LINK_SOFT, NAME_LINK_DATASET, NAME_LINK_SOFT) < 0) TEST_ERROR; /* close the group */ if ( H5Gclose(gid) < 0) TEST_ERROR; @@ -4555,6 +4584,141 @@ error: /*------------------------------------------------------------------------- + * Function: test_copy_ext_link + * + * Purpose: Create an external link in SRC file and copy it to DST file + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: James Laird + * Friday, June 16, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_ext_link(hid_t fapl) +{ + hid_t fid_src = -1, fid_dst = -1, fid_ext = -1; /* File IDs */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1, did2 = -1; /* Dataset IDs */ + hid_t gid = -1; /* Group ID */ + hsize_t dim2d[2]; + int buf[DIM_SIZE_1][DIM_SIZE_2]; + int i, j; + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + char ext_filename[NAME_BUF_SIZE]; + + TESTING("H5Gcopy(): object through external link"); + + /* set initial data values */ + for (i=0; i<DIM_SIZE_1; i++) + for (j=0; j<DIM_SIZE_2; j++) + buf[i][j] = 10000 + 100*i+j; + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], fapl, dst_filename, sizeof dst_filename); + h5_fixname(FILENAME[2], fapl, ext_filename, sizeof dst_filename); + + /* Reset file address checking info */ + addr_reset(); + + /* create source file */ + if ( (fid_src = H5Fcreate(src_filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR; + + /* create group at the SRC file */ + if ( (gid = H5Gcreate(fid_src, NAME_GROUP_LINK, (size_t)0)) < 0) TEST_ERROR; + + /* attach attributes to the group */ + if ( test_copy_attach_attributes(gid, H5T_NATIVE_INT) < 0) TEST_ERROR; + + /* Set dataspace dimensions */ + dim2d[0]=DIM_SIZE_1; + dim2d[1]=DIM_SIZE_2; + + /* create dataspace */ + if ( (sid = H5Screate_simple(2, dim2d, NULL)) < 0) TEST_ERROR; + + /* add a dataset to the group */ + if ( (did = H5Dcreate(fid_src, NAME_LINK_DATASET, H5T_NATIVE_INT, sid, H5P_DEFAULT) ) < 0) TEST_ERROR; + if ( H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) TEST_ERROR; + + /* close dataspace */ + if ( H5Sclose(sid) < 0) TEST_ERROR; + /* close the dataset */ + if (H5Dclose(did) < 0) TEST_ERROR; + /* close the group */ + if ( H5Gclose(gid) < 0) TEST_ERROR; + + + /* create file to hold external links to the src file */ + if ( (fid_ext = H5Fcreate(ext_filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR; + + /* create group in the external file */ + if ( (gid = H5Gcreate(fid_ext, NAME_GROUP_LINK, (size_t)0)) < 0) TEST_ERROR; + + /* Create an external link to the dataset */ + if ( H5Lcreate_external(src_filename, NAME_LINK_DATASET, fid_ext, NAME_LINK_EXTERN, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* close the group and file */ + if ( H5Gclose(gid) < 0) TEST_ERROR; + if (H5Fclose(fid_ext) < 0) TEST_ERROR; + + /* open the "extern" file with read-only */ + if ( (fid_ext = H5Fopen(ext_filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR; + + /* create destination file */ + if ( (fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR; + + /* Create an uncopied object in destination file so that addresses in source and destination files aren't the same */ + if ( H5Gclose(H5Gcreate(fid_dst, NAME_GROUP_UNCOPIED, (size_t)0)) < 0) TEST_ERROR; + + /* copy the dataset from SRC to DST */ + if ( H5Gcopy(fid_ext, NAME_LINK_EXTERN, fid_dst, NAME_DATASET_SIMPLE, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR; + + /* open the dataset through the external link */ + if ( (did = H5Dopen(fid_ext, NAME_LINK_EXTERN)) < 0) TEST_ERROR; + + /* open the destination dataset */ + if ( (did2 = H5Dopen(fid_dst, NAME_DATASET_SIMPLE)) < 0) TEST_ERROR; + + /* Check if the datasets are equal */ + if ( compare_datasets(did, did2, H5P_DEFAULT, buf) != TRUE) TEST_ERROR; + + /* close the destination dataset */ + if ( H5Dclose(did2) < 0) TEST_ERROR; + + /* close the source dataset */ + if ( H5Dclose(did) < 0) TEST_ERROR; + + /* close the SRC file */ + if ( H5Fclose(fid_src) < 0) TEST_ERROR; + + /* close the EXT file */ + if ( H5Fclose(fid_ext) < 0) TEST_ERROR; + + /* close the DST file */ + if ( H5Fclose(fid_dst) < 0) TEST_ERROR; + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Sclose(sid); + H5Dclose(did2); + H5Dclose(did); + H5Gclose(gid); + H5Fclose(fid_dst); + H5Fclose(fid_src); + } H5E_END_TRY; + return 1; +} /* end test_copy_ext_link */ + + +/*------------------------------------------------------------------------- * Function: test_copy_exist * * Purpose: Create a simple dataset in SRC file and copy it onto an @@ -6197,14 +6361,14 @@ test_copy_option(hid_t fapl, unsigned flag, hbool_t crt_intermediate_grp, const if ((flag & H5G_COPY_EXPAND_SOFT_LINK_FLAG) > 0) { /* Create group to copy */ if ( (gid = H5Gcreate(fid_src, NAME_GROUP_LINK, (size_t)0)) < 0) TEST_ERROR; - if (H5Glink(fid_src, H5G_LINK_SOFT, NAME_DATASET_SUB_SUB, NAME_LINK_SOFT) < 0) TEST_ERROR; - if (H5Glink(fid_src, H5G_LINK_SOFT, "nowhere", NAME_LINK_SOFT_DANGLE) < 0) TEST_ERROR; + if (H5Glink(fid_src, H5L_LINK_SOFT, NAME_DATASET_SUB_SUB, NAME_LINK_SOFT) < 0) TEST_ERROR; + if (H5Glink(fid_src, H5L_LINK_SOFT, "nowhere", NAME_LINK_SOFT_DANGLE) < 0) TEST_ERROR; if ( H5Gclose(gid) < 0) TEST_ERROR; /* Create group to compare with */ if ( (gid = H5Gcreate(fid_src, NAME_GROUP_LINK2, (size_t)0)) < 0) TEST_ERROR; - if (H5Glink(fid_src, H5G_LINK_HARD, NAME_DATASET_SUB_SUB, NAME_LINK_SOFT2) < 0) TEST_ERROR; - if (H5Glink(fid_src, H5G_LINK_SOFT, "nowhere", NAME_LINK_SOFT_DANGLE2) < 0) TEST_ERROR; + if (H5Glink(fid_src, H5L_LINK_HARD, NAME_DATASET_SUB_SUB, NAME_LINK_SOFT2) < 0) TEST_ERROR; + if (H5Glink(fid_src, H5L_LINK_SOFT, "nowhere", NAME_LINK_SOFT_DANGLE2) < 0) TEST_ERROR; if ( H5Gclose(gid) < 0) TEST_ERROR; } @@ -6396,6 +6560,7 @@ main(void) nerrors += test_copy_group_wide_loop(fapl); nerrors += test_copy_group_links(fapl); nerrors += test_copy_soft_link(fapl); + nerrors += test_copy_ext_link(fapl); nerrors += test_copy_exist(fapl); nerrors += test_copy_path(fapl); nerrors += test_copy_same_file_named_datatype(fapl); diff --git a/test/stab.c b/test/stab.c index 2562423..b684f9e 100644 --- a/test/stab.c +++ b/test/stab.c @@ -330,7 +330,7 @@ lifecycle(hid_t fapl) /* Create group for testing lifecycle */ if((gid = H5Gcreate_expand(fid, gcpl, H5P_DEFAULT)) < 0) TEST_ERROR - if((H5Llink(fid, LIFECYCLE_TOP_GROUP, gid, H5P_DEFAULT)) < 0) TEST_ERROR + if((H5Llink(fid, LIFECYCLE_TOP_GROUP, gid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR /* Query group creation property settings */ if(H5Pget_local_heap_size_hint(gcpl, &lheap_size_hint) < 0) TEST_ERROR; @@ -789,7 +789,7 @@ no_compact(hid_t fapl) /* Create group for testing lifecycle */ if((gid = H5Gcreate_expand(fid, gcpl, H5P_DEFAULT)) < 0) TEST_ERROR - if((H5Llink(fid, NO_COMPACT_TOP_GROUP, gid, H5P_DEFAULT)) < 0) TEST_ERROR + if((H5Llink(fid, NO_COMPACT_TOP_GROUP, gid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR /* Close GCPL */ if(H5Pclose(gcpl) < 0) TEST_ERROR; @@ -920,7 +920,7 @@ gcpl_on_root(hid_t fapl) /* Create a group and intermediate groups, to check if root group settings are inherited */ if((gid2 = H5Gcreate_expand(gid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR - if((H5Llink(fid, GCPL_ON_ROOT_BOTTOM_GROUP, gid, lcpl)) < 0) TEST_ERROR + if((H5Llink(fid, GCPL_ON_ROOT_BOTTOM_GROUP, gid2, lcpl, H5P_DEFAULT)) < 0) TEST_ERROR /* Close LCPL */ if(H5Pclose(lcpl) < 0) TEST_ERROR; diff --git a/test/testhdf5.c b/test/testhdf5.c index 925b8f8..eadc2bd 100644 --- a/test/testhdf5.c +++ b/test/testhdf5.c @@ -50,6 +50,7 @@ main(int argc, char *argv[]) AddTest("skiplist", test_skiplist, NULL, "Skip Lists", NULL); AddTest("refstr", test_refstr, NULL, "Reference Counted Strings", NULL); AddTest("file", test_file, cleanup_file, "Low-Level File I/O", NULL); + AddTest("objects", test_h5o, cleanup_file, "Generic Object Functions", NULL); AddTest("h5s", test_h5s, cleanup_h5s, "Dataspaces", NULL); AddTest("attr", test_attr, cleanup_attr, "Attributes", NULL); AddTest("select", test_select, cleanup_select, "Selections", NULL); diff --git a/test/testhdf5.h b/test/testhdf5.h index 2274b78..b4f1342 100644 --- a/test/testhdf5.h +++ b/test/testhdf5.h @@ -127,6 +127,7 @@ void test_tst(void); void test_heap(void); void test_refstr(void); void test_file(void); +void test_h5o(void); void test_h5t(void); void test_h5s(void); void test_h5d(void); @@ -148,6 +149,7 @@ void test_unicode(void); /* Prototypes for the cleanup routines */ void cleanup_metadata(void); void cleanup_file(void); +void cleanup_h5o(void); void cleanup_h5s(void); void cleanup_attr(void); void cleanup_select(void); diff --git a/test/th5o.c b/test/th5o.c new file mode 100644 index 0000000..fde15c7 --- /dev/null +++ b/test/th5o.c @@ -0,0 +1,601 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*********************************************************** +* +* Test program: th5o +* +* Test public H5O functions for accessing +* +*************************************************************/ + +#include "testhdf5.h" + +/*#include "H5private.h" +#include "H5Bprivate.h" +#include "H5Sprivate.h" +#include "H5Pprivate.h" +*/ + +#define TEST_FILENAME "th5o_file" + +#define RANK 2 +#define DIM0 5 +#define DIM1 10 + +/**************************************************************** +** +** test_h5o_open(): Test H5Oopen function. +** +****************************************************************/ +static void +test_h5o_open(void) +{ + hid_t fid; /* HDF5 File ID */ + hid_t grp, dset, dtype, dspace; /* Object identifiers */ + hsize_t dims[RANK]; + H5I_type_t id_type; /* Type of IDs returned from H5Oopen */ + hsize_t num_objs=-1; /* Number of objects in the group */ + H5T_class_t type_class; /* Class of the datatype */ + herr_t ret; /* Value returned from API calls */ + + /* Create a new HDF5 file */ + fid = H5Fcreate(TEST_FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fcreate"); + + /* Create a group, dataset, and committed datatype within the file */ + /* Create the group */ + grp = H5Gcreate(fid, "group", 0); + CHECK(grp, FAIL, "H5Gcreate"); + ret = H5Gclose(grp); + CHECK(ret, FAIL, "H5Gclose"); + + /* Commit the type inside the group */ + dtype = H5Tcopy(H5T_NATIVE_INT); + CHECK(dtype, FAIL, "H5Tcopy"); + ret = H5Tcommit(fid, "group/datatype", dtype); + CHECK(ret, FAIL, "H5Tcommit"); + ret = H5Tclose(dtype); + CHECK(ret, FAIL, "H5Tclose"); + + /* Create the data space for the dataset. */ + dims[0] = DIM0; + dims[1] = DIM1; + dspace = H5Screate_simple(RANK, dims, NULL); + CHECK(dspace, FAIL, "H5Screate_simple"); + + /* Create the dataset. */ + dset = H5Dcreate(fid, "dataset", H5T_NATIVE_INT, dspace, H5P_DEFAULT); + CHECK(dset, FAIL, "H5Dcreate"); + ret = H5Dclose(dset); + CHECK(ret, FAIL, "H5Dclose"); + ret = H5Sclose(dspace); + CHECK(ret, FAIL, "H5Sclose"); + + /* Now make sure that H5Oopen can open all three types of objects */ + grp = H5Oopen(fid, "group", H5P_DEFAULT); + CHECK(grp, FAIL, "H5Oopen"); + dtype = H5Oopen(fid, "group/datatype", H5P_DEFAULT); + CHECK(dtype, FAIL, "H5Oopen"); + /* Check that we can use the group as a valid location */ + dset = H5Oopen(grp, "/dataset", H5P_DEFAULT); + CHECK(dset, FAIL, "H5Oopen"); + + /* Make sure that each is the right kind of ID */ + id_type = H5Iget_type(grp); + VERIFY(id_type, H5I_GROUP, "H5Iget_type for group ID"); + id_type = H5Iget_type(dtype); + VERIFY(id_type, H5I_DATATYPE, "H5Iget_type for datatype ID"); + id_type = H5Iget_type(dset); + VERIFY(id_type, H5I_DATASET, "H5Iget_type for dataset ID"); + + /* Do something more complex with each of the IDs to make sure they "work" */ + ret = H5Gget_num_objs(grp, &num_objs); + CHECK(ret, FAIL, "H5Gget_num_objs"); + VERIFY(num_objs, 1, "H5Gget_num_objs"); /* There should be one object, the datatype */ + + type_class = H5Tget_class(dtype); + VERIFY(type_class, H5T_INTEGER, "H5Tget_class"); + + dspace = H5Dget_space(dset); + CHECK(dspace, FAIL, "H5Dget_space"); + + /* Close the IDs */ + ret = H5Gclose(grp); + CHECK(ret, FAIL, "H5Gclose"); + ret = H5Tclose(dtype); + CHECK(ret, FAIL, "H5Tclose"); + ret = H5Dclose(dset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Trying to open objects with bogus names should fail gracefully */ + H5E_BEGIN_TRY { + grp = H5Oopen(fid, "bogus_group", H5P_DEFAULT); + VERIFY(grp, FAIL, "H5Oopen"); + dtype = H5Oopen(fid, "group/bogus_datatype", H5P_DEFAULT); + VERIFY(dtype, FAIL, "H5Oopen"); + dset = H5Oopen(fid, "/bogus_dataset", H5P_DEFAULT); + VERIFY(dset, FAIL, "H5Oopen"); + } H5E_END_TRY + + /* Close the file */ + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); + + /* Trying to open an object with a bogus file ID should fail */ + H5E_BEGIN_TRY { + dset = H5Oopen(fid, "dataset", H5P_DEFAULT); + VERIFY(dset, FAIL, "H5Oopen"); + } H5E_END_TRY +} /* test_h5o_open() */ + + + +/**************************************************************** +** +** test_h5o_close(): Test H5Oclose function. +** +****************************************************************/ +static void +test_h5o_close(void) +{ + hid_t fid; /* HDF5 File ID */ + hid_t grp, dset, dtype, dspace; /* Object identifiers */ + hsize_t dims[RANK]; + herr_t ret; /* Value returned from API calls */ + + /* Create a new HDF5 file */ + fid = H5Fcreate(TEST_FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fcreate"); + + /* Create a group, dataset, and committed datatype within the file */ + /* Create the group and close it with H5Oclose */ + grp = H5Gcreate(fid, "group", 0); + CHECK(grp, FAIL, "H5Gcreate"); + VERIFY(H5Iget_type(grp), H5I_GROUP, "H5Iget_type"); + ret = H5Oclose(grp); + CHECK(ret, FAIL, "H5Oclose"); + + /* Commit the type inside the group */ + dtype = H5Tcopy(H5T_NATIVE_INT); + CHECK(dtype, FAIL, "H5Tcopy"); + ret = H5Tcommit(fid, "group/datatype", dtype); + CHECK(ret, FAIL, "H5Tcommit"); + ret = H5Oclose(dtype); + CHECK(ret, FAIL, "H5Oclose"); + + /* Create the data space for the dataset. */ + dims[0] = DIM0; + dims[1] = DIM1; + dspace = H5Screate_simple(RANK, dims, NULL); + CHECK(dspace, FAIL, "H5Screate_simple"); + + /* Create the dataset. */ + dset = H5Dcreate(fid, "dataset", H5T_NATIVE_INT, dspace, H5P_DEFAULT); + CHECK(dset, FAIL, "H5Dcreate"); + ret = H5Oclose(dset); + CHECK(ret, FAIL, "H5Oclose"); + + /* Attempting to close the data space with H5Oclose should fail */ + H5E_BEGIN_TRY { + ret = H5Oclose(dspace); + VERIFY(ret, FAIL, "H5Oclose"); + } H5E_END_TRY + /* Close the dataspace for real */ + ret = H5Sclose(dspace); + CHECK(ret, FAIL, "H5Sclose"); + + /* Make sure that H5Oclose can close objects opened with H5Oopen */ + grp = H5Oopen(fid, "group", H5P_DEFAULT); + CHECK(grp, FAIL, "H5Oopen"); + dtype = H5Oopen(fid, "group/datatype", H5P_DEFAULT); + CHECK(dtype, FAIL, "H5Oopen"); + dset = H5Oopen(fid, "dataset", H5P_DEFAULT); + CHECK(dset, FAIL, "H5Oopen"); + + ret = H5Oclose(grp); + CHECK(ret, FAIL, "H5Oclose"); + ret = H5Oclose(dtype); + CHECK(ret, FAIL, "H5Oclose"); + ret = H5Oclose(dset); + CHECK(ret, FAIL, "H5Oclose"); + + /* Make sure H5Oclose can close objects opened with H5*open */ + grp = H5Gopen(fid, "group"); + CHECK(grp, FAIL, "H5Gopen"); + dtype = H5Topen(fid, "group/datatype"); + CHECK(dtype, FAIL, "H5Topen"); + dset = H5Dopen(fid, "dataset"); + CHECK(dset, FAIL, "H5Dopen"); + + ret = H5Oclose(grp); + CHECK(ret, FAIL, "H5Oclose"); + ret = H5Oclose(dtype); + CHECK(ret, FAIL, "H5Oclose"); + ret = H5Oclose(dset); + CHECK(ret, FAIL, "H5Oclose"); + + /* Close the file */ + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); +} + + +/**************************************************************** +** +** test_h5o_open_by_addr(): Test H5Oopen_by_addr function. +** +****************************************************************/ +static void +test_h5o_open_by_addr(void) +{ + hid_t fid; /* HDF5 File ID */ + hid_t grp, dset, dtype, dspace; /* Object identifiers */ + H5L_linkinfo_t li; /* Buffer for H5Lget_linkinfo */ + haddr_t grp_addr; /* Addresses for objects */ + haddr_t dset_addr; + haddr_t dtype_addr; + hsize_t dims[RANK]; + H5I_type_t id_type; /* Type of IDs returned from H5Oopen */ + hsize_t num_objs=-1; /* Number of objects in the group */ + H5T_class_t type_class; /* Class of the datatype */ + herr_t ret; /* Value returned from API calls */ + + /* Create a new HDF5 file */ + fid = H5Fcreate(TEST_FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fcreate"); + + /* Create a group, dataset, and committed datatype within the file */ + /* Create the group */ + grp = H5Gcreate(fid, "group", 0); + CHECK(grp, FAIL, "H5Gcreate"); + ret = H5Gclose(grp); + CHECK(ret, FAIL, "H5Gclose"); + + /* Commit the type inside the group */ + dtype = H5Tcopy(H5T_NATIVE_INT); + CHECK(dtype, FAIL, "H5Tcopy"); + ret = H5Tcommit(fid, "group/datatype", dtype); + CHECK(ret, FAIL, "H5Tcommit"); + ret = H5Tclose(dtype); + CHECK(ret, FAIL, "H5Tclose"); + + /* Create the data space for the dataset. */ + dims[0] = DIM0; + dims[1] = DIM1; + dspace = H5Screate_simple(RANK, dims, NULL); + CHECK(dspace, FAIL, "H5Screate_simple"); + + /* Create the dataset. */ + dset = H5Dcreate(fid, "dataset", H5T_NATIVE_INT, dspace, H5P_DEFAULT); + CHECK(dset, FAIL, "H5Dcreate"); + ret = H5Dclose(dset); + CHECK(ret, FAIL, "H5Dclose"); + ret = H5Sclose(dspace); + CHECK(ret, FAIL, "H5Sclose"); + + /* Get address for each object */ + ret = H5Lget_linkinfo(fid, "group", &li, H5P_DEFAULT); + CHECK(ret, FAIL, "H5Lget_linkinfo"); + grp_addr = li.u.address; + ret = H5Lget_linkinfo(fid, "group/datatype", &li, H5P_DEFAULT); + CHECK(ret, FAIL, "H5Lget_linkinfo"); + dtype_addr = li.u.address; + ret = H5Lget_linkinfo(fid, "dataset", &li, H5P_DEFAULT); + CHECK(ret, FAIL, "H5Lget_linkinfo"); + dset_addr = li.u.address; + + /* Now make sure that H5Oopen_by_addr can open all three types of objects */ + grp = H5Oopen_by_addr(fid, grp_addr); + CHECK(grp, FAIL, "H5Oopen_by_addr"); + dtype = H5Oopen_by_addr(fid, dtype_addr); + CHECK(dtype, FAIL, "H5Oopen_by_addr"); + /* Check that we can use the group ID as a valid location */ + dset = H5Oopen_by_addr(grp, dset_addr); + CHECK(dset, FAIL, "H5Oopen_by_addr"); + + /* Make sure that each is the right kind of ID */ + id_type = H5Iget_type(grp); + VERIFY(id_type, H5I_GROUP, "H5Iget_type for group ID"); + id_type = H5Iget_type(dtype); + VERIFY(id_type, H5I_DATATYPE, "H5Iget_type for datatype ID"); + id_type = H5Iget_type(dset); + VERIFY(id_type, H5I_DATASET, "H5Iget_type for dataset ID"); + + /* Do something more complex with each of the IDs to make sure they "work" */ + ret = H5Gget_num_objs(grp, &num_objs); + CHECK(ret, FAIL, "H5Gget_num_objs"); + VERIFY(num_objs, 1, "H5Gget_num_objs"); /* There should be one object, the datatype */ + + type_class = H5Tget_class(dtype); + VERIFY(type_class, H5T_INTEGER, "H5Tget_class"); + + dspace = H5Dget_space(dset); + CHECK(dspace, FAIL, "H5Dget_space"); + + /* Close the IDs */ + ret = H5Gclose(grp); + CHECK(ret, FAIL, "H5Gclose"); + ret = H5Tclose(dtype); + CHECK(ret, FAIL, "H5Tclose"); + ret = H5Dclose(dset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Try giving some bogus values to H5O_open_by_addr. */ + /* Try to open an object with a bad address */ + grp_addr += 20; + H5E_BEGIN_TRY{ + grp = H5Oopen_by_addr(fid, grp_addr); + }H5E_END_TRY + VERIFY(grp, FAIL, "H5Oopen_by_addr"); + + /* For instance, an objectno smaller than the end of the file's superblock should + * trigger an error */ + grp_addr = 10; + H5E_BEGIN_TRY{ + grp = H5Oopen_by_addr(fid, grp_addr); + }H5E_END_TRY + VERIFY(grp, FAIL, "H5Oopen_by_addr"); + + /* Likewise, an objectno larger than the size of the file should fail */ + grp_addr = 0; + grp_addr = 1000000000; + H5E_BEGIN_TRY{ + grp = H5Oopen_by_addr(fid, grp_addr); + }H5E_END_TRY + VERIFY(grp, FAIL, "H5Oopen_by_addr"); + + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); + + /* Also, trying to open an object without a valid location should fail */ + H5E_BEGIN_TRY{ + dtype = H5Oopen_by_addr(fid, dtype_addr); + }H5E_END_TRY + VERIFY(dtype, FAIL, "H5Oopen_by_addr"); +} /* test_h5o_open_by_addr() */ + + +/**************************************************************** +** +** test_h5o_refcount(): Test H5O refcounting functions. +** +****************************************************************/ +static void +test_h5o_refcount(void) +{ + hid_t fid; /* HDF5 File ID */ + hid_t grp, dset, dtype, dspace; /* Object identifiers */ + H5G_stat_t sb; /* Statbuffer for H5Gget_objinfo */ + hsize_t dims[RANK]; + herr_t ret; /* Value returned from API calls */ + + /* Create a new HDF5 file */ + fid = H5Fcreate(TEST_FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fcreate"); + + /* Create a group, dataset, and committed datatype within the file */ + /* Create the group */ + grp = H5Gcreate(fid, "group", 0); + CHECK(grp, FAIL, "H5Gcreate"); + + /* Commit the type inside the group */ + dtype = H5Tcopy(H5T_NATIVE_INT); + CHECK(dtype, FAIL, "H5Tcopy"); + ret = H5Tcommit(fid, "datatype", dtype); + CHECK(ret, FAIL, "H5Tcommit"); + + /* Create the data space for the dataset. */ + dims[0] = DIM0; + dims[1] = DIM1; + dspace = H5Screate_simple(RANK, dims, NULL); + CHECK(dspace, FAIL, "H5Screate_simple"); + + /* Create the dataset. */ + dset = H5Dcreate(fid, "dataset", H5T_NATIVE_INT, dspace, H5P_DEFAULT); + CHECK(dset, FAIL, "H5Dcreate"); + ret = H5Sclose(dspace); + CHECK(ret, FAIL, "H5Sclose"); + + /* Get ref counts for each object. They should all be 1, since each object has a hard link. */ + ret = H5Gget_objinfo(fid, "group", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 1, "reference count in H5Gget_objinfo"); + ret = H5Gget_objinfo(fid, "datatype", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 1, "reference count in H5Gget_objinfo"); + ret = H5Gget_objinfo(fid, "dataset", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 1, "reference count in H5Gget_objinfo"); + + /* Increment each object's reference count. */ + ret = H5Oincr_refcount(grp); + CHECK(ret, FAIL, "H5Oincr_refcount"); + ret = H5Oincr_refcount(dtype); + CHECK(ret, FAIL, "H5Oincr_refcount"); + ret = H5Oincr_refcount(dset); + CHECK(ret, FAIL, "H5Oincr_refcount"); + + /* Get ref counts for each object. They should all be 2 now. */ + ret = H5Gget_objinfo(fid, "group", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 2, "reference count in H5Gget_objinfo"); + ret = H5Gget_objinfo(fid, "datatype", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 2, "reference count in H5Gget_objinfo"); + ret = H5Gget_objinfo(fid, "dataset", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 2, "reference count in H5Gget_objinfo"); + + /* Decrement the reference counts and check that they decrease back to 1. */ + ret = H5Odecr_refcount(grp); + CHECK(ret, FAIL, "H5Odecr_refcount"); + ret = H5Odecr_refcount(dtype); + CHECK(ret, FAIL, "H5Odecr_refcount"); + ret = H5Odecr_refcount(dset); + CHECK(ret, FAIL, "H5Odecr_refcount"); + + ret = H5Gget_objinfo(fid, "group", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 1, "reference count in H5Gget_objinfo"); + ret = H5Gget_objinfo(fid, "datatype", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 1, "reference count in H5Gget_objinfo"); + ret = H5Gget_objinfo(fid, "dataset", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 1, "reference count in H5Gget_objinfo"); + + /* Increment the reference counts and then close the file to make sure the increment is permanant */ + ret = H5Oincr_refcount(grp); + CHECK(ret, FAIL, "H5Oincr_refcount"); + ret = H5Oincr_refcount(dtype); + CHECK(ret, FAIL, "H5Oincr_refcount"); + ret = H5Oincr_refcount(dset); + CHECK(ret, FAIL, "H5Oincr_refcount"); + + ret = H5Gclose(grp); + CHECK(ret, FAIL, "H5Gclose"); + ret = H5Tclose(dtype); + CHECK(ret, FAIL, "H5Tclose"); + ret = H5Dclose(dset); + CHECK(ret, FAIL, "H5Dclose"); + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); + + /* Re-open the file and check that the reference counts were really incremented */ + fid = H5Fopen(TEST_FILENAME, H5F_ACC_RDWR, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fopen"); + + grp = H5Gopen(fid, "group"); + CHECK(grp, FAIL, "H5Gopen"); + dtype = H5Topen(fid, "datatype"); + CHECK(dtype, FAIL, "H5Gopen"); + dset = H5Dopen(fid, "dataset"); + CHECK(dset, FAIL, "H5Gopen"); + + ret = H5Gget_objinfo(fid, "group", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 2, "reference count in H5Gget_objinfo"); + ret = H5Gget_objinfo(fid, "datatype", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 2, "reference count in H5Gget_objinfo"); + ret = H5Gget_objinfo(fid, "dataset", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 2, "reference count in H5Gget_objinfo"); + + /* Decrement the reference counts and close the file */ + ret = H5Odecr_refcount(grp); + CHECK(ret, FAIL, "H5Odecr_refcount"); + ret = H5Odecr_refcount(dtype); + CHECK(ret, FAIL, "H5Odecr_refcount"); + ret = H5Odecr_refcount(dset); + CHECK(ret, FAIL, "H5Odecr_refcount"); + + ret = H5Gclose(grp); + CHECK(ret, FAIL, "H5Gclose"); + ret = H5Tclose(dtype); + CHECK(ret, FAIL, "H5Tclose"); + ret = H5Dclose(dset); + CHECK(ret, FAIL, "H5Dclose"); + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); + + /* Re-open the file and check that the reference counts were really decremented */ + fid = H5Fopen(TEST_FILENAME, H5F_ACC_RDWR, H5P_DEFAULT); + CHECK(fid, FAIL, "H5Fopen"); + + grp = H5Gopen(fid, "group"); + CHECK(grp, FAIL, "H5Gopen"); + dtype = H5Topen(fid, "datatype"); + CHECK(dtype, FAIL, "H5Gopen"); + dset = H5Dopen(fid, "dataset"); + CHECK(dset, FAIL, "H5Gopen"); + + ret = H5Gget_objinfo(fid, "group", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 1, "reference count in H5Gget_objinfo"); + ret = H5Gget_objinfo(fid, "datatype", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 1, "reference count in H5Gget_objinfo"); + ret = H5Gget_objinfo(fid, "dataset", FALSE, &sb); + CHECK(ret, FAIL, "H5Gget_objinfo"); + VERIFY(sb.nlink, 1, "reference count in H5Gget_objinfo"); + + /* Close the IDs */ + ret = H5Gclose(grp); + CHECK(ret, FAIL, "H5Gclose"); + ret = H5Tclose(dtype); + CHECK(ret, FAIL, "H5Tclose"); + ret = H5Dclose(dset); + CHECK(ret, FAIL, "H5Dclose"); + + /* Make sure that bogus IDs return errors properly */ + H5E_BEGIN_TRY { + ret = H5Oincr_refcount(grp); + VERIFY(ret, FAIL, "H5Oincr_refcount"); + ret = H5Oincr_refcount(dtype); + VERIFY(ret, FAIL, "H5Oincr_refcount"); + ret = H5Oincr_refcount(dset); + VERIFY(ret, FAIL, "H5Oincr_refcount"); + ret = H5Odecr_refcount(grp); + VERIFY(ret, FAIL, "H5Odecr_refcount"); + ret = H5Odecr_refcount(dtype); + VERIFY(ret, FAIL, "H5Odecr_refcount"); + ret = H5Odecr_refcount(dset); + VERIFY(ret, FAIL, "H5Odecr_refcount"); + } H5E_END_TRY + + /* Close the file */ + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); +} /* test_h5o_refcount() */ + + +/**************************************************************** +** +** test_h5o(): Main H5O (generic object) testing routine. +** +****************************************************************/ +void +test_h5o(void) +{ + /* Output message about test being performed */ + MESSAGE(5, ("Testing Objects\n")); + + test_h5o_open(); /* Test generic open function */ + test_h5o_open_by_addr(); /* Test opening objects by address */ + test_h5o_close(); /* Test generic close function */ + test_h5o_refcount(); /* Test incrementing and decrementing reference count */ +} /* test_h5o() */ + + +/*------------------------------------------------------------------------- + * Function: cleanup_h5o + * + * Purpose: Cleanup temporary test files + * + * Return: none + * + * Programmer: James Laird + * June 3, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +cleanup_h5o(void) +{ + remove(TEST_FILENAME); +} diff --git a/test/titerate.c b/test/titerate.c index 0c41ce6..4850db0 100644 --- a/test/titerate.c +++ b/test/titerate.c @@ -854,10 +854,10 @@ static void test_links(void) CHECK(gid1, FAIL, "H5Gcreate"); /* create soft and hard links to the group "/g1". */ - ret = H5Glink (gid, H5G_LINK_SOFT, "something", "softlink"); + ret = H5Glink (gid, H5L_LINK_SOFT, "something", "softlink"); CHECK(ret, FAIL, "H5Glink"); - ret = H5Glink (gid, H5G_LINK_HARD, "/g1", "hardlink"); + ret = H5Glink (gid, H5L_LINK_HARD, "/g1", "hardlink"); CHECK(ret, FAIL, "H5Glink"); ret = H5Gget_num_objs(gid, &nobjs); diff --git a/test/tmisc.c b/test/tmisc.c index cc4d7b2..b89a9a6 100644 --- a/test/tmisc.c +++ b/test/tmisc.c @@ -2850,6 +2850,7 @@ test_misc18(void) #else /* H5_HAVE_LARGE_HSIZET */ VERIFY(statbuf.ohdr.free, 160, "H5Gget_objinfo"); #endif /* H5_HAVE_LARGE_HSIZET */ + VERIFY(statbuf.linklen, 0, "H5Gget_objinfo"); /* Create second dataset */ did2 = H5Dcreate(fid, MISC18_DSET2_NAME, H5T_STD_U32LE, sid, H5P_DEFAULT); @@ -2866,6 +2867,7 @@ test_misc18(void) #else /* H5_HAVE_LARGE_HSIZET */ VERIFY(statbuf.ohdr.free, 160, "H5Gget_objinfo"); #endif /* H5_HAVE_LARGE_HSIZET */ + VERIFY(statbuf.linklen, 0, "H5Gget_objinfo"); /* Loop creating attributes on each dataset, flushing them to the file each time */ for(u=0; u<10; u++) { @@ -2905,6 +2907,7 @@ test_misc18(void) VERIFY(statbuf.ohdr.size, 888, "H5Gget_objinfo"); VERIFY(statbuf.ohdr.free, 24, "H5Gget_objinfo"); #endif /* H5_HAVE_LARGE_HSIZET */ + VERIFY(statbuf.linklen, 0, "H5Gget_objinfo"); /* Get object information for dataset #2 now */ ret = H5Gget_objinfo(fid,MISC18_DSET2_NAME,0,&statbuf); @@ -2920,6 +2923,7 @@ test_misc18(void) VERIFY(statbuf.ohdr.size, 888, "H5Gget_objinfo"); VERIFY(statbuf.ohdr.free, 24, "H5Gget_objinfo"); #endif /* H5_HAVE_LARGE_HSIZET */ + VERIFY(statbuf.linklen, 0, "H5Gget_objinfo"); /* Close second dataset */ ret = H5Dclose(did2); @@ -3844,7 +3848,7 @@ test_misc23(void) tmp_id = H5Gcreate_expand(file_id, H5P_DEFAULT, access_id); CHECK(tmp_id, FAIL, "H5Gcreate_expand"); - status = H5Llink(file_id, "/A/B01/grp", tmp_id, create_id); + status = H5Llink(file_id, "/A/B01/grp", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); /* Query that the name of the new group is correct */ @@ -3870,7 +3874,7 @@ test_misc23(void) tmp_id = H5Gcreate_expand(file_id, H5P_DEFAULT, access_id); CHECK(tmp_id, FAIL, "H5Gcreate_expand"); - status = H5Llink(file_id, "/A/B02/C02/grp", tmp_id, create_id); + status = H5Llink(file_id, "/A/B02/C02/grp", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Gclose(tmp_id); @@ -3880,7 +3884,7 @@ test_misc23(void) tmp_id = H5Gcreate_expand(group_id, H5P_DEFAULT, access_id); CHECK(tmp_id, FAIL, "H5Gcreate_expand"); - status = H5Llink(group_id, "B03/grp/", tmp_id, create_id); + status = H5Llink(group_id, "B03/grp/", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Gclose(tmp_id); @@ -3890,7 +3894,7 @@ test_misc23(void) if ( (tmp_id = H5Gcreate_expand(group_id, H5P_DEFAULT, access_id)) < 0) CHECK(tmp_id, FAIL, "H5Gcreate_expand"); - status = H5Llink(group_id, "/A/B04/grp/", tmp_id, create_id); + status = H5Llink(group_id, "/A/B04/grp/", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Gclose(tmp_id); @@ -3900,7 +3904,7 @@ test_misc23(void) if ( (tmp_id = H5Gcreate_expand(file_id, H5P_DEFAULT, access_id)) < 0) CHECK(tmp_id, FAIL, "H5Gcreate_expand"); - status = H5Llink(file_id, "/A/B05/C05/A", tmp_id, create_id); + status = H5Llink(file_id, "/A/B05/C05/A", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Gclose(tmp_id); @@ -3924,50 +3928,50 @@ test_misc23(void) CHECK(status, FAIL, "H5Pset_create_intermediate_group"); - tmp_id = H5Dcreate_expand(file_id, type_id, space_id, H5P_DEFAULT); + tmp_id = H5Dcreate_expand(file_id, type_id, space_id, H5P_DEFAULT, H5P_DEFAULT); CHECK(tmp_id, FAIL, "H5Dcreate"); - status = H5Llink(file_id, "/A/B06/dset", tmp_id, create_id); + status = H5Llink(file_id, "/A/B06/dset", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Dclose(tmp_id); CHECK(status, FAIL, "H5Dclose"); - tmp_id = H5Dcreate_expand(file_id, type_id, space_id, H5P_DEFAULT); + tmp_id = H5Dcreate_expand(file_id, type_id, space_id, H5P_DEFAULT, H5P_DEFAULT); CHECK(tmp_id, FAIL, "H5Dcreate"); - status = H5Llink(file_id, "/A/B07/B07/dset", tmp_id, create_id); + status = H5Llink(file_id, "/A/B07/B07/dset", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Dclose(tmp_id); CHECK(status, FAIL, "H5Dclose"); - tmp_id = H5Dcreate_expand(group_id, type_id, space_id, H5P_DEFAULT); + tmp_id = H5Dcreate_expand(group_id, type_id, space_id, H5P_DEFAULT, H5P_DEFAULT); CHECK(tmp_id, FAIL, "H5Dcreate"); - status = H5Llink(group_id, "B08/dset", tmp_id, create_id); + status = H5Llink(group_id, "B08/dset", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Dclose(tmp_id); CHECK(status, FAIL, "H5Dclose"); - tmp_id = H5Dcreate_expand(group_id, type_id, space_id, H5P_DEFAULT); + tmp_id = H5Dcreate_expand(group_id, type_id, space_id, H5P_DEFAULT, H5P_DEFAULT); CHECK(tmp_id, FAIL, "H5Dcreate"); - status = H5Llink(group_id, "/A/B09/dset", tmp_id, create_id); + status = H5Llink(group_id, "/A/B09/dset", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Dclose(tmp_id); CHECK(status, FAIL, "H5Dclose"); - tmp_id = H5Dcreate_expand(file_id, type_id, space_id, H5P_DEFAULT); + tmp_id = H5Dcreate_expand(file_id, type_id, space_id, H5P_DEFAULT, H5P_DEFAULT); CHECK(tmp_id, FAIL, "H5Dcreate"); - status = H5Llink(file_id, "/A/B10/C10/A/dset", tmp_id, create_id); + status = H5Llink(file_id, "/A/B10/C10/A/dset", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Dclose(tmp_id); @@ -4002,7 +4006,7 @@ test_misc23(void) status = H5Tcommit_expand(file_id, tmp_id, H5P_DEFAULT, access_id); CHECK(status, FAIL, "H5Tcommit_expand"); - status = H5Llink(file_id, "/A/B11/dtype", tmp_id, create_id); + status = H5Llink(file_id, "/A/B11/dtype", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Tclose(tmp_id); @@ -4015,7 +4019,7 @@ test_misc23(void) status = H5Tcommit_expand(file_id, tmp_id, H5P_DEFAULT, access_id); CHECK(status, FAIL, "H5Tcommit_expand"); - status = H5Llink(file_id, "/A/B12/C12/dtype", tmp_id, create_id); + status = H5Llink(file_id, "/A/B12/C12/dtype", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Tclose(tmp_id); @@ -4028,7 +4032,7 @@ test_misc23(void) status = H5Tcommit_expand(group_id, tmp_id, H5P_DEFAULT, access_id); CHECK(status, FAIL, "H5Tcommit_expand"); - status = H5Llink(group_id, "B13/C12/dtype", tmp_id, create_id); + status = H5Llink(group_id, "B13/C12/dtype", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Tclose(tmp_id); @@ -4041,7 +4045,7 @@ test_misc23(void) status = H5Tcommit_expand(group_id, tmp_id, H5P_DEFAULT, access_id); CHECK(status, FAIL, "H5Tcommit_expand"); - status = H5Llink(group_id, "/A/B14/dtype", tmp_id, create_id); + status = H5Llink(group_id, "/A/B14/dtype", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Tclose(tmp_id); @@ -4054,7 +4058,7 @@ test_misc23(void) status = H5Tcommit_expand(file_id, tmp_id, H5P_DEFAULT, access_id); CHECK(status, FAIL, "H5Tcommit_expand"); - status = H5Llink(file_id, "/A/B15/C15/A/dtype", tmp_id, create_id); + status = H5Llink(file_id, "/A/B15/C15/A/dtype", tmp_id, create_id, H5P_DEFAULT); CHECK(status, FAIL, "H5Llink"); status = H5Tclose(tmp_id); @@ -4110,13 +4114,13 @@ test_misc24(void) CHECK(ret, FAIL, "H5Tcommit"); /* Create soft links to the objects created */ - ret = H5Glink2(file_id, MISC24_GROUP_NAME, H5G_LINK_SOFT, file_id, MISC24_GROUP_LINK); + ret = H5Glink2(file_id, MISC24_GROUP_NAME, H5L_LINK_SOFT, file_id, MISC24_GROUP_LINK); CHECK(ret, FAIL, "H5Glink2"); - ret = H5Glink2(file_id, MISC24_DATASET_NAME, H5G_LINK_SOFT, file_id, MISC24_DATASET_LINK); + ret = H5Glink2(file_id, MISC24_DATASET_NAME, H5L_LINK_SOFT, file_id, MISC24_DATASET_LINK); CHECK(ret, FAIL, "H5Glink2"); - ret = H5Glink2(file_id, MISC24_DATATYPE_NAME, H5G_LINK_SOFT, file_id, MISC24_DATATYPE_LINK); + ret = H5Glink2(file_id, MISC24_DATATYPE_NAME, H5L_LINK_SOFT, file_id, MISC24_DATATYPE_LINK); CHECK(ret, FAIL, "H5Glink2"); /* Close IDs for objects */ diff --git a/test/unlink.c b/test/unlink.c index d86e4eb..1ad3790 100644 --- a/test/unlink.c +++ b/test/unlink.c @@ -19,8 +19,14 @@ * Purpose: Test H5Gunlink(). */ +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ + +/* Define this macro to indicate that the testing APIs should be available */ +#define H5G_TESTING + #include <time.h> #include "h5test.h" +#include "H5Gpkg.h" /* Groups */ const char *FILENAME[] = { "unlink", @@ -33,6 +39,7 @@ const char *FILENAME[] = { "resurrect_type", "resurrect_group", "unlink_chunked", + "full_group", NULL }; @@ -68,6 +75,9 @@ const char *FILENAME[] = { #define SLASHES_SOFTLINK_NAME "Soft///" #define SLASHES_SOFTLINK2_NAME "Soft2///" #define SLASHES_ROOTLINK_NAME "Root///" +#define FULL_GROUP_NUM_KEEP 2 +#define FULL_GROUP_NUM_DELETE_COMPACT 2 +#define FULL_GROUP_NUM_DELETE_DENSE 16 /*------------------------------------------------------------------------- @@ -170,7 +180,7 @@ test_many(hid_t file) TESTING("forward unlink"); for (i=0; i<how_many; i++) { sprintf(name, "obj_%05d", i); - if (H5Glink(work, H5G_LINK_HARD, "/test_many_foo", name)<0) goto error; + if (H5Glink(work, H5L_LINK_HARD, "/test_many_foo", name)<0) goto error; } for (i=0; i<how_many; i++) { sprintf(name, "obj_%05d", i); @@ -182,7 +192,7 @@ test_many(hid_t file) TESTING("backward unlink"); for (i=0; i<how_many; i++) { sprintf(name, "obj_%05d", i); - if (H5Glink(work, H5G_LINK_HARD, "/test_many_foo", name)<0) goto error; + if (H5Glink(work, H5L_LINK_HARD, "/test_many_foo", name)<0) goto error; } for (i=how_many-1; i>=0; --i) { sprintf(name, "obj_%05d", i); @@ -194,7 +204,7 @@ test_many(hid_t file) TESTING("inward unlink"); for (i=0; i<how_many; i++) { sprintf(name, "obj_%05d", i); - if (H5Glink(work, H5G_LINK_HARD, "/test_many_foo", name)<0) goto error; + if (H5Glink(work, H5L_LINK_HARD, "/test_many_foo", name)<0) goto error; } for (i=0; i<how_many; i++) { if (i%2) { @@ -210,7 +220,7 @@ test_many(hid_t file) TESTING("outward unlink"); for (i=0; i<how_many; i++) { sprintf(name, "obj_%05d", i); - if (H5Glink(work, H5G_LINK_HARD, "/test_many_foo", name)<0) goto error; + if (H5Glink(work, H5L_LINK_HARD, "/test_many_foo", name)<0) goto error; } for (i=how_many-1; i>=0; --i) { if (i%2) { @@ -259,7 +269,7 @@ test_symlink(hid_t file) /* Create a test group and symlink */ if ((work=H5Gcreate(file, "/test_symlink", 0))<0) TEST_ERROR; - if (H5Glink(work, H5G_LINK_SOFT, "link_value", "link")<0) TEST_ERROR; + if (H5Glink(work, H5L_LINK_SOFT, "link_value", "link")<0) TEST_ERROR; if (H5Gunlink(work, "link")<0) TEST_ERROR; /* Cleanup */ @@ -310,7 +320,7 @@ test_rename(hid_t file) /* Try renaming a symlink */ TESTING("symlink renaming"); - if (H5Glink(work, H5G_LINK_SOFT, "link_value", "link_one")<0) goto error; + if (H5Glink(work, H5L_LINK_SOFT, "link_value", "link_one")<0) goto error; if (H5Gmove(work, "link_one", "link_two")<0) goto error; PASSED(); @@ -368,9 +378,9 @@ test_new_move(void) if((grp_move=H5Gcreate(grp_1, "group_move", 0))<0) goto error; /* Create hard and soft links. */ - if(H5Glink2(grp_1, "group_move", H5G_LINK_HARD, H5G_SAME_LOC, "hard")<0) + if(H5Glink2(grp_1, "group_move", H5L_LINK_HARD, H5G_SAME_LOC, "hard")<0) goto error; - if(H5Glink2(grp_1, "/group1/group_move", H5G_LINK_SOFT, grp_2, "soft")<0) + if(H5Glink2(grp_1, "/group1/group_move", H5L_LINK_SOFT, grp_2, "soft")<0) goto error; /* Move a group within the file. Both of source and destination use @@ -1357,22 +1367,22 @@ test_link_slashes(void) if(H5Gclose(gid2)<0) TEST_ERROR; /* Create a hard link to the nested group */ - if(H5Glink2(gid, SLASHES_GROUP_NAME, H5G_LINK_HARD, H5G_SAME_LOC, SLASHES_HARDLINK_NAME)<0) TEST_ERROR; + if(H5Glink2(gid, SLASHES_GROUP_NAME, H5L_LINK_HARD, H5G_SAME_LOC, SLASHES_HARDLINK_NAME)<0) TEST_ERROR; /* Create a soft link with a relative path to the nested group */ - if(H5Glink2(gid, SLASHES_GROUP_NAME, H5G_LINK_SOFT, H5G_SAME_LOC, SLASHES_SOFTLINK_NAME)<0) TEST_ERROR; + if(H5Glink2(gid, SLASHES_GROUP_NAME, H5L_LINK_SOFT, H5G_SAME_LOC, SLASHES_SOFTLINK_NAME)<0) TEST_ERROR; /* Create a soft link with the full path to the nested group */ - if(H5Glink2(gid, "////"SLASHES_GROUP_NAME""SLASHES_GROUP_NAME, H5G_LINK_SOFT, H5G_SAME_LOC, SLASHES_SOFTLINK2_NAME)<0) TEST_ERROR; + if(H5Glink2(gid, "////"SLASHES_GROUP_NAME""SLASHES_GROUP_NAME, H5L_LINK_SOFT, H5G_SAME_LOC, SLASHES_SOFTLINK2_NAME)<0) TEST_ERROR; /* Create a soft link to the root group */ - if(H5Glink2(gid, "////", H5G_LINK_SOFT, H5G_SAME_LOC, SLASHES_ROOTLINK_NAME)<0) TEST_ERROR; + if(H5Glink2(gid, "////", H5L_LINK_SOFT, H5G_SAME_LOC, SLASHES_ROOTLINK_NAME)<0) TEST_ERROR; /* Close the group */ if(H5Gclose(gid)<0) TEST_ERROR; /* Create a hard link to the existing group */ - if(H5Glink2(fid, SLASHES_GROUP_NAME, H5G_LINK_HARD, H5G_SAME_LOC, SLASHES_HARDLINK_NAME)<0) TEST_ERROR; + if(H5Glink2(fid, SLASHES_GROUP_NAME, H5L_LINK_HARD, H5G_SAME_LOC, SLASHES_HARDLINK_NAME)<0) TEST_ERROR; /* Close the file */ if(H5Fclose(fid)<0) TEST_ERROR; @@ -1861,7 +1871,7 @@ test_resurrect_dataset(void) if(H5Iget_name(d, NULL, 0) != 0) TEST_ERROR; /* Re-link the dataset to the group hierarchy (shouldn't get deleted now) */ - if(H5Glink2(d, ".", H5G_LINK_HARD, f, DATASET2NAME)<0) TEST_ERROR; + if(H5Glink2(d, ".", H5L_LINK_HARD, f, DATASET2NAME)<0) TEST_ERROR; /* Close things */ if(H5Dclose(d)<0) TEST_ERROR; @@ -1934,7 +1944,7 @@ test_resurrect_datatype(void) if(H5Iget_name(type, NULL, 0) != 0) TEST_ERROR; /* Re-link the datatype to the group hierarchy (shouldn't get deleted now) */ - if(H5Glink2(type, ".", H5G_LINK_HARD, file, TYPE2NAME) < 0) TEST_ERROR; + if(H5Glink2(type, ".", H5L_LINK_HARD, file, TYPE2NAME) < 0) TEST_ERROR; /* Close things */ if(H5Tclose(type)<0) TEST_ERROR; @@ -2003,7 +2013,7 @@ test_resurrect_group(void) if(H5Iget_name(group, NULL, 0) != 0) TEST_ERROR; /* Re-link the group into the group hierarchy (shouldn't get deleted now) */ - if(H5Glink2(group, ".", H5G_LINK_HARD, file, GROUP2NAME)<0) TEST_ERROR; + if(H5Glink2(group, ".", H5L_LINK_HARD, file, GROUP2NAME)<0) TEST_ERROR; /* Close things */ if(H5Gclose(group)<0) TEST_ERROR; @@ -2121,6 +2131,269 @@ error: return 1; } /* end test_unlink_chunked_dataset() */ +#ifdef H5_GROUP_REVISION + +/*------------------------------------------------------------------------- + * Function: test_full_group_compact + * + * Purpose: Test deleting a compact group which still has valid objects in it + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Wednesday, January 18, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_full_group_compact(void) +{ + hid_t fapl_id = -1; + hid_t file_id = -1; + hid_t gid = -1, gid2 = -1; /* Group IDs */ + H5G_stat_t sb; /* Stat buffer for object */ + char objname[128]; /* Buffer for name of objects to create */ + char objname2[128]; /* Buffer for name of objects to create */ + char filename[1024]; /* Buffer for filename */ + off_t keep_size; /* Size of the file with objects to keep */ + off_t file_size; /* Size of each file created */ + unsigned u; /* Local index variable */ + + TESTING("unlinking non-empty compact group"); + + /* Create file */ + fapl_id = h5_fileaccess(); + h5_fixname(FILENAME[10], fapl_id, filename, sizeof filename); + + /* Create the file */ + if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id))<0) TEST_ERROR + + /* Create group to link objects to */ + if((gid = H5Gcreate(file_id, "/keep", (size_t)0)) < 0) TEST_ERROR + + /* Create several objects to link to */ + for(u = 0; u < FULL_GROUP_NUM_KEEP; u++) { + sprintf(objname, "keep %u\n", u); + if((gid2 = H5Gcreate(gid, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid2) < 0) TEST_ERROR + } /* end for */ + + /* Close group with objects to keep */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Close the file */ + if(H5Fclose(file_id) < 0) TEST_ERROR + + /* Get the size of the file with only the objects to keep */ + if((keep_size = h5_get_file_size(filename)) == 0) TEST_ERROR + + /* Re-open the file */ + if((file_id = H5Fopen(filename, H5F_ACC_RDWR, fapl_id)) < 0) TEST_ERROR + + /* Create group to delete */ + if((gid = H5Gcreate(file_id, "/delete", (size_t)0)) < 0) goto error; + + /* Create external link (doesn't matter if it dangles) */ + if(H5Lcreate_external("foo.h5", "/dst", gid, "external", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Create soft link (doesn't matter if it dangles) */ + if(H5Glink2(file_id, "/foo", H5L_LINK_SOFT, gid, "soft") < 0) TEST_ERROR + + /* Create hard links to objects in group to keep */ + for(u = 0; u < FULL_GROUP_NUM_KEEP; u++) { + sprintf(objname, "/keep/keep %u\n", u); + sprintf(objname2, "keep %u\n", u); + if(H5Glink2(file_id, objname, H5L_LINK_HARD, gid, objname2) < 0) TEST_ERROR + } /* end for */ + + /* Create several objects to delete */ + for(u = 0; u < FULL_GROUP_NUM_DELETE_COMPACT; u++) { + sprintf(objname, "delete %u\n", u); + if((gid2 = H5Gcreate(gid, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid2) < 0) TEST_ERROR + } /* end for */ + + /* Check on group's status */ + if(H5G_is_empty_test(gid) == TRUE) TEST_ERROR; + if(H5G_has_links_test(gid, NULL) != TRUE) TEST_ERROR; + if(H5G_has_stab_test(gid) == TRUE) TEST_ERROR; + + /* Close group with objects to delete */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Check reference count on objects to keep */ + for(u = 0; u < FULL_GROUP_NUM_KEEP; u++) { + sprintf(objname, "/keep/keep %u\n", u); + if(H5Gget_objinfo(file_id, objname, TRUE, &sb) < 0) TEST_ERROR + if(sb.nlink != 2) TEST_ERROR + } /* end for */ + + /* Close the file */ + if(H5Fclose(file_id) < 0) TEST_ERROR + + + /* Re-open the file */ + if((file_id = H5Fopen(filename, H5F_ACC_RDWR, fapl_id)) < 0) TEST_ERROR + + /* Delete the full group */ + if(H5Gunlink(file_id, "/delete") < 0) TEST_ERROR + + /* Check reference count on objects to keep */ + for(u = 0; u < FULL_GROUP_NUM_KEEP; u++) { + sprintf(objname, "/keep/keep %u\n", u); + if(H5Gget_objinfo(file_id, objname, TRUE, &sb) < 0) TEST_ERROR + if(sb.nlink != 1) TEST_ERROR + } /* end for */ + + /* Close the file */ + if(H5Fclose(file_id) < 0) TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) TEST_ERROR + + /* Verify the file is correct size */ + if(file_size != keep_size) TEST_ERROR + + /* Close the file access property list */ + if(H5Pclose(fapl_id) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gid2); + H5Gclose(gid); + H5Fclose(file_id); + H5Pclose(fapl_id); + } H5E_END_TRY; + return 1; +} /* end test_full_group_compact() */ + + +/*------------------------------------------------------------------------- + * Function: test_full_group_dense + * + * Purpose: Test deleting a dense group which still has valid objects in it + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Wednesday, January 18, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_full_group_dense(void) +{ + hid_t fapl_id = -1; + hid_t file_id = -1; + hid_t gid = -1, gid2 = -1; /* Group IDs */ + H5G_stat_t sb; /* Stat buffer for object */ + char objname[128]; /* Buffer for name of objects to create */ + char objname2[128]; /* Buffer for name of objects to create */ + char filename[1024]; /* Buffer for filename */ + unsigned u; /* Local index variable */ + + TESTING("unlinking non-empty dense group"); + + /* Create file */ + fapl_id = h5_fileaccess(); + h5_fixname(FILENAME[10], fapl_id, filename, sizeof filename); + + /* Create the file */ + if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id))<0) TEST_ERROR + + /* Create group to link objects to */ + if((gid = H5Gcreate(file_id, "/keep", (size_t)0)) < 0) TEST_ERROR + + /* Create several objects to link to */ + for(u = 0; u < FULL_GROUP_NUM_KEEP; u++) { + sprintf(objname, "keep %u\n", u); + if((gid2 = H5Gcreate(gid, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid2) < 0) TEST_ERROR + } /* end for */ + + /* Close group with objects to keep */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Create group to delete */ + if((gid = H5Gcreate(file_id, "/delete", (size_t)0)) < 0) goto error; + + /* Create external link (doesn't matter if it dangles) */ + if(H5Lcreate_external("foo.h5", "/dst", gid, "external", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR + + /* Create soft link (doesn't matter if it dangles) */ + if(H5Glink2(file_id, "/foo", H5L_LINK_SOFT, gid, "soft") < 0) TEST_ERROR + + /* Create hard links to objects in group to keep */ + for(u = 0; u < FULL_GROUP_NUM_KEEP; u++) { + sprintf(objname, "/keep/keep %u\n", u); + sprintf(objname2, "keep %u\n", u); + if(H5Glink2(file_id, objname, H5L_LINK_HARD, gid, objname2) < 0) TEST_ERROR + } /* end for */ + + /* Create several objects to delete */ + for(u = 0; u < FULL_GROUP_NUM_DELETE_DENSE; u++) { + sprintf(objname, "delete %u\n", u); + if((gid2 = H5Gcreate(gid, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(gid2) < 0) TEST_ERROR + } /* end for */ + + /* Check on group's status */ + if(H5G_is_empty_test(gid) == TRUE) TEST_ERROR; + if(H5G_has_links_test(gid, NULL) == TRUE) TEST_ERROR; + if(H5G_has_stab_test(gid) != TRUE) TEST_ERROR; + + /* Close group with objects to delete */ + if(H5Gclose(gid) < 0) TEST_ERROR + + /* Check reference count on objects to keep */ + for(u = 0; u < FULL_GROUP_NUM_KEEP; u++) { + sprintf(objname, "/keep/keep %u\n", u); + if(H5Gget_objinfo(file_id, objname, TRUE, &sb) < 0) TEST_ERROR + if(sb.nlink != 2) TEST_ERROR + } /* end for */ + + /* Close the file */ + if(H5Fclose(file_id) < 0) TEST_ERROR + + + /* Re-open the file */ + if((file_id = H5Fopen(filename, H5F_ACC_RDWR, fapl_id)) < 0) TEST_ERROR + + /* Delete the full group */ + if(H5Gunlink(file_id, "/delete") < 0) TEST_ERROR + + /* Check reference count on objects to keep */ + for(u = 0; u < FULL_GROUP_NUM_KEEP; u++) { + sprintf(objname, "/keep/keep %u\n", u); + if(H5Gget_objinfo(file_id, objname, TRUE, &sb) < 0) TEST_ERROR + if(sb.nlink != 1) TEST_ERROR + } /* end for */ + + /* Close the file */ + if(H5Fclose(file_id) < 0) TEST_ERROR + + /* Close the file access property list */ + if(H5Pclose(fapl_id) < 0) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gid2); + H5Gclose(gid); + H5Fclose(file_id); + H5Pclose(fapl_id); + } H5E_END_TRY; + return 1; +} /* end test_full_group_dense() */ +#endif /* H5_GROUP_REVISION */ + /*------------------------------------------------------------------------- * Function: main @@ -2209,13 +2482,20 @@ main(void) /* Test unlinking chunked datasets */ nerrors += test_unlink_chunked_dataset(); - /* Close */ - if (H5Pclose(fapl2)<0) TEST_ERROR; - if (H5Fclose(file)<0) TEST_ERROR; - if (nerrors) { - printf("***** %d FAILURE%s! *****\n", nerrors, 1==nerrors?"":"S"); +#ifdef H5_GROUP_REVISION + /* Test unlinked groups which still have objects in them */ + nerrors += test_full_group_compact(); + nerrors += test_full_group_dense(); +#endif /* H5_GROUP_REVISION */ + + /* Close */ + if (H5Pclose(fapl2)<0) TEST_ERROR; + if (H5Fclose(file)<0) TEST_ERROR; + if (nerrors) { + printf("***** %d FAILURE%s! *****\n", nerrors, 1==nerrors?"":"S"); exit(1); } + puts("All unlink tests passed."); h5_cleanup(FILENAME, fapl); } |