summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Kim <jkm@hdfgroup.org>2010-06-02 15:13:13 (GMT)
committerJonathan Kim <jkm@hdfgroup.org>2010-06-02 15:13:13 (GMT)
commit1a02e37f167159e817b3230f95d0900aa82af8aa (patch)
tree1c9b9883a0e50de8b9b73800080d595919af3e8a
parent1f14f80226663c45d07b3627daca20b83d32e219 (diff)
downloadhdf5-1a02e37f167159e817b3230f95d0900aa82af8aa.zip
hdf5-1a02e37f167159e817b3230f95d0900aa82af8aa.tar.gz
hdf5-1a02e37f167159e817b3230f95d0900aa82af8aa.tar.bz2
[svn-r18943] Purpose:
Support follow symbolic links. Description: Add '--follow-symlinks' option to follow symbolic links (soft and external). Update help page according to RM. Remove some warning messages from compiler. Tested: jam, amani and linew
-rw-r--r--MANIFEST11
-rw-r--r--release_docs/RELEASE.txt2
-rw-r--r--tools/h5dump/h5dumpgentest.c277
-rw-r--r--tools/h5ls/CMakeLists.txt75
-rw-r--r--tools/h5ls/h5ls.c300
-rw-r--r--tools/h5ls/testh5ls.sh.in27
-rw-r--r--tools/testfiles/help-1.ls62
-rw-r--r--tools/testfiles/help-2.ls62
-rw-r--r--tools/testfiles/help-3.ls62
-rw-r--r--tools/testfiles/textlinksrc-1-old.ls19
-rw-r--r--tools/testfiles/textlinksrc-1.ls2
-rw-r--r--tools/testfiles/textlinksrc-2-old.ls8
-rw-r--r--tools/testfiles/textlinksrc-2.ls2
-rw-r--r--tools/testfiles/textlinksrc-3-old.ls14
-rw-r--r--tools/testfiles/textlinksrc-3.ls2
-rw-r--r--tools/testfiles/textlinksrc-6-old.ls8
-rw-r--r--tools/testfiles/textlinksrc-6.ls2
-rw-r--r--tools/testfiles/textlinksrc-7-old.ls4
-rw-r--r--tools/testfiles/textlinksrc-7.ls2
-rw-r--r--tools/testfiles/tgroup-1.ls62
-rw-r--r--tools/testfiles/tsoftlinks-1.ls13
-rw-r--r--tools/testfiles/tsoftlinks-2.ls24
-rw-r--r--tools/testfiles/tsoftlinks-3.ls8
-rw-r--r--tools/testfiles/tsoftlinks-4.ls8
-rw-r--r--tools/testfiles/tsoftlinks-5.ls4
-rw-r--r--tools/testfiles/tsoftlinks.h5bin0 -> 6352 bytes
26 files changed, 842 insertions, 218 deletions
diff --git a/MANIFEST b/MANIFEST
index ec31e83..d110b65 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1211,7 +1211,18 @@
./tools/testfiles/textlinksrc-5.ls
./tools/testfiles/textlinksrc-6.ls
./tools/testfiles/textlinksrc-7.ls
+./tools/testfiles/textlinksrc-1-old.ls
+./tools/testfiles/textlinksrc-2-old.ls
+./tools/testfiles/textlinksrc-3-old.ls
+./tools/testfiles/textlinksrc-6-old.ls
+./tools/testfiles/textlinksrc-7-old.ls
./tools/testfiles/textlinktar.h5
+./tools/testfiles/tsoftlinks.h5
+./tools/testfiles/tsoftlinks-1.ls
+./tools/testfiles/tsoftlinks-2.ls
+./tools/testfiles/tsoftlinks-3.ls
+./tools/testfiles/tsoftlinks-4.ls
+./tools/testfiles/tsoftlinks-5.ls
./tools/testfiles/tfamily.ddl
./tools/testfiles/tfamily00000.h5
./tools/testfiles/tfamily00001.h5
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index b1671d3..141c113 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -159,6 +159,8 @@ New Features
Tools:
------
+ - h5ls: Add new flag --follow-symlinks. (refer to --help for details)
+ (JKM - 2010/05/25)
- h5diff: Add new flag --no-dangling-links. (refer to --help for details)
(JKM - 2010/02/10)
- h5diff: Add new flag --follow-symlinks. (refer to --help for details)
diff --git a/tools/h5dump/h5dumpgentest.c b/tools/h5dump/h5dumpgentest.c
index 6b75aa3..531cdcd 100644
--- a/tools/h5dump/h5dumpgentest.c
+++ b/tools/h5dump/h5dumpgentest.c
@@ -35,6 +35,7 @@
#define FILE2 "tdset.h5"
#define FILE3 "tattr.h5"
#define FILE4 "tslink.h5"
+#define FILE4_1 "tsoftlinks.h5"
#define FILE5 "thlink.h5"
#define FILE6 "tcompound.h5"
#define FILE7 "tall.h5"
@@ -94,7 +95,7 @@
#define FILE61 "textlinksrc.h5"
#define FILE62 "textlinktar.h5"
#define FILE63 "textlinkfar.h5"
-#define FILE64 "tarray8.h5"
+/*#define FILE64 "tarray8.h5"*/
#define FILE65 "tattrreg.h5"
#define FILE66 "file_space.h5"
@@ -213,7 +214,8 @@ typedef struct s1_t {
#define ARRAY3_DIM2 3
/* VL string datatype name */
-#define VLSTR_TYPE "vl_string_type"
+/* TODO remove complier error not used, remove the link when everything is OK */
+/* #define VLSTR_TYPE "vl_string_type" */
/* "File 41" macros */
/* Name of dataset to create in datafile */
@@ -466,6 +468,246 @@ static void gent_softlink(void)
H5Fclose(fid);
}
+/*-------------------------------------------------------------------------
+ * Function: gent_softlink2
+ *
+ * Purpose: Create soft links to various objects.
+ * Return:
+ * SUCCEED
+ * FAIL
+ * Programmer: Jonathan Kim
+ * Date: May 26, 2010
+ *-------------------------------------------------------------------------*/
+#define NX 4
+#define NY 2
+static int gent_softlink2(void)
+{
+ hid_t fileid1;
+ hid_t grp1=0, grp2=0;
+ hid_t tid;
+ hid_t dset1, dset2;
+ hid_t datatype, dataspace;
+ hsize_t dimsf[2]; /* dataset dimensions */
+ herr_t status=SUCCEED;
+ int data1[NX][NY] = {{0,0},{1,1},{2,2},{3,3}};
+ int data2[NX][NY] = {{0,0},{0,1},{0,2},{3,3}};
+
+ /*-----------------------------------------------------------------------
+ * FILE
+ *------------------------------------------------------------------------*/
+ /* Create a new file */
+ fileid1 = H5Fcreate(FILE4_1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ if (fileid1 < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Fcreate failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /*-----------------------------------------------------------------------
+ * Groups
+ *------------------------------------------------------------------------*/
+ grp1 = H5Gcreate2(fileid1, "group1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ if (grp1 < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Gcreate2 failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ grp2 = H5Gcreate2(fileid1, "group_empty", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ if (grp2 < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Gcreate2 failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /*-----------------------------------------------------------------------
+ * Named datatype
+ *------------------------------------------------------------------------*/
+ tid = H5Tcopy(H5T_NATIVE_INT);
+ status = H5Tcommit2(fileid1, "dtype", tid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Tcommit2 failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /*-----------------------------------------------------------------------
+ * Datasets
+ *------------------------------------------------------------------------*/
+ /*
+ * Describe the size of the array and create the data space for fixed
+ * size dataset.
+ */
+ dimsf[0] = NX;
+ dimsf[1] = NY;
+ dataspace = H5Screate_simple(2, dimsf, NULL);
+
+ /*
+ * Define datatype for the data in the file.
+ * We will store little endian INT numbers.
+ */
+ datatype = H5Tcopy(H5T_NATIVE_INT);
+
+ /*---------------
+ * dset1
+ */
+ /* Create a new dataset as sample object */
+ dset1 = H5Dcreate2(fileid1, "/dset1", datatype, dataspace,
+ H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ if (dset1 < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Dcreate2 failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ status = H5Dwrite(dset1, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data1);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Dwrite failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /*---------------
+ * dset2
+ */
+ /* Create a new dataset as sample object */
+ dset2 = H5Dcreate2(fileid1, "/dset2", datatype, dataspace,
+ H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ if (dset2 < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Dcreate2 failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ status = H5Dwrite(dset2, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data2);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Dwrite failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /*-----------------------------------------------------------------------
+ * Soft links
+ *------------------------------------------------------------------------*/
+ /*
+ * create various soft links under '/' root
+ */
+ /* link to dset1 */
+ status = H5Lcreate_soft("/dset1", fileid1, "soft_dset1", H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Lcreate_soft failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /* link to data type */
+ status = H5Lcreate_soft("/dtype", fileid1, "soft_dtype", H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Lcreate_soft failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /* link to group1 */
+ status = H5Lcreate_soft("/group1", fileid1, "soft_group1", H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Lcreate_soft failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /* link to empty group */
+ status = H5Lcreate_soft("/group_empty", fileid1, "soft_empty_grp", H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Lcreate_soft failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /* dangling link */
+ status = H5Lcreate_soft("not_yet", fileid1, "soft_dangle", H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Lcreate_soft failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /*-----------------------------------------
+ * create various soft links under a group
+ */
+ /* link to dset1 */
+ status = H5Lcreate_soft("/dset1", grp1, "soft_dset1", H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Lcreate_soft failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /* link to dset2 */
+ status = H5Lcreate_soft("/dset2", grp1, "soft_dset2", H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Lcreate_soft failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /* link to data type */
+ status = H5Lcreate_soft("/dtype", grp1, "soft_dtype", H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Lcreate_soft failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /* link to empty group */
+ status = H5Lcreate_soft("/group_empty", grp1, "soft_empty_grp", H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Lcreate_soft failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+ /* dangling link */
+ status = H5Lcreate_soft("not_yet", grp1, "soft_dangle", H5P_DEFAULT, H5P_DEFAULT);
+ if (status < 0)
+ {
+ fprintf(stderr, "Error: %s> H5Lcreate_soft failed.\n", FILE4_1);
+ status = FAIL;
+ goto out;
+ }
+
+out:
+ /*
+ * Close/release resources.
+ */
+ H5Sclose(dataspace);
+ H5Gclose(grp1);
+ H5Gclose(grp2);
+ H5Tclose(datatype);
+ H5Dclose(dset1);
+ H5Dclose(dset2);
+ H5Fclose(fileid1);
+
+ return status;
+}
+
/*
/
@@ -1661,7 +1903,7 @@ static void gent_objref(void)
hid_t sid1; /* Dataspace ID */
hid_t tid1; /* Datatype ID */
hsize_t dims1[] = {SPACE1_DIM1};
- hobj_ref_t *wbuf, /* buffer to write to disk */
+ hobj_ref_t *wbuf, /* buffer to write to disk */
*rbuf, /* buffer read from disk */
*tbuf; /* temp. buffer read from disk */
uint32_t *tu32; /* Temporary pointer to uint32 data */
@@ -1669,9 +1911,9 @@ static void gent_objref(void)
const char *write_comment = "Foo!"; /* Comments for group */
/* Allocate write & read buffers */
- wbuf = malloc(sizeof(hobj_ref_t) * SPACE1_DIM1);
- rbuf = malloc(sizeof(hobj_ref_t) * SPACE1_DIM1);
- tbuf = malloc(sizeof(hobj_ref_t) * SPACE1_DIM1);
+ wbuf = (hobj_ref_t*) malloc(sizeof(hobj_ref_t) * SPACE1_DIM1);
+ rbuf = (hobj_ref_t*) malloc(sizeof(hobj_ref_t) * SPACE1_DIM1);
+ tbuf = (hobj_ref_t*) malloc(sizeof(hobj_ref_t) * SPACE1_DIM1);
/* Create file */
fid1 = H5Fcreate(FILE16, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
@@ -1779,10 +2021,10 @@ static void gent_datareg(void)
int i; /* counting variables */
/* Allocate write & read buffers */
- wbuf=calloc(sizeof(hdset_reg_ref_t), SPACE1_DIM1);
- rbuf=malloc(sizeof(hdset_reg_ref_t)*SPACE1_DIM1);
- dwbuf=malloc(sizeof(uint8_t)*SPACE2_DIM1*SPACE2_DIM2);
- drbuf=calloc(sizeof(uint8_t),SPACE2_DIM1*SPACE2_DIM2);
+ wbuf = (hdset_reg_ref_t*) calloc(sizeof(hdset_reg_ref_t), SPACE1_DIM1);
+ rbuf = (hdset_reg_ref_t*) malloc(sizeof(hdset_reg_ref_t)*SPACE1_DIM1);
+ dwbuf = (uint8_t*) malloc(sizeof(uint8_t)*SPACE2_DIM1*SPACE2_DIM2);
+ drbuf = (uint8_t*) calloc(sizeof(uint8_t),SPACE2_DIM1*SPACE2_DIM2);
/* Create file */
fid1 = H5Fcreate(FILE17, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
@@ -1888,10 +2130,10 @@ static void gent_attrreg(void)
int i; /* counting variables */
/* Allocate write & read buffers */
- wbuf=calloc(sizeof(hdset_reg_ref_t), SPACE1_DIM1);
- rbuf=malloc(sizeof(hdset_reg_ref_t)*SPACE1_DIM1);
- dwbuf=malloc(sizeof(uint8_t)*SPACE2_DIM1*SPACE2_DIM2);
- drbuf=calloc(sizeof(uint8_t),SPACE2_DIM1*SPACE2_DIM2);
+ wbuf = (hdset_reg_ref_t*) calloc(sizeof(hdset_reg_ref_t), SPACE1_DIM1);
+ rbuf = (hdset_reg_ref_t*) malloc(sizeof(hdset_reg_ref_t)*SPACE1_DIM1);
+ dwbuf = (uint8_t*) malloc(sizeof(uint8_t)*SPACE2_DIM1*SPACE2_DIM2);
+ drbuf = (uint8_t*) calloc(sizeof(uint8_t),SPACE2_DIM1*SPACE2_DIM2);
/* Create file */
fid1 = H5Fcreate(FILE65, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
@@ -2961,7 +3203,7 @@ static void gent_array8(void)
hsize_t sdims[] = {F64_DIM0};
hsize_t tdims[] = {F64_DIM1};
int wdata[(F64_DIM1) * sizeof(int)]; /* Write buffer */
- int i;
+ unsigned int i;
/*
* Initialize data. i is the element in the dataspace, j and k the
@@ -5655,7 +5897,7 @@ static void gent_longlinks(void)
assert(gid >= 0);
/* Construct very long file name */
- objname = HDmalloc((size_t)(F51_MAX_NAME_LEN + 1));
+ objname = (char*) HDmalloc((size_t)(F51_MAX_NAME_LEN + 1));
assert(objname);
for(u = 0; u < F51_MAX_NAME_LEN; u++)
objname[u] = 'a';
@@ -5919,7 +6161,7 @@ gent_hyperslab(void)
double *buf;
int i, ret;
- buf = malloc(32 * 4097 * sizeof(double) );
+ buf = (double*) malloc(32 * 4097 * sizeof(double) );
for(i = 0; i < 32 * 4097; i++)
buf[i] = 1;
@@ -6526,6 +6768,7 @@ int main(void)
gent_group();
gent_attribute();
gent_softlink();
+ gent_softlink2();
gent_dataset();
gent_hardlink();
gent_extlink();
diff --git a/tools/h5ls/CMakeLists.txt b/tools/h5ls/CMakeLists.txt
index 840f80e..fe9f927 100644
--- a/tools/h5ls/CMakeLists.txt
+++ b/tools/h5ls/CMakeLists.txt
@@ -43,6 +43,16 @@ IF (BUILD_TESTING)
textlinksrc-5.ls
textlinksrc-6.ls
textlinksrc-7.ls
+ textlinksrc-1-old.ls
+ textlinksrc-2-old.ls
+ textlinksrc-3-old.ls
+ textlinksrc-6-old.ls
+ textlinksrc-7-old.ls
+ tsoftlinks-1.ls
+ tsoftlinks-2.ls
+ tsoftlinks-3.ls
+ tsoftlinks-4.ls
+ tsoftlinks-5.ls
tgroup.ls
tgroup-1.ls
tgroup-2.ls
@@ -75,6 +85,7 @@ IF (BUILD_TESTING)
tnestedcomp.h5
tsaf.h5
tslink.h5
+ tsoftlinks.h5
tstr.h5
tudlink.h5
tvldtypes1.h5
@@ -116,39 +127,93 @@ IF (BUILD_TESTING)
)
ENDMACRO (ADD_H5_TEST file)
+ # test the help syntax
ADD_H5_TEST (help-1 0 -w80 -h)
ADD_H5_TEST (help-2 0 -w80 --help)
ADD_H5_TEST (help-3 0 -w80 -?)
+
+ # test simple command
ADD_H5_TEST (tall-1 0 -w80 tall.h5)
ADD_H5_TEST (tall-2 0 -w80 -r -d tall.h5)
ADD_H5_TEST (tgroup 0 -w80 tgroup.h5)
ADD_H5_TEST (tgroup-3 0 -w80 tgroup.h5/g1)
+
+ # test for displaying groups
+ # The following combination of arguments is expected to return an error message
+ # and return value 1
ADD_H5_TEST (tgroup-1 1 -w80 -r -g tgroup.h5)
ADD_H5_TEST (tgroup-2 0 -w80 -g tgroup.h5/g1)
+
+ # test for displaying simple space datasets
ADD_H5_TEST (tdset-1 0 -w80 -r -d tdset.h5)
+
+ # test for displaying soft links (dangle)
ADD_H5_TEST (tslink-1 0 -w80 -r tslink.h5)
+
+ # test for displaying more soft links with --follow-symlinks
+ ADD_H5_TEST (tsoftlinks-1 0 --follow-symlinks tsoftlinks.h5)
+ ADD_H5_TEST (tsoftlinks-2 0 --follow-symlinks -r tsoftlinks.h5)
+ ADD_H5_TEST (tsoftlinks-3 0 --follow-symlinks tsoftlinks.h5/group1)
+ ADD_H5_TEST (tsoftlinks-4 0 --follow-symlinks -r tsoftlinks.h5/group1)
+ ADD_H5_TEST (tsoftlinks-5 0 --follow-symlinks tsoftlinks.h5/soft_dset1)
+
+ # test for displaying external and user-defined links with --follow-symlinks
ADD_H5_TEST (textlink-1 0 -w80 -r textlink.h5)
- ADD_H5_TEST (textlinksrc-1 0 -w80 -Er textlinksrc.h5)
- ADD_H5_TEST (textlinksrc-2 0 -w80 -Erv textlinksrc.h5/ext_link5)
- ADD_H5_TEST (textlinksrc-3 0 -w80 -Er textlinksrc.h5/ext_link1)
+ ADD_H5_TEST (textlinksrc-1 0 -w80 --follow-symlinks -r textlinksrc.h5)
+ ADD_H5_TEST (textlinksrc-2 0 -w80 --follow-symlinks -rv textlinksrc.h5/ext_link5)
+ ADD_H5_TEST (textlinksrc-3 0 -w80 --follow-symlinks -r textlinksrc.h5/ext_link1)
ADD_H5_TEST (textlinksrc-4 0 -w80 -r textlinksrc.h5)
ADD_H5_TEST (textlinksrc-5 0 -w80 -r textlinksrc.h5/ext_link1)
- ADD_H5_TEST (textlinksrc-6 0 -w80 -E textlinksrc.h5)
- ADD_H5_TEST (textlinksrc-7 0 -w80 -E textlinksrc.h5/ext_link1)
+ ADD_H5_TEST (textlinksrc-6 0 -w80 --follow-symlinks textlinksrc.h5)
+ ADD_H5_TEST (textlinksrc-7 0 -w80 --follow-symlinks textlinksrc.h5/ext_link1)
ADD_H5_TEST (tudlink-1 0 -w80 -r tudlink.h5)
+
+ # test for displaying external links with -E
+ # the option -E will be depriciated but keep it for backward compatibility
+ ADD_H5_TEST (textlinksrc-1-old 0 -w80 -Er textlinksrc.h5)
+ ADD_H5_TEST (textlinksrc-2-old 0 -w80 -Erv textlinksrc.h5/ext_link5)
+ ADD_H5_TEST (textlinksrc-3-old 0 -w80 -Er textlinksrc.h5/ext_link1)
+ ADD_H5_TEST (textlinksrc-6-old 0 -w80 -E textlinksrc.h5)
+ ADD_H5_TEST (textlinksrc-7-old 0 -w80 -E textlinksrc.h5/ext_link1)
+
+ # tests for hard links
ADD_H5_TEST (thlink-1 0 -w80 thlink.h5)
+
+ # tests for compound data types
ADD_H5_TEST (tcomp-1 0 -w80 -r -d tcompound.h5)
+
+ #test for the nested compound type
ADD_H5_TEST (tnestcomp-1 0 -w80 -r -d tnestedcomp.h5)
+
+ # test for loop detection
ADD_H5_TEST (tloop-1 0 -w80 -r -d tloop.h5)
+
+ # test for string
ADD_H5_TEST (tstr-1 0 -w80 -r -d tstr.h5)
+
+ # test test file created from lib SAF team
ADD_H5_TEST (tsaf 0 -w80 -r -d tsaf.h5)
+
+ # test for variable length data types
ADD_H5_TEST (tvldtypes1 0 -w80 -r -d tvldtypes1.h5)
+
+ # test for array data types
ADD_H5_TEST (tarray1 0 -w80 -r -d tarray1.h5)
+
+ # test for empty data
ADD_H5_TEST (tempty 0 -w80 -d tempty.h5)
+
+ # test for all dataset types written to attributes
+ # enable -S for avoiding printing NATIVE types
ADD_H5_TEST (tattr2 0 -w80 -v -S tattr2.h5)
+
+ # test for non-existing file
ADD_H5_TEST (nosuchfile 1 nosuchfile.h5)
+
IF (WORDS_BIGENDIAN)
+ # test for variable length data types in verbose mode
ADD_H5_TEST (tvldtypes2be 0 -v tvldtypes1.h5)
+ # test for dataset region references data types in verbose mode
ADD_H5_TEST (tdataregbe 0 -v tdatareg.h5)
ELSE (WORDS_BIGENDIAN)
ADD_H5_TEST (tvldtypes2le 0 -v tvldtypes1.h5)
diff --git a/tools/h5ls/h5ls.c b/tools/h5ls/h5ls.c
index c856642..835af10 100644
--- a/tools/h5ls/h5ls.c
+++ b/tools/h5ls/h5ls.c
@@ -34,23 +34,24 @@
#define NAME_BUF_SIZE 2048
-/* Struct to keep track of external link targets visited */
-typedef struct elink_trav_t {
+/* Struct to keep track of symbolic link targets visited */
+typedef struct symlink_trav_t {
size_t nalloc;
size_t nused;
struct {
+ H5L_type_t type;
char *file;
char *path;
} *objs;
-} elink_trav_t;
+} symlink_trav_t;
/* Struct to pass through to visitors */
typedef struct {
const char *fname; /* Filename */
hid_t fid; /* File ID */
hid_t gid; /* Group ID */
- hbool_t ext_target; /* Whether this is the target of an external link */
- elink_trav_t *elink_list; /* List of visited external links */
+ hbool_t symlink_target; /* Whether this is the target of an symbolic link */
+ symlink_trav_t *symlink_list; /* List of visited symbolic links */
int base_len; /* Length of base path name, if not root */
int name_start; /* # of leading characters to strip off path names on output */
}iter_t;
@@ -64,6 +65,7 @@ static hbool_t label_g = FALSE; /* label compound values? */
static hbool_t string_g = FALSE; /* print 1-byte numbers as ASCII? */
static hbool_t fullname_g = FALSE; /* print full path names */
static hbool_t recursive_g = FALSE; /* recursive descent listing */
+static hbool_t follow_symlink_g = FALSE; /* follow symbolic links */
static hbool_t follow_elink_g = FALSE; /* follow external links */
static hbool_t grp_literal_g = FALSE; /* list group, not contents */
static hbool_t hexdump_g = FALSE; /* show data as raw hexadecimal */
@@ -111,30 +113,46 @@ usage (void)
{
fprintf(stderr, "\
usage: %s [OPTIONS] [OBJECTS...]\n\
- OPTIONS\n\
- -h, -?, --help Print a usage message and exit\n\
- -a, --address Print addresses for raw data\n\
- -d, --data Print the values of datasets\n\
- -e, --errors Show all HDF5 error reporting\n\
- -E, --external Allow traversal into external files\n\
- -f, --full Print full path names instead of base names\n\
- -g, --group Show information about a group, not its contents\n\
- -l, --label Label members of compound datasets\n\
- -r, --recursive List all groups recursively, avoiding cycles\n\
- -s, --string Print 1-byte integer datasets as ASCII\n\
- -S, --simple Use a machine-readable output format\n\
- -wN, --width=N Set the number of columns of output\n\
- -v, --verbose Generate more verbose output\n\
- -V, --version Print version number and exit\n\
- --vfd=DRIVER Use the specified virtual file driver\n\
- -x, --hexdump Show raw data in hexadecimal format\n\
+ OPTIONS\n\
+ -h, -?, --help Print a usage message and exit\n\
+ -a, --address Print addresses for raw data\n\
+ -d, --data Print the values of datasets\n\
+ -e, --errors Show all HDF5 error reporting\n\
+ --follow-symlinks Follow symbolic links (soft links and external links)\n\
+ to display target object information.\n\
+ Without this option, h5ls identifies a symbolic link\n\
+ as a soft link or external link and prints the value\n\
+ assigned to the symbolic link; it does not provide any\n\
+ information regarding the target object or determine\n\
+ whether the link is a dangling link.\n\
+ -f, --full Print full path names instead of base names\n\
+ -g, --group Show information about a group, not its contents\n\
+ -l, --label Label members of compound datasets\n\
+ -r, --recursive List all groups recursively, avoiding cycles\n\
+ -s, --string Print 1-byte integer datasets as ASCII\n\
+ -S, --simple Use a machine-readable output format\n\
+ -wN, --width=N Set the number of columns of output\n\
+ -v, --verbose Generate more verbose output\n\
+ -V, --version Print version number and exit\n\
+ --vfd=DRIVER Use the specified virtual file driver\n\
+ -x, --hexdump Show raw data in hexadecimal format\n\
\n\
- OBJECTS\n\
- Each object consists of an HDF5 file name optionally followed by a\n\
- slash and an object name within the file (if no object is specified\n\
- within the file then the contents of the root group are displayed).\n\
- The file name may include a printf(3C) integer format such as\n\
- \"%%05d\" to open a file family.\n",
+ OBJECTS\n\
+ Each object consists of an HDF5 file name optionally followed by a\n\
+ slash and an object name within the file (if no object is specified\n\
+ within the file then the contents of the root group are displayed).\n\
+ The file name may include a printf(3C) integer format such as\n\
+ \"%%05d\" to open a file family.\n\
+\n\
+ Deprecated Options\n\
+ The following options have been deprecated in HDF5. While they remain\n\
+ available, they have been superseded as indicated and may be removed\n\
+ from HDF5 in the future. Use the indicated replacement option in all\n\
+ new work; where possible, existing scripts, et cetera, should also be\n\
+ updated to use the replacement option.\n\
+\n\
+ -E or --external Follow external links.\n\
+ Replaced by --follow-symlinks.\n",
h5tools_getprogname());
}
@@ -469,6 +487,9 @@ display_precision(hid_t type, int ind)
case H5T_NPAD:
plsb_s = "unknown";
break;
+ default:
+ ;
+ break;
}
}
if (H5Tget_offset(type)+prec<8*H5Tget_size(type)) {
@@ -486,6 +507,9 @@ display_precision(hid_t type, int ind)
case H5T_NPAD:
pmsb_s = "unknown";
break;
+ default:
+ ;
+ break;
}
}
if (plsb_s || pmsb_s) {
@@ -646,6 +670,9 @@ display_float_type(hid_t type, int ind)
case H5T_NORM_ERROR:
norm_s = ", unknown normalization";
break;
+ default:
+ ;
+ break;
}
printf("\n%*s(significant for %lu bit%s at bit %lu%s)", ind, "",
(unsigned long)msize, 1==msize?"":"s", (unsigned long)mpos,
@@ -672,6 +699,9 @@ display_float_type(hid_t type, int ind)
case H5T_NPAD:
pad_s = "unknown";
break;
+ default:
+ ;
+ break;
}
printf("\n%*s(internal padding bits are %s)", ind, "", pad_s);
}
@@ -786,7 +816,7 @@ display_enum_type(hid_t type, int ind)
/* Get the names and raw values of all members */
name = calloc(nmembs, sizeof(char*));
- value = calloc(nmembs, MAX(H5Tget_size(type), dst_size));
+ value = (unsigned char *)calloc(nmembs, MAX(H5Tget_size(type), dst_size));
for (i=0; i<nmembs; i++) {
name[i] = H5Tget_member_name(type, i);
H5Tget_member_value(type, i, value+i*H5Tget_size(type));
@@ -889,6 +919,9 @@ display_string_type(hid_t type, int UNUSED ind)
case H5T_STR_ERROR:
pad_s = "unknown-format";
break;
+ default:
+ ;
+ break;
}
/* Character set */
@@ -917,6 +950,9 @@ display_string_type(hid_t type, int UNUSED ind)
case H5T_CSET_ERROR:
cset_s = "unknown-character-set";
break;
+ default:
+ ;
+ break;
}
if (H5Tis_variable_str(type)) {
@@ -1054,7 +1090,7 @@ display_array_type(hid_t type, int ind)
if (H5T_ARRAY!=H5Tget_class(type)) return FALSE;
ndims = H5Tget_array_ndims(type);
if (ndims) {
- dims = malloc(ndims*sizeof(dims[0]));
+ dims = (hsize_t *)malloc(ndims*sizeof(dims[0]));
H5Tget_array_dims2(type, dims);
/* Print dimensions */
@@ -1701,7 +1737,7 @@ list_obj(const char *name, const H5O_info_t *oinfo, const char *first_seen, void
iter_t *iter = (iter_t*)_iter;
/* Print the link's name, either full name or base name */
- if(!iter->ext_target)
+ if(!iter->symlink_target)
display_obj_name(stdout, iter, name, "");
/* Check object information */
@@ -1709,7 +1745,7 @@ list_obj(const char *name, const H5O_info_t *oinfo, const char *first_seen, void
printf("Unknown type(%d)", (int)oinfo->type);
obj_type = H5O_TYPE_UNKNOWN;
}
- if(iter->ext_target)
+ if(iter->symlink_target)
fputc('{', stdout);
if(obj_type >= 0 && dispatch_g[obj_type].name)
fputs(dispatch_g[obj_type].name, stdout);
@@ -1718,7 +1754,7 @@ list_obj(const char *name, const H5O_info_t *oinfo, const char *first_seen, void
if(first_seen) {
printf(", same as ");
display_string(stdout, first_seen, TRUE);
- if(!iter->ext_target)
+ if(!iter->symlink_target)
printf("\n");
} /* end if */
else {
@@ -1735,7 +1771,7 @@ list_obj(const char *name, const H5O_info_t *oinfo, const char *first_seen, void
/* List the first line of information for the object. */
if(obj_type >= 0 && dispatch_g[obj_type].list1)
(dispatch_g[obj_type].list1)(obj);
- if(!iter->ext_target || (verbose_g > 0))
+ if(!iter->symlink_target || (verbose_g > 0))
putchar('\n');
/* Show detailed information about the object, beginning with information
@@ -1787,18 +1823,18 @@ list_obj(const char *name, const H5O_info_t *oinfo, const char *first_seen, void
} /* end else */
done:
- if(iter->ext_target) {
+ if(iter->symlink_target) {
fputs("}\n", stdout);
- iter->ext_target = FALSE;
+ iter->symlink_target = FALSE;
}
return 0;
} /* end list_obj() */
/*-------------------------------------------------------------------------
- * Function: elink_trav_add
+ * Function: symlink_visit_add
*
- * Purpose: Add an external link to visited data structure
+ * Purpose: Add an symbolic link to visited data structure
*
* Return: 0 on success, -1 on failure
*
@@ -1807,16 +1843,26 @@ done:
*
* Date: September 5, 2008
*
+ * Modified:
+ * Jonathan Kim
+ * - Renamed from elink_trav_add to symlink_visit_add for both soft and
+ * external links. (May 25, 2010)
+ * - Add type parameter to distingush between soft and external link for
+ * sure, which prevent from mixing up visited link when the target names
+ * are same between the soft and external link, as code marks with the
+ * target name. (May 25,2010)
+ *
*-------------------------------------------------------------------------
*/
static herr_t
-elink_trav_add(elink_trav_t *visited, const char *file, const char *path)
+symlink_visit_add(symlink_trav_t *visited, H5L_type_t type, const char *file, const char *path)
{
size_t idx; /* Index of address to use */
void *tmp_ptr;
/* Allocate space if necessary */
- if(visited->nused == visited->nalloc) {
+ if(visited->nused == visited->nalloc)
+ {
visited->nalloc = MAX(1, visited->nalloc * 2);
if(NULL == (tmp_ptr = HDrealloc(visited->objs, visited->nalloc * sizeof(visited->objs[0]))))
return -1;
@@ -1825,24 +1871,36 @@ elink_trav_add(elink_trav_t *visited, const char *file, const char *path)
/* Append it */
idx = visited->nused++;
- if(NULL == (visited->objs[idx].file = HDstrdup(file))) {
- visited->nused--;
- return -1;
+
+ visited->objs[idx].type = type;
+ visited->objs[idx].file = NULL;
+ visited->objs[idx].path = NULL;
+
+ if (type == H5L_TYPE_EXTERNAL)
+ {
+ if(NULL == (visited->objs[idx].file = HDstrdup(file)))
+ {
+ visited->nused--;
+ return -1;
+ }
}
- if(NULL == (visited->objs[idx].path = HDstrdup(path))) {
+
+ if(NULL == (visited->objs[idx].path = HDstrdup(path)))
+ {
visited->nused--;
- HDfree (visited->objs[idx].file);
+ if (visited->objs[idx].file)
+ HDfree (visited->objs[idx].file);
return -1;
}
return 0;
-} /* end elink_trav_add() */
+} /* end symlink_visit_add() */
/*-------------------------------------------------------------------------
- * Function: elink_trav_visited
+ * Function: symlink_is_visited
*
- * Purpose: Check if an external link has already been visited
+ * Purpose: Check if an symbolic link has already been visited
*
* Return: TRUE/FALSE
*
@@ -1851,22 +1909,41 @@ elink_trav_add(elink_trav_t *visited, const char *file, const char *path)
*
* Date: September 5, 2008
*
+ * Modified:
+ * Jonathan Kim
+ * - Renamed from elink_trav_visited to symlink_is_visited for both soft and
+ * external links. (May 25, 2010)
+ * - Add type parameter to distingush between soft and external link for
+ * sure, which prevent from mixing up visited link when the target names
+ * are same between the soft and external link, as code marks with the
+ * target name. (May 25,2010)
+ *
*-------------------------------------------------------------------------
*/
static hbool_t
-elink_trav_visited(elink_trav_t *visited, const char *file, const char *path)
+symlink_is_visited(symlink_trav_t *visited, H5L_type_t type, const char *file, const char *path)
{
- size_t u; /* Local index variable */
+ size_t u; /* Local index variable */
- /* Look for elink */
+ /* Look for symlink */
for(u = 0; u < visited->nused; u++)
- /* Check for elink value already in array */
- if(!HDstrcmp(visited->objs[u].file, file) && !HDstrcmp(visited->objs[u].path, path))
- return(TRUE);
-
- /* Didn't find elink */
+ {
+ /* Check for symlink values already in array */
+ /* check type and path pair to distingush between symbolic links */
+ if ((visited->objs[u].type == type) && !HDstrcmp(visited->objs[u].path, path))
+ {
+ /* if external link, file need to be matched as well */
+ if (visited->objs[u].type == H5L_TYPE_EXTERNAL)
+ {
+ if (!HDstrcmp(visited->objs[u].file, file))
+ return (TRUE);
+ }
+ return (TRUE);
+ }
+ }
+ /* Didn't find symlink */
return(FALSE);
-} /* end elink_trav_visited() */
+} /* end symlink_is_visited() */
/*-------------------------------------------------------------------------
@@ -1886,7 +1963,7 @@ elink_trav_visited(elink_trav_t *visited, const char *file, const char *path)
static herr_t
list_lnk(const char *name, const H5L_info_t *linfo, void *_iter)
{
- char *buf;
+ char *buf=NULL;
iter_t *iter = (iter_t*)_iter;
/* Print the link's name, either full name or base name */
@@ -1894,18 +1971,52 @@ list_lnk(const char *name, const H5L_info_t *linfo, void *_iter)
switch(linfo->type) {
case H5L_TYPE_SOFT:
- if((buf = HDmalloc(linfo->u.val_size)) == NULL)
+ if((buf = (char*)HDmalloc(linfo->u.val_size)) == NULL)
goto done;
if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) {
- HDfree(buf);
goto done;
} /* end if */
HDfputs("Soft Link {", stdout);
HDfputs(buf, stdout);
- HDfree(buf);
- HDfputs("}\n", stdout);
+ HDfputc('}', stdout);
+ if(follow_symlink_g)
+ {
+ hbool_t orig_grp_literal = grp_literal_g;
+ HDfputc(' ', stdout);
+
+ /* Check if we have already seen this softlink */
+ if(symlink_is_visited(iter->symlink_list, linfo->type, NULL, buf))
+ {
+ HDfputs("{Already Visited}\n", stdout);
+ goto done;
+ }
+
+ /* Add this link to the list of seen softlinks */
+ if(symlink_visit_add(iter->symlink_list, linfo->type, NULL, buf) < 0)
+ goto done;
+
+ /* Adjust user data to specify that we are operating on the
+ * target of an soft link */
+ iter->symlink_target = TRUE;
+
+ /* Prevent recursive listing of soft link target if
+ * recursive_g is off */
+ if(!recursive_g)
+ grp_literal_g = TRUE;
+ /* Recurse through the soft link */
+ if(visit_obj(iter->fid, name, iter) < 0)
+ {
+ grp_literal_g = orig_grp_literal;
+ goto done;
+ }
+
+ grp_literal_g = orig_grp_literal;
+ }
+ else
+ HDfputc('\n', stdout);
+
break;
case H5L_TYPE_EXTERNAL:
@@ -1913,16 +2024,13 @@ list_lnk(const char *name, const H5L_info_t *linfo, void *_iter)
const char *filename;
const char *path;
- if((buf = HDmalloc(linfo->u.val_size)) == NULL)
+ if((buf = (char*)HDmalloc(linfo->u.val_size)) == NULL)
goto done;
- if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) {
- HDfree(buf);
+ if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0)
goto done;
- } /* end if */
- if(H5Lunpack_elink_val(buf, linfo->u.val_size, NULL, &filename, &path) < 0) {
- HDfree(buf);
+
+ if(H5Lunpack_elink_val(buf, linfo->u.val_size, NULL, &filename, &path) < 0)
goto done;
- } /* end if */
HDfputs("External Link {", stdout);
HDfputs(filename, stdout);
@@ -1933,27 +2041,28 @@ list_lnk(const char *name, const H5L_info_t *linfo, void *_iter)
HDfputc('}', stdout);
/* Recurse through the external link */
- if(follow_elink_g) {
+ /* keep the follow_elink_g for backward compatibility with -E */
+ if(follow_symlink_g || follow_elink_g)
+ {
hbool_t orig_grp_literal = grp_literal_g;
-
HDfputc(' ', stdout);
/* Check if we have already seen this elink */
- if(elink_trav_visited(iter->elink_list, filename, path)) {
+ if(symlink_is_visited(iter->symlink_list, linfo->type, filename, path))
+ {
HDfputs("{Already Visited}\n", stdout);
- HDfree(buf);
goto done;
}
/* Add this link to the list of seen elinks */
- if(elink_trav_add(iter->elink_list, filename, path) < 0) {
- HDfree(buf);
+ if(symlink_visit_add(iter->symlink_list, linfo->type, filename, path) < 0)
+ {
goto done;
}
/* Adjust user data to specify that we are operating on the
* target of an external link */
- iter->ext_target = TRUE;
+ iter->symlink_target = TRUE;
/* Prevent recursive listing of external link target if
* recursive_g is off */
@@ -1962,7 +2071,6 @@ list_lnk(const char *name, const H5L_info_t *linfo, void *_iter)
/* Recurse through the external link */
if(visit_obj(iter->fid, name, iter) < 0) {
- HDfree(buf);
grp_literal_g = orig_grp_literal;
goto done;
}
@@ -1972,7 +2080,6 @@ list_lnk(const char *name, const H5L_info_t *linfo, void *_iter)
else
HDfputc('\n', stdout);
- HDfree(buf);
}
break;
@@ -1982,6 +2089,8 @@ list_lnk(const char *name, const H5L_info_t *linfo, void *_iter)
} /* end switch */
done:
+ if (buf)
+ HDfree(buf);
return 0;
} /* end list_lnk() */
@@ -2008,9 +2117,9 @@ visit_obj(hid_t file, const char *oname, iter_t *iter)
/* Retrieve info for object to list */
if(H5Oget_info_by_name(file, oname, &oi, H5P_DEFAULT) < 0) {
- if(iter->ext_target) {
+ if(iter->symlink_target) {
HDfputs("{**NOT FOUND**}\n", stdout);
- iter->ext_target = FALSE;
+ iter->symlink_target = FALSE;
}
else
display_obj_name(stdout, iter, oname, "**NOT FOUND**");
@@ -2020,7 +2129,7 @@ visit_obj(hid_t file, const char *oname, iter_t *iter)
/* Check for group iteration */
if(H5O_TYPE_GROUP == oi.type && !grp_literal_g) {
/* Get ID for group */
- if(!iter->ext_target && (iter->gid = H5Gopen2(file, oname, H5P_DEFAULT)) < 0) {
+ if(!iter->symlink_target && (iter->gid = H5Gopen2(file, oname, H5P_DEFAULT)) < 0) {
fprintf(stderr, "%s: unable to open '%s' as group\n", iter->fname, oname);
return 0; /* Previously "continue", when this code was in main().
* We don't "continue" here in order to close the file
@@ -2032,10 +2141,10 @@ visit_obj(hid_t file, const char *oname, iter_t *iter)
iter->name_start = iter->base_len;
/* Specified name is a group. List the complete contents of the group. */
- h5trav_visit(file, oname, (hbool_t) (display_root_g || iter->ext_target), recursive_g, list_obj, list_lnk, iter);
+ h5trav_visit(file, oname, (hbool_t) (display_root_g || iter->symlink_target), recursive_g, list_obj, list_lnk, iter);
/* Close group */
- if(!iter->ext_target)
+ if(!iter->symlink_target)
H5Gclose(iter->gid);
} /* end if */
else {
@@ -2211,6 +2320,8 @@ main(int argc, const char *argv[])
data_g = TRUE;
} else if(!HDstrcmp(argv[argno], "--errors")) {
show_errors_g = TRUE;
+ } else if(!HDstrcmp(argv[argno], "--follow-symlinks")) {
+ follow_symlink_g = TRUE;
} else if(!HDstrcmp(argv[argno], "--external")) {
follow_elink_g = TRUE;
} else if(!HDstrcmp(argv[argno], "--full")) {
@@ -2381,7 +2492,7 @@ main(int argc, const char *argv[])
while(argno < argc) {
H5L_info_t li;
iter_t iter;
- elink_trav_t elink_list;
+ symlink_trav_t symlink_list;
size_t u;
fname = HDstrdup(argv[argno++]);
@@ -2443,12 +2554,12 @@ main(int argc, const char *argv[])
iter.fname = fname;
iter.fid = file;
iter.gid = -1;
- iter.ext_target = FALSE;
- iter.elink_list = &elink_list;
+ iter.symlink_target = FALSE;
+ iter.symlink_list = &symlink_list;
- /* Initialize list of visited external links */
- elink_list.nused = elink_list.nalloc = 0;
- elink_list.objs = NULL;
+ /* Initialize list of visited symbolic links */
+ symlink_list.nused = symlink_list.nalloc = 0;
+ symlink_list.objs = NULL;
/* Check for root group as object name */
if(HDstrcmp(oname, root_name)) {
@@ -2477,11 +2588,14 @@ main(int argc, const char *argv[])
if(x)
HDfree(oname);
- for(u=0; u < elink_list.nused; u++) {
- HDfree(elink_list.objs[u].file);
- HDfree(elink_list.objs[u].path);
+ for(u=0; u < symlink_list.nused; u++)
+ {
+ if (symlink_list.objs[u].type == H5L_TYPE_EXTERNAL)
+ HDfree(symlink_list.objs[u].file);
+
+ HDfree(symlink_list.objs[u].path);
}
- HDfree(elink_list.objs);
+ HDfree(symlink_list.objs);
} /* end while */
if (err_openfile)
diff --git a/tools/h5ls/testh5ls.sh.in b/tools/h5ls/testh5ls.sh.in
index 367e539..40dcaa4 100644
--- a/tools/h5ls/testh5ls.sh.in
+++ b/tools/h5ls/testh5ls.sh.in
@@ -129,17 +129,32 @@ TOOLTEST tdset-1.ls 0 -w80 -r -d tdset.h5
# test for displaying soft links
TOOLTEST tslink-1.ls 0 -w80 -r tslink.h5
-# test for displaying external and user-defined links
+# test for displaying more soft links with --follow-symlinks
+TOOLTEST tsoftlinks-1.ls 0 --follow-symlinks tsoftlinks.h5
+TOOLTEST tsoftlinks-2.ls 0 --follow-symlinks -r tsoftlinks.h5
+TOOLTEST tsoftlinks-3.ls 0 --follow-symlinks tsoftlinks.h5/group1
+TOOLTEST tsoftlinks-4.ls 0 --follow-symlinks -r tsoftlinks.h5/group1
+TOOLTEST tsoftlinks-5.ls 0 --follow-symlinks tsoftlinks.h5/soft_dset1
+
+# test for displaying external and user-defined links with --follow-symlinks
TOOLTEST textlink-1.ls 0 -w80 -r textlink.h5
-TOOLTEST textlinksrc-1.ls 0 -w80 -Er textlinksrc.h5
-TOOLTEST textlinksrc-2.ls 0 -w80 -Erv textlinksrc.h5/ext_link5
-TOOLTEST textlinksrc-3.ls 0 -w80 -Er textlinksrc.h5/ext_link1
+TOOLTEST textlinksrc-1.ls 0 -w80 --follow-symlinks -r textlinksrc.h5
+TOOLTEST textlinksrc-2.ls 0 -w80 --follow-symlinks -rv textlinksrc.h5/ext_link5
+TOOLTEST textlinksrc-3.ls 0 -w80 --follow-symlinks -r textlinksrc.h5/ext_link1
TOOLTEST textlinksrc-4.ls 0 -w80 -r textlinksrc.h5
TOOLTEST textlinksrc-5.ls 0 -w80 -r textlinksrc.h5/ext_link1
-TOOLTEST textlinksrc-6.ls 0 -w80 -E textlinksrc.h5
-TOOLTEST textlinksrc-7.ls 0 -w80 -E textlinksrc.h5/ext_link1
+TOOLTEST textlinksrc-6.ls 0 -w80 --follow-symlinks textlinksrc.h5
+TOOLTEST textlinksrc-7.ls 0 -w80 --follow-symlinks textlinksrc.h5/ext_link1
TOOLTEST tudlink-1.ls 0 -w80 -r tudlink.h5
+# test for displaying external links with -E
+# the option -E will be depriciated but keep it for backward compatibility
+TOOLTEST textlinksrc-1-old.ls 0 -w80 -Er textlinksrc.h5
+TOOLTEST textlinksrc-2-old.ls 0 -w80 -Erv textlinksrc.h5/ext_link5
+TOOLTEST textlinksrc-3-old.ls 0 -w80 -Er textlinksrc.h5/ext_link1
+TOOLTEST textlinksrc-6-old.ls 0 -w80 -E textlinksrc.h5
+TOOLTEST textlinksrc-7-old.ls 0 -w80 -E textlinksrc.h5/ext_link1
+
# tests for hard links
TOOLTEST thlink-1.ls 0 -w80 thlink.h5
diff --git a/tools/testfiles/help-1.ls b/tools/testfiles/help-1.ls
index 4c45570..1b5de0c 100644
--- a/tools/testfiles/help-1.ls
+++ b/tools/testfiles/help-1.ls
@@ -2,27 +2,43 @@
output for 'h5ls -w80 -h'
#############################
usage: h5ls [OPTIONS] [OBJECTS...]
- OPTIONS
- -h, -?, --help Print a usage message and exit
- -a, --address Print addresses for raw data
- -d, --data Print the values of datasets
- -e, --errors Show all HDF5 error reporting
- -E, --external Allow traversal into external files
- -f, --full Print full path names instead of base names
- -g, --group Show information about a group, not its contents
- -l, --label Label members of compound datasets
- -r, --recursive List all groups recursively, avoiding cycles
- -s, --string Print 1-byte integer datasets as ASCII
- -S, --simple Use a machine-readable output format
- -wN, --width=N Set the number of columns of output
- -v, --verbose Generate more verbose output
- -V, --version Print version number and exit
- --vfd=DRIVER Use the specified virtual file driver
- -x, --hexdump Show raw data in hexadecimal format
+ OPTIONS
+ -h, -?, --help Print a usage message and exit
+ -a, --address Print addresses for raw data
+ -d, --data Print the values of datasets
+ -e, --errors Show all HDF5 error reporting
+ --follow-symlinks Follow symbolic links (soft links and external links)
+ to display target object information.
+ Without this option, h5ls identifies a symbolic link
+ as a soft link or external link and prints the value
+ assigned to the symbolic link; it does not provide any
+ information regarding the target object or determine
+ whether the link is a dangling link.
+ -f, --full Print full path names instead of base names
+ -g, --group Show information about a group, not its contents
+ -l, --label Label members of compound datasets
+ -r, --recursive List all groups recursively, avoiding cycles
+ -s, --string Print 1-byte integer datasets as ASCII
+ -S, --simple Use a machine-readable output format
+ -wN, --width=N Set the number of columns of output
+ -v, --verbose Generate more verbose output
+ -V, --version Print version number and exit
+ --vfd=DRIVER Use the specified virtual file driver
+ -x, --hexdump Show raw data in hexadecimal format
- OBJECTS
- Each object consists of an HDF5 file name optionally followed by a
- slash and an object name within the file (if no object is specified
- within the file then the contents of the root group are displayed).
- The file name may include a printf(3C) integer format such as
- "%05d" to open a file family.
+ OBJECTS
+ Each object consists of an HDF5 file name optionally followed by a
+ slash and an object name within the file (if no object is specified
+ within the file then the contents of the root group are displayed).
+ The file name may include a printf(3C) integer format such as
+ "%05d" to open a file family.
+
+ Deprecated Options
+ The following options have been deprecated in HDF5. While they remain
+ available, they have been superseded as indicated and may be removed
+ from HDF5 in the future. Use the indicated replacement option in all
+ new work; where possible, existing scripts, et cetera, should also be
+ updated to use the replacement option.
+
+ -E or --external Follow external links.
+ Replaced by --follow-symlinks.
diff --git a/tools/testfiles/help-2.ls b/tools/testfiles/help-2.ls
index 522cb5a..6f7e75d 100644
--- a/tools/testfiles/help-2.ls
+++ b/tools/testfiles/help-2.ls
@@ -2,27 +2,43 @@
output for 'h5ls -w80 -help'
#############################
usage: h5ls [OPTIONS] [OBJECTS...]
- OPTIONS
- -h, -?, --help Print a usage message and exit
- -a, --address Print addresses for raw data
- -d, --data Print the values of datasets
- -e, --errors Show all HDF5 error reporting
- -E, --external Allow traversal into external files
- -f, --full Print full path names instead of base names
- -g, --group Show information about a group, not its contents
- -l, --label Label members of compound datasets
- -r, --recursive List all groups recursively, avoiding cycles
- -s, --string Print 1-byte integer datasets as ASCII
- -S, --simple Use a machine-readable output format
- -wN, --width=N Set the number of columns of output
- -v, --verbose Generate more verbose output
- -V, --version Print version number and exit
- --vfd=DRIVER Use the specified virtual file driver
- -x, --hexdump Show raw data in hexadecimal format
+ OPTIONS
+ -h, -?, --help Print a usage message and exit
+ -a, --address Print addresses for raw data
+ -d, --data Print the values of datasets
+ -e, --errors Show all HDF5 error reporting
+ --follow-symlinks Follow symbolic links (soft links and external links)
+ to display target object information.
+ Without this option, h5ls identifies a symbolic link
+ as a soft link or external link and prints the value
+ assigned to the symbolic link; it does not provide any
+ information regarding the target object or determine
+ whether the link is a dangling link.
+ -f, --full Print full path names instead of base names
+ -g, --group Show information about a group, not its contents
+ -l, --label Label members of compound datasets
+ -r, --recursive List all groups recursively, avoiding cycles
+ -s, --string Print 1-byte integer datasets as ASCII
+ -S, --simple Use a machine-readable output format
+ -wN, --width=N Set the number of columns of output
+ -v, --verbose Generate more verbose output
+ -V, --version Print version number and exit
+ --vfd=DRIVER Use the specified virtual file driver
+ -x, --hexdump Show raw data in hexadecimal format
- OBJECTS
- Each object consists of an HDF5 file name optionally followed by a
- slash and an object name within the file (if no object is specified
- within the file then the contents of the root group are displayed).
- The file name may include a printf(3C) integer format such as
- "%05d" to open a file family.
+ OBJECTS
+ Each object consists of an HDF5 file name optionally followed by a
+ slash and an object name within the file (if no object is specified
+ within the file then the contents of the root group are displayed).
+ The file name may include a printf(3C) integer format such as
+ "%05d" to open a file family.
+
+ Deprecated Options
+ The following options have been deprecated in HDF5. While they remain
+ available, they have been superseded as indicated and may be removed
+ from HDF5 in the future. Use the indicated replacement option in all
+ new work; where possible, existing scripts, et cetera, should also be
+ updated to use the replacement option.
+
+ -E or --external Follow external links.
+ Replaced by --follow-symlinks.
diff --git a/tools/testfiles/help-3.ls b/tools/testfiles/help-3.ls
index 22ad865..939c8eb 100644
--- a/tools/testfiles/help-3.ls
+++ b/tools/testfiles/help-3.ls
@@ -2,27 +2,43 @@
output for 'h5ls -w80 -?'
#############################
usage: h5ls [OPTIONS] [OBJECTS...]
- OPTIONS
- -h, -?, --help Print a usage message and exit
- -a, --address Print addresses for raw data
- -d, --data Print the values of datasets
- -e, --errors Show all HDF5 error reporting
- -E, --external Allow traversal into external files
- -f, --full Print full path names instead of base names
- -g, --group Show information about a group, not its contents
- -l, --label Label members of compound datasets
- -r, --recursive List all groups recursively, avoiding cycles
- -s, --string Print 1-byte integer datasets as ASCII
- -S, --simple Use a machine-readable output format
- -wN, --width=N Set the number of columns of output
- -v, --verbose Generate more verbose output
- -V, --version Print version number and exit
- --vfd=DRIVER Use the specified virtual file driver
- -x, --hexdump Show raw data in hexadecimal format
+ OPTIONS
+ -h, -?, --help Print a usage message and exit
+ -a, --address Print addresses for raw data
+ -d, --data Print the values of datasets
+ -e, --errors Show all HDF5 error reporting
+ --follow-symlinks Follow symbolic links (soft links and external links)
+ to display target object information.
+ Without this option, h5ls identifies a symbolic link
+ as a soft link or external link and prints the value
+ assigned to the symbolic link; it does not provide any
+ information regarding the target object or determine
+ whether the link is a dangling link.
+ -f, --full Print full path names instead of base names
+ -g, --group Show information about a group, not its contents
+ -l, --label Label members of compound datasets
+ -r, --recursive List all groups recursively, avoiding cycles
+ -s, --string Print 1-byte integer datasets as ASCII
+ -S, --simple Use a machine-readable output format
+ -wN, --width=N Set the number of columns of output
+ -v, --verbose Generate more verbose output
+ -V, --version Print version number and exit
+ --vfd=DRIVER Use the specified virtual file driver
+ -x, --hexdump Show raw data in hexadecimal format
- OBJECTS
- Each object consists of an HDF5 file name optionally followed by a
- slash and an object name within the file (if no object is specified
- within the file then the contents of the root group are displayed).
- The file name may include a printf(3C) integer format such as
- "%05d" to open a file family.
+ OBJECTS
+ Each object consists of an HDF5 file name optionally followed by a
+ slash and an object name within the file (if no object is specified
+ within the file then the contents of the root group are displayed).
+ The file name may include a printf(3C) integer format such as
+ "%05d" to open a file family.
+
+ Deprecated Options
+ The following options have been deprecated in HDF5. While they remain
+ available, they have been superseded as indicated and may be removed
+ from HDF5 in the future. Use the indicated replacement option in all
+ new work; where possible, existing scripts, et cetera, should also be
+ updated to use the replacement option.
+
+ -E or --external Follow external links.
+ Replaced by --follow-symlinks.
diff --git a/tools/testfiles/textlinksrc-1-old.ls b/tools/testfiles/textlinksrc-1-old.ls
new file mode 100644
index 0000000..5e81dec
--- /dev/null
+++ b/tools/testfiles/textlinksrc-1-old.ls
@@ -0,0 +1,19 @@
+#############################
+ output for 'h5ls -w80 -Er textlinksrc.h5'
+#############################
+/ Group
+/ext_link1 External Link {textlinktar.h5//group} {Group}
+/ext_link1/dset Dataset {6}
+/ext_link1/elink_t1 External Link {textlinksrc.h5//} {Group}
+/ext_link1/elink_t1/ext_link1 External Link {textlinktar.h5//group} {Already Visited}
+/ext_link1/elink_t1/ext_link2 External Link {textlinktar.h5//dset} {Dataset {6}}
+/ext_link1/elink_t1/ext_link3 External Link {textlinktar.h5//type} {Type}
+/ext_link1/elink_t1/ext_link4 External Link {textlinktar.h5//group/elink_t2} {**NOT FOUND**}
+/ext_link1/elink_t1/ext_link5 External Link {textlinktar.h5//empty_group} {Group}
+/ext_link1/elink_t2 External Link {textlinksrc.h5//ext_link4} {**NOT FOUND**}
+/ext_link1/subgroup Group
+/ext_link1/subgroup/link_to_group Group, same as /ext_link1
+/ext_link2 External Link {textlinktar.h5//dset} {Already Visited}
+/ext_link3 External Link {textlinktar.h5//type} {Already Visited}
+/ext_link4 External Link {textlinktar.h5//group/elink_t2} {Already Visited}
+/ext_link5 External Link {textlinktar.h5//empty_group} {Already Visited}
diff --git a/tools/testfiles/textlinksrc-1.ls b/tools/testfiles/textlinksrc-1.ls
index 5e81dec..f39eec9 100644
--- a/tools/testfiles/textlinksrc-1.ls
+++ b/tools/testfiles/textlinksrc-1.ls
@@ -1,5 +1,5 @@
#############################
- output for 'h5ls -w80 -Er textlinksrc.h5'
+ output for 'h5ls -w80 --follow-symlinks -r textlinksrc.h5'
#############################
/ Group
/ext_link1 External Link {textlinktar.h5//group} {Group}
diff --git a/tools/testfiles/textlinksrc-2-old.ls b/tools/testfiles/textlinksrc-2-old.ls
new file mode 100644
index 0000000..acdc3d2
--- /dev/null
+++ b/tools/testfiles/textlinksrc-2-old.ls
@@ -0,0 +1,8 @@
+#############################
+ output for 'h5ls -w80 -Erv textlinksrc.h5/ext_link5'
+#############################
+Opened "textlinksrc.h5" with sec2 driver.
+ext_link5 External Link {textlinktar.h5//empty_group} {Group
+ Location: 3:1832
+ Links: 1
+}
diff --git a/tools/testfiles/textlinksrc-2.ls b/tools/testfiles/textlinksrc-2.ls
index acdc3d2..ea99be8 100644
--- a/tools/testfiles/textlinksrc-2.ls
+++ b/tools/testfiles/textlinksrc-2.ls
@@ -1,5 +1,5 @@
#############################
- output for 'h5ls -w80 -Erv textlinksrc.h5/ext_link5'
+ output for 'h5ls -w80 --follow-symlinks -rv textlinksrc.h5/ext_link5'
#############################
Opened "textlinksrc.h5" with sec2 driver.
ext_link5 External Link {textlinktar.h5//empty_group} {Group
diff --git a/tools/testfiles/textlinksrc-3-old.ls b/tools/testfiles/textlinksrc-3-old.ls
new file mode 100644
index 0000000..a86ca32
--- /dev/null
+++ b/tools/testfiles/textlinksrc-3-old.ls
@@ -0,0 +1,14 @@
+#############################
+ output for 'h5ls -w80 -Er textlinksrc.h5/ext_link1'
+#############################
+ext_link1 External Link {textlinktar.h5//group} {Group}
+/dset Dataset {6}
+/elink_t1 External Link {textlinksrc.h5//} {Group}
+/elink_t1/ext_link1 External Link {textlinktar.h5//group} {Already Visited}
+/elink_t1/ext_link2 External Link {textlinktar.h5//dset} {Dataset {6}}
+/elink_t1/ext_link3 External Link {textlinktar.h5//type} {Type}
+/elink_t1/ext_link4 External Link {textlinktar.h5//group/elink_t2} {**NOT FOUND**}
+/elink_t1/ext_link5 External Link {textlinktar.h5//empty_group} {Group}
+/elink_t2 External Link {textlinksrc.h5//ext_link4} {**NOT FOUND**}
+/subgroup Group
+/subgroup/link_to_group Group, same as /ext_link1
diff --git a/tools/testfiles/textlinksrc-3.ls b/tools/testfiles/textlinksrc-3.ls
index a86ca32..bd173f3 100644
--- a/tools/testfiles/textlinksrc-3.ls
+++ b/tools/testfiles/textlinksrc-3.ls
@@ -1,5 +1,5 @@
#############################
- output for 'h5ls -w80 -Er textlinksrc.h5/ext_link1'
+ output for 'h5ls -w80 --follow-symlinks -r textlinksrc.h5/ext_link1'
#############################
ext_link1 External Link {textlinktar.h5//group} {Group}
/dset Dataset {6}
diff --git a/tools/testfiles/textlinksrc-6-old.ls b/tools/testfiles/textlinksrc-6-old.ls
new file mode 100644
index 0000000..e1b8b74
--- /dev/null
+++ b/tools/testfiles/textlinksrc-6-old.ls
@@ -0,0 +1,8 @@
+#############################
+ output for 'h5ls -w80 -E textlinksrc.h5'
+#############################
+ext_link1 External Link {textlinktar.h5//group} {Group}
+ext_link2 External Link {textlinktar.h5//dset} {Dataset {6}}
+ext_link3 External Link {textlinktar.h5//type} {Type}
+ext_link4 External Link {textlinktar.h5//group/elink_t2} {**NOT FOUND**}
+ext_link5 External Link {textlinktar.h5//empty_group} {Group}
diff --git a/tools/testfiles/textlinksrc-6.ls b/tools/testfiles/textlinksrc-6.ls
index e1b8b74..6cda888 100644
--- a/tools/testfiles/textlinksrc-6.ls
+++ b/tools/testfiles/textlinksrc-6.ls
@@ -1,5 +1,5 @@
#############################
- output for 'h5ls -w80 -E textlinksrc.h5'
+ output for 'h5ls -w80 --follow-symlinks textlinksrc.h5'
#############################
ext_link1 External Link {textlinktar.h5//group} {Group}
ext_link2 External Link {textlinktar.h5//dset} {Dataset {6}}
diff --git a/tools/testfiles/textlinksrc-7-old.ls b/tools/testfiles/textlinksrc-7-old.ls
new file mode 100644
index 0000000..9249d0c
--- /dev/null
+++ b/tools/testfiles/textlinksrc-7-old.ls
@@ -0,0 +1,4 @@
+#############################
+ output for 'h5ls -w80 -E textlinksrc.h5/ext_link1'
+#############################
+ext_link1 External Link {textlinktar.h5//group} {Group}
diff --git a/tools/testfiles/textlinksrc-7.ls b/tools/testfiles/textlinksrc-7.ls
index 9249d0c..528c4c5 100644
--- a/tools/testfiles/textlinksrc-7.ls
+++ b/tools/testfiles/textlinksrc-7.ls
@@ -1,4 +1,4 @@
#############################
- output for 'h5ls -w80 -E textlinksrc.h5/ext_link1'
+ output for 'h5ls -w80 --follow-symlinks textlinksrc.h5/ext_link1'
#############################
ext_link1 External Link {textlinktar.h5//group} {Group}
diff --git a/tools/testfiles/tgroup-1.ls b/tools/testfiles/tgroup-1.ls
index 5401cd7..8d38e0f 100644
--- a/tools/testfiles/tgroup-1.ls
+++ b/tools/testfiles/tgroup-1.ls
@@ -4,27 +4,43 @@
Error: 'recursive' option not compatible with 'group info' option!
usage: h5ls [OPTIONS] [OBJECTS...]
- OPTIONS
- -h, -?, --help Print a usage message and exit
- -a, --address Print addresses for raw data
- -d, --data Print the values of datasets
- -e, --errors Show all HDF5 error reporting
- -E, --external Allow traversal into external files
- -f, --full Print full path names instead of base names
- -g, --group Show information about a group, not its contents
- -l, --label Label members of compound datasets
- -r, --recursive List all groups recursively, avoiding cycles
- -s, --string Print 1-byte integer datasets as ASCII
- -S, --simple Use a machine-readable output format
- -wN, --width=N Set the number of columns of output
- -v, --verbose Generate more verbose output
- -V, --version Print version number and exit
- --vfd=DRIVER Use the specified virtual file driver
- -x, --hexdump Show raw data in hexadecimal format
+ OPTIONS
+ -h, -?, --help Print a usage message and exit
+ -a, --address Print addresses for raw data
+ -d, --data Print the values of datasets
+ -e, --errors Show all HDF5 error reporting
+ --follow-symlinks Follow symbolic links (soft links and external links)
+ to display target object information.
+ Without this option, h5ls identifies a symbolic link
+ as a soft link or external link and prints the value
+ assigned to the symbolic link; it does not provide any
+ information regarding the target object or determine
+ whether the link is a dangling link.
+ -f, --full Print full path names instead of base names
+ -g, --group Show information about a group, not its contents
+ -l, --label Label members of compound datasets
+ -r, --recursive List all groups recursively, avoiding cycles
+ -s, --string Print 1-byte integer datasets as ASCII
+ -S, --simple Use a machine-readable output format
+ -wN, --width=N Set the number of columns of output
+ -v, --verbose Generate more verbose output
+ -V, --version Print version number and exit
+ --vfd=DRIVER Use the specified virtual file driver
+ -x, --hexdump Show raw data in hexadecimal format
- OBJECTS
- Each object consists of an HDF5 file name optionally followed by a
- slash and an object name within the file (if no object is specified
- within the file then the contents of the root group are displayed).
- The file name may include a printf(3C) integer format such as
- "%05d" to open a file family.
+ OBJECTS
+ Each object consists of an HDF5 file name optionally followed by a
+ slash and an object name within the file (if no object is specified
+ within the file then the contents of the root group are displayed).
+ The file name may include a printf(3C) integer format such as
+ "%05d" to open a file family.
+
+ Deprecated Options
+ The following options have been deprecated in HDF5. While they remain
+ available, they have been superseded as indicated and may be removed
+ from HDF5 in the future. Use the indicated replacement option in all
+ new work; where possible, existing scripts, et cetera, should also be
+ updated to use the replacement option.
+
+ -E or --external Follow external links.
+ Replaced by --follow-symlinks.
diff --git a/tools/testfiles/tsoftlinks-1.ls b/tools/testfiles/tsoftlinks-1.ls
new file mode 100644
index 0000000..fc57da9
--- /dev/null
+++ b/tools/testfiles/tsoftlinks-1.ls
@@ -0,0 +1,13 @@
+#############################
+ output for 'h5ls --follow-symlinks tsoftlinks.h5'
+#############################
+dset1 Dataset {4, 2}
+dset2 Dataset {4, 2}
+dtype Type
+group1 Group
+group_empty Group
+soft_dangle Soft Link {not_yet} {**NOT FOUND**}
+soft_dset1 Soft Link {/dset1} {Dataset {4, 2}}
+soft_dtype Soft Link {/dtype} {Type}
+soft_empty_grp Soft Link {/group_empty} {Group}
+soft_group1 Soft Link {/group1} {Group}
diff --git a/tools/testfiles/tsoftlinks-2.ls b/tools/testfiles/tsoftlinks-2.ls
new file mode 100644
index 0000000..3566f70
--- /dev/null
+++ b/tools/testfiles/tsoftlinks-2.ls
@@ -0,0 +1,24 @@
+#############################
+ output for 'h5ls --follow-symlinks -r tsoftlinks.h5'
+#############################
+/ Group
+/dset1 Dataset {4, 2}
+/dset2 Dataset {4, 2}
+/dtype Type
+/group1 Group
+/group1/soft_dangle Soft Link {not_yet} {**NOT FOUND**}
+/group1/soft_dset1 Soft Link {/dset1} {Dataset {4, 2}}
+/group1/soft_dset2 Soft Link {/dset2} {Dataset {4, 2}}
+/group1/soft_dtype Soft Link {/dtype} {Type}
+/group1/soft_empty_grp Soft Link {/group_empty} {Group}
+/group_empty Group
+/soft_dangle Soft Link {not_yet} {Already Visited}
+/soft_dset1 Soft Link {/dset1} {Already Visited}
+/soft_dtype Soft Link {/dtype} {Already Visited}
+/soft_empty_grp Soft Link {/group_empty} {Already Visited}
+/soft_group1 Soft Link {/group1} {Group}
+/soft_group1/soft_dangle Soft Link {not_yet} {Already Visited}
+/soft_group1/soft_dset1 Soft Link {/dset1} {Already Visited}
+/soft_group1/soft_dset2 Soft Link {/dset2} {Already Visited}
+/soft_group1/soft_dtype Soft Link {/dtype} {Already Visited}
+/soft_group1/soft_empty_grp Soft Link {/group_empty} {Already Visited}
diff --git a/tools/testfiles/tsoftlinks-3.ls b/tools/testfiles/tsoftlinks-3.ls
new file mode 100644
index 0000000..2face70
--- /dev/null
+++ b/tools/testfiles/tsoftlinks-3.ls
@@ -0,0 +1,8 @@
+#############################
+ output for 'h5ls --follow-symlinks tsoftlinks.h5/group1'
+#############################
+soft_dangle Soft Link {not_yet} {**NOT FOUND**}
+soft_dset1 Soft Link {/dset1} {Dataset {4, 2}}
+soft_dset2 Soft Link {/dset2} {Dataset {4, 2}}
+soft_dtype Soft Link {/dtype} {Type}
+soft_empty_grp Soft Link {/group_empty} {Group}
diff --git a/tools/testfiles/tsoftlinks-4.ls b/tools/testfiles/tsoftlinks-4.ls
new file mode 100644
index 0000000..c1f4568
--- /dev/null
+++ b/tools/testfiles/tsoftlinks-4.ls
@@ -0,0 +1,8 @@
+#############################
+ output for 'h5ls --follow-symlinks -r tsoftlinks.h5/group1'
+#############################
+/soft_dangle Soft Link {not_yet} {**NOT FOUND**}
+/soft_dset1 Soft Link {/dset1} {Dataset {4, 2}}
+/soft_dset2 Soft Link {/dset2} {Dataset {4, 2}}
+/soft_dtype Soft Link {/dtype} {Type}
+/soft_empty_grp Soft Link {/group_empty} {Group}
diff --git a/tools/testfiles/tsoftlinks-5.ls b/tools/testfiles/tsoftlinks-5.ls
new file mode 100644
index 0000000..6e915e1
--- /dev/null
+++ b/tools/testfiles/tsoftlinks-5.ls
@@ -0,0 +1,4 @@
+#############################
+ output for 'h5ls --follow-symlinks tsoftlinks.h5/soft_dset1'
+#############################
+soft_dset1 Soft Link {/dset1} {Dataset {4, 2}}
diff --git a/tools/testfiles/tsoftlinks.h5 b/tools/testfiles/tsoftlinks.h5
new file mode 100644
index 0000000..01ea922
--- /dev/null
+++ b/tools/testfiles/tsoftlinks.h5
Binary files differ