summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormattjala <124107509+mattjala@users.noreply.github.com>2023-11-11 04:34:46 (GMT)
committerGitHub <noreply@github.com>2023-11-11 04:34:46 (GMT)
commit5e0b59a70cc093b6ce17820a78de410201867226 (patch)
treeb559cda1fe0ed1fbe759a39434ef5ef72ffbd785
parentafb1f3c19ace049faa1404b312b4ff44560a03f6 (diff)
downloadhdf5-5e0b59a70cc093b6ce17820a78de410201867226.zip
hdf5-5e0b59a70cc093b6ce17820a78de410201867226.tar.gz
hdf5-5e0b59a70cc093b6ce17820a78de410201867226.tar.bz2
Test and document path handling of H5Lcreate_* API (#3829)
-rw-r--r--src/H5Lpublic.h27
-rw-r--r--test/links.c250
2 files changed, 270 insertions, 7 deletions
diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h
index 03b47c5..2bf3c53 100644
--- a/src/H5Lpublic.h
+++ b/src/H5Lpublic.h
@@ -260,9 +260,13 @@ H5_DLL herr_t H5Lcopy(hid_t src_loc, const char *src_name, hid_t dst_loc, const
* location and name, respectively, of the new hard link.
*
* \p cur_name and \p dst_name are interpreted relative to \p cur_loc
- * and \p dst_loc, respectively. If \p cur_loc and \p dst_loc are the
- * same location, the HDF5 macro #H5L_SAME_LOC can be used for either
- * parameter (but not both).
+ * and \p dst_loc, respectively. If a given name begins with \c /,
+ * then it will be interpreted as absolute path in the file.
+ * The names of the created links will be the last element of
+ * each provided path. Prior elements in each path are used to
+ * locate the parent groups of each new link. If \p cur_loc and
+ * \p dst_loc are the same location, the HDF5 macro
+ * #H5L_SAME_LOC can be used for either parameter (but not both).
*
* \p lcpl_id and \p lapl_id are the link creation and access property
* lists associated with the new link.
@@ -321,8 +325,10 @@ H5_DLL herr_t H5Lcreate_hard_async(hid_t cur_loc_id, const char *cur_name, hid_t
*
* \p link_loc_id and \p link_name specify the location and name,
* respectively, of the new soft link. \p link_name is interpreted
- * relative to \p link_loc_id and must contain only the name of the soft
- * link; \p link_name may not contain any additional path elements.
+ * as a path relative to \p link_loc_id, or an absolute path if it
+ * begins with \c /. The name of the created link will be the last
+ * element of the provided path. Prior elements in the path are
+ * used to locate the parent group of the new link.
*
* If \p link_loc_id is a group identifier, the object pointed to by
* \p link_name will be accessed as a member of that group. If
@@ -1190,7 +1196,11 @@ H5_DLL herr_t H5Lvisit_by_name2(hid_t loc_id, const char *group_name, H5_index_t
* named \p link_name at the location specified in \p link_loc_id with
* user-specified data \p udata.
*
- * \p link_name is interpreted relative to \p link_loc_id.
+ * \p link_name is interpreted relative to \p link_loc_id. If
+ * \p link_name begins with \c /, then it will be interpreted as
+ * an absolute path in the file. The name of the created link
+ * will be the last element of the provided path. Prior elements
+ * in the path are used to locate the parent group of the new link.
*
* Valid values for the link class of the new link, \p link_type,
* include #H5L_TYPE_EXTERNAL and any user-defined link classes that
@@ -1307,7 +1317,10 @@ H5_DLL herr_t H5Lunpack_elink_val(const void *ext_linkval /*in*/, size_t link_si
*
* \p link_loc_id and \p link_name specify the location and name,
* respectively, of the new link. \p link_name is interpreted relative
- * to \p link_loc_id.
+ * to \p link_loc_id. If \p link_name begins with \c /, then it is
+ * interpreted as an absolute path in the file. The name of the created
+ * link will be the last element of the provided path. Prior elements in
+ * the path are used to locate the parent group of the new link.
*
* \p lcpl_id is the link creation property list used in creating the
* new link.
diff --git a/test/links.c b/test/links.c
index 99e0114..e068d71 100644
--- a/test/links.c
+++ b/test/links.c
@@ -22624,6 +22624,253 @@ error:
} /* end timestamps() */
/*-------------------------------------------------------------------------
+ * Function: link_path_handling
+ *
+ * Purpose: Create hard and soft links by relative and absolute paths
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *-------------------------------------------------------------------------
+ */
+static int
+link_path_handling(hid_t fapl, bool new_format)
+{
+
+ hid_t file_id = (H5I_INVALID_HID);
+ hid_t grp1 = (H5I_INVALID_HID), grp2 = (H5I_INVALID_HID);
+ char filename[NAME_BUF_SIZE];
+
+ if (new_format)
+ TESTING("H5Lcreate path handling (w/new group format)");
+ else
+ TESTING("H5Lcreate path handling");
+
+ /* Create file */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ if ((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR;
+
+ /* Create two groups */
+ if ((grp1 = H5Gcreate2(file_id, "grp1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+ if ((grp2 = H5Gcreate2(grp1, "grp2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Create hard link to grp1 that resides in grp2 by relative path */
+ if (H5Lcreate_hard(file_id, "grp1", grp1, "grp2/relative_hard_link", H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR;
+
+ if (H5Lexists(grp2, "relative_hard_link", H5P_DEFAULT) <= 0)
+ TEST_ERROR;
+
+ /* Create soft link to grp1 that resides in grp2 by relative path */
+ if (H5Lcreate_soft("/grp1", grp1, "grp2/relative_soft_link", H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR;
+
+ if (H5Lexists(grp2, "relative_soft_link", H5P_DEFAULT) <= 0)
+ TEST_ERROR;
+
+ /* Create hard link to grp1 that resides in grp2 by absolute path */
+ if (H5Lcreate_hard(file_id, "grp1", grp1, "/grp1/grp2/absolute_hard_link", H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR;
+
+ if (H5Lexists(grp2, "absolute_hard_link", H5P_DEFAULT) <= 0)
+ TEST_ERROR;
+
+ /* Create soft link to grp1 that resides in grp2 by absolute path */
+ if (H5Lcreate_soft("/grp1", grp1, "/grp1/grp2/absolute_soft_link", H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR;
+
+ if (H5Lexists(grp2, "absolute_soft_link", H5P_DEFAULT) <= 0)
+ TEST_ERROR;
+
+ /* Close groups and file */
+ if (H5Gclose(grp1) < 0)
+ TEST_ERROR;
+ if (H5Gclose(grp2) < 0)
+ TEST_ERROR;
+ if (H5Fclose(file_id) < 0)
+ TEST_ERROR;
+
+ PASSED();
+ return SUCCEED;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Gclose(grp1);
+ H5Gclose(grp2);
+ H5Fclose(file_id);
+ }
+ H5E_END_TRY
+ return FAIL;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: ext_link_path_handling
+ *
+ * Purpose: Create external links by relative and absolute paths
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *-------------------------------------------------------------------------
+ */
+static int
+ext_link_path_handling(hid_t fapl, bool new_format)
+{
+
+ hid_t file_id = (H5I_INVALID_HID);
+ hid_t grp1 = (H5I_INVALID_HID), grp2 = (H5I_INVALID_HID);
+ char filename[NAME_BUF_SIZE];
+
+ if (new_format)
+ TESTING("H5Lcreate external link path handling (w/new group format)");
+ else
+ TESTING("H5Lcreate external link path handling");
+
+ /* Create file */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ if ((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR;
+
+ /* Create two groups */
+ if ((grp1 = H5Gcreate2(file_id, "grp1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+ if ((grp2 = H5Gcreate2(grp1, "grp2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Create external link to nonexistent object by relative path */
+ if (H5Lcreate_external("nonexistent_file", "nonexistent_object", grp1, "grp2/relative_ext_link",
+ H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR;
+
+ if (H5Lexists(grp2, "relative_ext_link", H5P_DEFAULT) <= 0)
+ TEST_ERROR;
+
+ /* Create external link to nonexistent object by absolute path */
+ if (H5Lcreate_external("nonexistent_file", "nonexistent_object", grp1, "/grp1/grp2/relative_soft_link",
+ H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR;
+
+ if (H5Lexists(grp2, "relative_soft_link", H5P_DEFAULT) <= 0)
+ TEST_ERROR;
+
+ /* Close groups and file */
+ if (H5Gclose(grp1) < 0)
+ TEST_ERROR;
+ if (H5Gclose(grp2) < 0)
+ TEST_ERROR;
+ if (H5Fclose(file_id) < 0)
+ TEST_ERROR;
+
+ PASSED();
+ return SUCCEED;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Gclose(grp1);
+ H5Gclose(grp2);
+ H5Fclose(file_id);
+ }
+ H5E_END_TRY
+ return FAIL;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: ud_link_path_handling
+ *
+ * Purpose: Create user-defined links by relative and absolute paths
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *-------------------------------------------------------------------------
+ */
+static int
+ud_link_path_handling(hid_t fapl, bool new_format)
+{
+
+ hid_t file_id = (H5I_INVALID_HID);
+ hid_t grp1 = (H5I_INVALID_HID), grp2 = (H5I_INVALID_HID);
+ char filename[NAME_BUF_SIZE];
+ H5L_info2_t li;
+
+ if (new_format)
+ TESTING("H5Lcreate ud link path handling (w/new group format)");
+ else
+ TESTING("H5Lcreate ud link path handling");
+
+ /* Create file */
+ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
+
+ if ((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR;
+
+ /* Create two groups */
+ if ((grp1 = H5Gcreate2(file_id, "grp1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+ if ((grp2 = H5Gcreate2(grp1, "grp2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Check that UD hard links are not registered */
+ if (H5Lis_registered((H5L_type_t)UD_HARD_TYPE) != false)
+ 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((H5L_type_t)UD_HARD_TYPE) != true)
+ TEST_ERROR;
+
+ if (H5Lget_info2(file_id, "grp1", &li, H5P_DEFAULT) < 0)
+ TEST_ERROR;
+
+ /* Create user-defined (hard) link to grp1 by relative path */
+ if (H5Lcreate_ud(grp1, "grp2/relative_ud_link", (H5L_type_t)UD_HARD_TYPE, &(li.u.token),
+ sizeof(li.u.token), H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR;
+
+ if (H5Lexists(grp2, "relative_ud_link", H5P_DEFAULT) <= 0)
+ TEST_ERROR;
+
+ /* Create user-defined (hard) link to grp1 by absolute path */
+ if (H5Lcreate_ud(grp1, "/grp1/grp2/absolute_ud_link", (H5L_type_t)UD_HARD_TYPE, &(li.u.token),
+ sizeof(li.u.token), H5P_DEFAULT, H5P_DEFAULT) < 0)
+ TEST_ERROR;
+
+ if (H5Lexists(grp2, "absolute_ud_link", H5P_DEFAULT) <= 0)
+ TEST_ERROR;
+
+ /* Close groups and file */
+ if (H5Gclose(grp1) < 0)
+ TEST_ERROR;
+ if (H5Gclose(grp2) < 0)
+ TEST_ERROR;
+ if (H5Fclose(file_id) < 0)
+ TEST_ERROR;
+ if (H5Lunregister((H5L_type_t)UD_HARD_TYPE) < 0)
+ TEST_ERROR;
+
+ PASSED();
+ return SUCCEED;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Gclose(grp1);
+ H5Gclose(grp2);
+ H5Fclose(file_id);
+ H5Lunregister((H5L_type_t)UD_HARD_TYPE);
+ }
+ H5E_END_TRY
+ return FAIL;
+}
+
+/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Test links
@@ -22697,6 +22944,7 @@ main(void)
nerrors += ck_new_links(my_fapl, new_format) < 0 ? 1 : 0;
nerrors += long_links(my_fapl, new_format) < 0 ? 1 : 0;
nerrors += toomany(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += link_path_handling(my_fapl, new_format) < 0 ? 1 : 0;
/* Test new H5L link creation routine */
nerrors += test_lcpl(my_fapl, new_format);
@@ -22804,6 +23052,7 @@ main(void)
nerrors += external_open_twice(my_fapl, new_format) < 0 ? 1 : 0;
nerrors += external_link_with_committed_datatype(my_fapl, new_format) < 0 ? 1 : 0;
nerrors += external_link_public_macros(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += ext_link_path_handling(my_fapl, new_format) < 0 ? 1 : 0;
} /* with/without external file cache */
}
@@ -22826,6 +23075,7 @@ main(void)
nerrors += ud_callbacks_deprec(my_fapl, new_format) < 0 ? 1 : 0;
#endif /* H5_NO_DEPRECATED_SYMBOLS */
nerrors += ud_link_errors(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += ud_link_path_handling(my_fapl, new_format) < 0 ? 1 : 0;
nerrors += lapl_udata(my_fapl, new_format) < 0 ? 1 : 0;
nerrors += lapl_nlinks(my_fapl, new_format) < 0 ? 1 : 0;
#ifndef H5_NO_DEPRECATED_SYMBOLS