summaryrefslogtreecommitdiffstats
path: root/test/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/mount.c')
-rw-r--r--test/mount.c1072
1 files changed, 1072 insertions, 0 deletions
diff --git a/test/mount.c b/test/mount.c
new file mode 100644
index 0000000..516eba8
--- /dev/null
+++ b/test/mount.c
@@ -0,0 +1,1072 @@
+/*
+ * Copyright (C) 1998 NCSA
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Wednesday, October 7, 1998
+ *
+ * Purpose: Tests file mounting.
+ */
+#include <hdf5.h>
+#include <stdlib.h>
+
+#define FALSE 0
+#define TRUE 1
+
+#define FILE_NAME_1 "mount_1.h5"
+#define FILE_NAME_2 "mount_2.h5"
+#define FILE_NAME_3 "mount_3.h5"
+
+#include <H5config.h>
+#ifndef HAVE_ATTRIBUTE
+# undef __attribute__
+# define __attribute__(X) /*void*/
+# define __unused__ /*void*/
+#else
+# define __unused__ __attribute__((unused))
+#endif
+
+
+/*-------------------------------------------------------------------------
+ * Function: cleanup
+ *
+ * Purpose: Removes test files
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Thursday, June 4, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+cleanup(void)
+{
+ if (!getenv("HDF5_NOCLEANUP")) {
+ remove(FILE_NAME_1);
+ remove(FILE_NAME_2);
+ remove(FILE_NAME_3);
+ }
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: display_error_cb
+ *
+ * Purpose: Displays the error stack after printing "*FAILED*".
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, March 4, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+display_error_cb(void __unused__ *client_data)
+{
+ puts("*FAILED*");
+ H5Eprint(stdout);
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: setup
+ *
+ * Purpose: Create some files and populate them with a few groups.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 7, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+setup(void)
+{
+ hid_t file=-1;
+
+ /* file 1 */
+ if ((file=H5Fcreate(FILE_NAME_1, H5F_ACC_TRUNC, H5P_DEFAULT,
+ H5P_DEFAULT))<0) goto error;
+ if (H5Gclose(H5Gcreate(file, "/mnt1", 0))<0) goto error;
+ if (H5Gclose(H5Gcreate(file, "/mnt1/file1", 0))<0) goto error;
+ if (H5Gclose(H5Gcreate(file, "/mnt_unlink", 0))<0) goto error;
+ if (H5Gclose(H5Gcreate(file, "/mnt_move_a", 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 (H5Fclose(file)<0) goto error;
+
+ /* file 2 */
+ if ((file=H5Fcreate(FILE_NAME_2, H5F_ACC_TRUNC, H5P_DEFAULT,
+ H5P_DEFAULT))<0) goto error;
+ if (H5Gclose(H5Gcreate(file, "/file2", 0))<0) goto error;
+ if (H5Gclose(H5Gcreate(file, "/rename_a", 0))<0) goto error;
+ if (H5Gclose(H5Gcreate(file, "/rename_b", 0))<0) goto error;
+ if (H5Gclose(H5Gcreate(file, "/rename_a/x", 0))<0) goto error;
+ if (H5Fclose(file)<0) goto error;
+
+ /* file 3 */
+ if ((file=H5Fcreate(FILE_NAME_3, H5F_ACC_TRUNC, H5P_DEFAULT,
+ H5P_DEFAULT))<0) goto error;
+ if (H5Fclose(file)<0) goto error;
+
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Fclose(file);
+ } H5E_END_TRY;
+ return -1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_basic
+ *
+ * Purpose: Mount file1 at file2:/mnt1 and try accessing an object in
+ * file2. Then unmount.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 7, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_basic(void)
+{
+ hid_t file1=-1, file2=-1, grp=-1;
+
+ printf("%-70s", "Testing basic functionality");
+ fflush(stdout);
+
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDONLY, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDONLY, H5P_DEFAULT))<0)
+ goto error;
+ if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
+ if ((grp=H5Gopen(file1, "/mnt1/file2"))<0) goto error;
+ if (H5Gclose(grp)<0) goto error;
+ if (H5Funmount(file1, "/mnt1")<0) goto error;
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Fclose(file1);
+ H5Fclose(file2);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_illegal
+ *
+ * Purpose: Test things that are illegal to do. We should get a failure
+ * from the library for each of them.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 7, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_illegal(void)
+{
+ hid_t file1=-1, file2=-1, file3=-1, mnt=-1;
+ herr_t status;
+
+ printf("%-70s", "Testing illegal mount operations");
+ fflush(stdout);
+
+ /* Open the files */
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDONLY, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDONLY, H5P_DEFAULT))<0 ||
+ (file3=H5Fopen(FILE_NAME_3, H5F_ACC_RDONLY, H5P_DEFAULT))<0)
+ goto error;
+
+ /* Try mounting a file on itself */
+ H5E_BEGIN_TRY {
+ status = H5Fmount(file1, "/mnt1", file1, H5P_DEFAULT);
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" Mounting a file on itself should have failed.");
+ goto error;
+ }
+
+ /*
+ * Try mounting two files at the same place. We have to open the mount
+ * point before we mount the first file or we'll end up mounting file3 at
+ * the root of file2 and the mount will succeed.
+ */
+ if ((mnt=H5Gopen(file1, "/mnt1"))<0) goto error;
+ if (H5Fmount(mnt, ".", file2, H5P_DEFAULT)<0) goto error;
+ H5E_BEGIN_TRY {
+ status = H5Fmount(mnt, ".", file3, H5P_DEFAULT);
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" Mounting two files at one mount point should have failed.");
+ goto error;
+ }
+ if (H5Funmount(mnt, ".")<0) goto error;
+ if (H5Gclose(mnt)<0) goto error;
+
+
+ /* Close everything and return */
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+ if (H5Fclose(file3)<0) goto error;
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose(mnt);
+ H5Fclose(file1);
+ H5Fclose(file2);
+ H5Fclose(file3);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_hide
+ *
+ * Purpose: The previous contents of the mount point is temporarily
+ * hidden. If objects in that group had names from other groups
+ * then the objects will still be visible by those other names.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 7, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_hide(void)
+{
+ hid_t file1=-1, file2=-1, grp=-1;
+ H5G_stat_t sb1, sb2;
+
+ printf("%-70s", "Testing name hiding under mount point");
+ fflush(stdout);
+
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDONLY, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDONLY, H5P_DEFAULT))<0)
+ goto error;
+
+ /* Get information about file1:/mnt1/file1 for later */
+ if (H5Gget_objinfo(file1, "/mnt1/file1", TRUE, &sb1)<0) goto error;
+
+ /* Build the virtual file */
+ if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
+
+ /* Original names under file1:/mnt1 should not be accessible */
+ H5E_BEGIN_TRY {
+ grp = H5Gopen(file1, "/mnt1/file1");
+ } H5E_END_TRY;
+ if (grp>=0) {
+ puts("*FAILED*");
+ puts(" Name is still accessible under mount point.");
+ goto error;
+ }
+
+ /*
+ * The original objects under file1:/mnt1 are still accessible by their
+ * other names. This is a rather stupid test but demonstrates a point.
+ */
+ if (H5Gget_objinfo(file1, "/file1", TRUE, &sb2)<0) goto error;
+ if (sb1.fileno[0]!=sb2.fileno[0] || sb1.fileno[1]!=sb2.fileno[1] ||
+ sb1.objno[0]!=sb2.objno[0] || sb1.objno[1]!=sb2.objno[1]) {
+ puts("*FAILED*");
+ puts(" Hard link failed for hidden object.");
+ goto error;
+ }
+
+ /* Unmount and close objects */
+ if (H5Funmount(file1, "/mnt1")<0) goto error;
+ H5Fclose(file1);
+ H5Fclose(file2);
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose(grp);
+ H5Fclose(file1);
+ H5Fclose(file2);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_assoc
+ *
+ * Purpose: Opening the mount point is the same as opening the root group
+ * of the mounted file before the file was mounted.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 13, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_assoc(void)
+{
+ hid_t file1=-1, file2=-1;
+ H5G_stat_t sb1, sb2;
+
+ printf("%-70s", "Testing mount point open");
+ fflush(stdout);
+
+ /* Open the files */
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDONLY, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDONLY, H5P_DEFAULT))<0)
+ goto error;
+
+ /* Get information about the root of file2 */
+ if (H5Gget_objinfo(file2, "/", TRUE, &sb1)<0) goto error;
+
+ /* Create the virtual file */
+ if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
+
+ /*
+ * Get info about the mount point -- should be the same as the root group
+ * of file2.
+ */
+ if (H5Gget_objinfo(file1, "/mnt1", TRUE, &sb2)<0) goto error;
+ if (sb1.fileno[0]!=sb2.fileno[0] || sb1.fileno[1]!=sb2.fileno[1] ||
+ sb1.objno[0]!=sb2.objno[0] || sb1.objno[1]!=sb2.objno[1]) {
+ puts("*FAILED*");
+ puts(" Association failed.");
+ goto error;
+ }
+
+ /* Shut down */
+ if (H5Funmount(file1, "/mnt1_link")<0) goto error;
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Fclose(file2);
+ H5Fclose(file1);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_mntlnk
+ *
+ * Purpose: The mount point is actually an OID (not a name) so if there
+ * are other names for that group then the root group of the
+ * child will be visible in all those names.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 7, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_mntlnk(void)
+{
+ hid_t file1=-1, file2=-1, grp=-1;
+
+ printf("%-70s", "Testing multi-linked mount point");
+ fflush(stdout);
+
+ /* Build the virtual file */
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDONLY, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDONLY, H5P_DEFAULT))<0)
+ goto error;
+ if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
+
+ /*
+ * Can we see file2:/file2 as both file1:/mnt1/file2 and
+ * file1:/mnt1_link/file2?
+ */
+ if ((grp=H5Gopen(file1, "/mnt1/file2"))<0) goto error;
+ if (H5Gclose(grp)<0) goto error;
+ if ((grp=H5Gopen(file1, "/mnt1_link/file2"))<0) goto error;
+ if (H5Gclose(grp)<0) goto error;
+
+ /* Unlink using second name */
+ if (H5Funmount(file1, "/mnt1_link")<0) goto error;
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose(grp);
+ H5Fclose(file1);
+ H5Fclose(file2);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_move
+ *
+ * Purpose: An object cannot be moved or renamed with H5Gmove() in such a
+ * way that the new location would be in a different file than
+ * the original location.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 7, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_move(void)
+{
+ hid_t file1=-1, file2=-1;
+ herr_t status;
+
+ printf("%-70s", "Testing object renaming");
+ fflush(stdout);
+
+ /* Build the virtual file */
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDWR, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDWR, H5P_DEFAULT))<0)
+ goto error;
+ 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;
+ H5E_BEGIN_TRY {
+ status = H5Gmove(file1, "/mnt1/rename_b/y", "/y");
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" Moving an object across files should not have been possible");
+ goto error;
+ }
+
+ /* Shut down */
+ if (H5Funmount(file1, "/mnt1")<0) goto error;
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Fclose(file1);
+ H5Fclose(file2);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_preopen
+ *
+ * Purpose: Objects that are opened under the mount point before the
+ * child is mounted will remain accessible.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 7, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_preopen(void)
+{
+ hid_t file1=-1, file2=-1, grp=-1;
+
+ printf("%-70s", "Testing preopening objects under the mount point");
+ fflush(stdout);
+
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDONLY, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDONLY, H5P_DEFAULT))<0)
+ goto error;
+
+ /* Open something under the mount point */
+ if ((grp=H5Gopen(file1, "/mnt1/file1"))<0) goto error;
+
+ /* Build the virtual file */
+ if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
+
+ /* Now access the thing we previously opened */
+ if (H5Gget_objinfo(grp, ".", TRUE, NULL)<0) goto error;
+
+ /* Shut down */
+ if (H5Funmount(file1, "/mnt1")<0) goto error;
+ if (H5Gclose(grp)<0) goto error;
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose(grp);
+ H5Fclose(file2);
+ H5Fclose(file1);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_postopen
+ *
+ * Purpose: Objects that are open in a mounted file remain accessible
+ * after the file is unmounted. Unmounting the file doesn't
+ * close the file.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 14, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_postopen(void)
+{
+
+ hid_t file1=-1, file2=-1, grp=-1;
+
+ printf("%-70s", "Testing open object access after unmount");
+ fflush(stdout);
+
+ /* Create the virtual file */
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDONLY, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDONLY, H5P_DEFAULT))<0)
+ goto error;
+ if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
+
+ /* Open some object in the mounted file */
+ if ((grp=H5Gopen(file1, "/mnt1/file2"))<0) goto error;
+
+ /* Unmount the file */
+ if (H5Funmount(file1, "/mnt1")<0) goto error;
+
+ /* Now access the thing we previously opened */
+ if (H5Gget_objinfo(grp, ".", TRUE, NULL)<0) goto error;
+
+ /* Try accessing it from the file */
+ if (H5Gget_objinfo(file2, "/file2", TRUE, NULL)<0) goto error;
+
+ /* Shut down */
+ if (H5Gclose(grp)<0) goto error;
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose(grp);
+ H5Fclose(file2);
+ H5Fclose(file1);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_unlink
+ *
+ * Purpose: Unlinking the mount point from its name doesn't affect its
+ * existence or the fact that there is a file that is mounted
+ * there.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 13, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_unlink(void)
+{
+ hid_t file1=-1, file2=-1, mnt=-1, root=-1;
+ herr_t status;
+
+ printf("%-70s", "Testing mount point unlinking");
+ fflush(stdout);
+
+ /* Open files */
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDWR, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDWR, H5P_DEFAULT))<0)
+ goto error;
+
+ /*
+ * Opening the mount point before mounting opens the group in the parent
+ * file, but opening the mount point after mounting is the same as
+ * opening the root group of the child file.
+ */
+ if ((mnt=H5Gopen(file1, "/mnt_unlink"))<0) goto error;
+ if (H5Fmount(file1, "/mnt_unlink", file2, H5P_DEFAULT)<0) goto error;
+ if ((root=H5Gopen(file1, "/mnt_unlink"))<0) goto error;
+
+ /*
+ * "/file2" of file2 should be visible as an absolute name through either
+ * file handle but not from the `mnt' handle since that handle was opened
+ * before the H5Fmount() and thus refers to the mount point itself rather
+ * than the group mounted there.
+ */
+ if (H5Gget_objinfo(file1, "/mnt_unlink/file2", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(mnt, "/mnt_unlink/file2", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(root, "/mnt_unlink/file2", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(root, "file2", TRUE, NULL)<0) goto error;
+ H5E_BEGIN_TRY {
+ status = H5Gget_objinfo(mnt, "file2", TRUE, NULL);
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" Incorrect traversal from mount point!");
+ goto error;
+ }
+
+ /* Unlink the mount point */
+ if (H5Gunlink(file1, "/mnt_unlink")<0) goto error;
+
+ /*
+ * We should still be able to get to "/file2" of file2 by starting at
+ * `root' which is still open, but not by name.
+ */
+ if (H5Gget_objinfo(root, "file2", TRUE, NULL)<0) goto error;
+ H5E_BEGIN_TRY {
+ status = H5Gget_objinfo(mnt, "file2", TRUE, NULL);
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" Traversal through mount point should not have worked!");
+ goto error;
+ }
+ H5E_BEGIN_TRY {
+ status = H5Gget_objinfo(file2, "/mnt_unlink/file2", TRUE, NULL);
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" Traversal through mount point should not have worked!");
+ goto error;
+ }
+
+ /*
+ * It's no longer possible to unmount the child by supplying the name of
+ * the mount point because the name doesn't exist anymore. We must
+ * supply the mount point directly.
+ */
+ H5E_BEGIN_TRY {
+ status = H5Funmount(file1, "/mnt_unlink");
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" Unmount by name should not have been allowed!");
+ goto error;
+ }
+ H5E_BEGIN_TRY {
+ status = H5Funmount(file2, "/");
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" Unmount by name should not have been allowed!");
+ goto error;
+ }
+ if (H5Funmount(mnt, ".")<0) goto error;
+
+ /* Close files */
+ if (H5Gclose(mnt)<0) goto error;
+ if (H5Gclose(root)<0) goto error;
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose(mnt);
+ H5Gclose(root);
+ H5Fclose(file2);
+ H5Fclose(file1);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_mvmpt
+ *
+ * Purpose: Try renaming the mount point while a file is mounted there.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 13, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_mvmpt(void)
+{
+ hid_t file1=-1, file2=-1;
+
+ printf("%-70s", "Testing mount point renaming");
+ fflush(stdout);
+
+ /* Build the virtual file */
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDWR, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDWR, H5P_DEFAULT))<0)
+ goto error;
+ if (H5Fmount(file1, "/mnt_move_a", file2, H5P_DEFAULT)<0) goto error;
+
+ /* Rename the mount point */
+ if (H5Gmove(file1, "/mnt_move_a", "/mnt_move_b")<0) goto error;
+
+ /* Access something under the new name */
+ if (H5Gget_objinfo(file1, "/mnt_move_b/file2", TRUE, NULL)<0) goto error;
+
+ /* Shut down */
+ if (H5Funmount(file1, "/mnt_move_b")<0) goto error;
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Fclose(file1);
+ H5Fclose(file2);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_interlink
+ *
+ * Purpose: Hard links cannot cross file boundaries.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 14, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_interlink(void)
+{
+ hid_t file1=-1, file2=-1, type=-1, space=-1, dset=-1;
+ herr_t status;
+ hsize_t cur_dims[1] = {2};
+
+ printf("%-70s", "Testing interfile hard links");
+ fflush(stdout);
+
+ /* Build the virtual file */
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDWR, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDWR, H5P_DEFAULT))<0)
+ goto error;
+ if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
+
+ /* Try an interfile hard link directly */
+ H5E_BEGIN_TRY {
+ status = H5Glink(file1, H5G_LINK_HARD, "/mnt1/file2", "/file2");
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" Interfile hard link should not have been allowed!");
+ goto error;
+ }
+
+ /* Try an interfile hard link by renaming something */
+ H5E_BEGIN_TRY {
+ status = H5Gmove(file1, "/mnt1/file2", "/file2");
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" Interfile renaming should not have been allowed!");
+ goto error;
+ }
+
+ /* Try an interfile hard link by sharing a data type */
+ if ((type=H5Tcopy(H5T_NATIVE_INT))<0) goto error;
+ if (H5Tcommit(file1, "/type1", type)<0) goto error;
+ if ((space=H5Screate_simple(1, cur_dims, NULL))<0) goto error;
+ H5E_BEGIN_TRY {
+ dset = H5Dcreate(file1, "/mnt1/file2/dset", type, space, H5P_DEFAULT);
+ } H5E_END_TRY;
+ if (dset>=0) {
+ puts("*FAILED*");
+ puts(" Dataset and shared type must be in the same file!");
+ goto error;
+ }
+
+ /* Shut down */
+ if (H5Sclose(space)<0) goto error;
+ if (H5Tclose(type)<0) goto error;
+ if (H5Funmount(file1, "/mnt1")<0) goto error;
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Dclose(dset);
+ H5Sclose(space);
+ H5Tclose(type);
+ H5Fclose(file1);
+ H5Fclose(file2);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_uniformity
+ *
+ * Purpose: Any file handle is equivalent to any other file handle in the
+ * same virtual file.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 14, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_uniformity(void)
+{
+ hid_t file1=-1, file2=-1;
+
+ printf("%-70s", "Testing file handle uniformity");
+ fflush(stdout);
+
+ /* Build the virtual file */
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDWR, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDWR, H5P_DEFAULT))<0)
+ goto error;
+ if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
+
+ /* Access some things from the file1 handle */
+ if (H5Gget_objinfo(file1, "/", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(file1, "/mnt1", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(file1, "mnt1", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(file1, "/mnt1/file2", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(file1, "mnt1/file2", TRUE, NULL)<0) goto error;
+
+ /* Access the same things from the file2 handle */
+ if (H5Gget_objinfo(file2, "/", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(file2, "/mnt1", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(file2, "mnt1", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(file2, "/mnt1/file2", TRUE, NULL)<0) goto error;
+ if (H5Gget_objinfo(file2, "mnt1/file2", TRUE, NULL)<0) goto error;
+
+ /* Shut down */
+ if (H5Funmount(file1, "/mnt1")<0) goto error;
+ if (H5Fclose(file1)<0) goto error;
+ if (H5Fclose(file2)<0) goto error;
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Fclose(file1);
+ H5Fclose(file2);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_close
+ *
+ * Purpose: Closing any file handle closes the entire virtual file.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 14, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_close(void)
+{
+ hid_t file1=-1, file2=-1;
+ herr_t status;
+
+ printf("%-70s", "Testing file handle close");
+ fflush(stdout);
+#if 1
+ puts(" SKIP");
+ puts(" Skipped for now (until H5F_t refcounts are implemented)...");
+ return 0;
+#endif
+
+ /* Build the virtual file */
+ if ((file1=H5Fopen(FILE_NAME_1, H5F_ACC_RDWR, H5P_DEFAULT))<0 ||
+ (file2=H5Fopen(FILE_NAME_2, H5F_ACC_RDWR, H5P_DEFAULT))<0)
+ goto error;
+ if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error;
+
+ /* Close by file1 */
+ if (H5Fclose(file1)<0) goto error;
+ H5E_BEGIN_TRY {
+ status = H5Fclose(file2);
+ } H5E_END_TRY;
+ if (status>=0) {
+ puts("*FAILED*");
+ puts(" File close should have closed all virtual file members!");
+ goto error;
+ }
+
+ /* Shut down */
+ puts(" PASSED");
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Fclose(file1);
+ H5Fclose(file2);
+ } H5E_END_TRY;
+ return 1;
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: Test file mounting
+ *
+ * Return: Success: zero
+ *
+ * Failure: non-zero
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 7, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ int nerrors = 0;
+
+ H5Eset_auto(display_error_cb, NULL);
+ if (setup()<0) goto error;
+
+ nerrors += test_basic();
+ nerrors += test_illegal();
+ nerrors += test_hide();
+ nerrors += test_assoc();
+ nerrors += test_mntlnk();
+ nerrors += test_unlink();
+ nerrors += test_move();
+ nerrors += test_mvmpt();
+ nerrors += test_preopen();
+ nerrors += test_postopen();
+ nerrors += test_interlink();
+ nerrors += test_uniformity();
+ nerrors += test_close();
+
+ if (nerrors) goto error;
+ puts("All mount tests passed.");
+ cleanup();
+ exit(0);
+
+ error:
+ puts("***** MOUNT ERRORS *****");
+ exit(1);
+}