summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.in18
-rw-r--r--src/H5F.c41
-rw-r--r--src/H5Fpkg.h1
-rw-r--r--src/H5Fprivate.h3
-rw-r--r--src/H5Lexternal.c200
-rw-r--r--src/H5config.h.in3
-rw-r--r--src/H5private.h47
-rw-r--r--src/H5system.c96
-rw-r--r--test/Makefile.am3
-rw-r--r--test/Makefile.in4
-rw-r--r--test/links.c895
11 files changed, 1268 insertions, 43 deletions
diff --git a/configure.in b/configure.in
index 2a4c06c..67f881c 100644
--- a/configure.in
+++ b/configure.in
@@ -2814,6 +2814,24 @@ else
AC_MSG_RESULT([false])
fi
+dnl ----------------------------------------------------------------------
+dnl Set the flag to indicate that the machine has window style pathname,
+dnl that is, "drive-letter:\" (e.g. "C:") or "drive-letter:/" (e.g. "C:/").
+dnl (This flag should be _unset_ for all machines, except for Windows, where
+dnl it's set in the custom Windows H5pubconf.h file)
+dnl
+AC_MSG_CHECKING([if the machine has window style path name])
+AC_CACHE_VAL([hdf5_have_window_path], [hdf5_have_window_path=no])
+
+if test ${hdf5_have_window_path} = "yes"; then
+ AC_DEFINE([HAVE_WINDOW_PATH], [1],
+ [Define if your system has window style path name.])
+ AC_MSG_RESULT([true])
+else
+ AC_MSG_RESULT([false])
+fi
+
+
dnl -----------------------------------------------------------------------
dnl Set flag to indicate that the machine can handle conversion from
dnl long double to integers accurately. This flag should be set "yes" for
diff --git a/src/H5F.c b/src/H5F.c
index cb9e3b8..80c28bc 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -978,6 +978,9 @@ done:
* Programmer: Robb Matzke
* matzke@llnl.gov
* Jul 18 1997
+ * Modifications:
+ * Vailin Choi, April 2, 2008
+ * Free f->extpath
*
*-------------------------------------------------------------------------
*/
@@ -1068,6 +1071,7 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
/* Free the non-shared part of the file */
f->name = H5MM_xfree(f->name);
+ f->extpath = H5MM_xfree(f->extpath);
f->mtab.child = H5MM_xfree(f->mtab.child);
f->mtab.nalloc = 0;
if(H5FO_top_dest(f) < 0)
@@ -1078,6 +1082,8 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_dest() */
+
+
/*-------------------------------------------------------------------------
* Function: H5F_open
@@ -1157,6 +1163,9 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
* Modified H5F_flush call to take one flag instead of
* multiple Boolean flags.
*
+ * Vailin Choi, 2008-04-02
+ * To formulate path for later searching of target file for external link
+ * via H5_build_extpath().
*-------------------------------------------------------------------------
*/
H5F_t *
@@ -1353,6 +1362,10 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
} /* end if */
+ /* formulate the absolute path for later search of target file for external link */
+ if (H5_build_extpath(name, &file->extpath) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath")
+
/* Success */
ret_value = file;
@@ -2140,6 +2153,33 @@ H5F_get_intent(const H5F_t *f)
/*-------------------------------------------------------------------------
+ * Function: H5F_get_extpath
+ *
+ * Purpose: Retrieve the file's 'extpath' flags
+ * This is used by H5L_extern_traverse() to retrieve the main file's location
+ * when searching the target file.
+ *
+ * Return: 'extpath' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Vailin Choi, April 2, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+H5F_get_extpath(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_extpath)
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(f->extpath)
+} /* end H5F_get_extpath() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_sizeof_addr
*
* Purpose: Quick and dirty routine to retrieve the size of the file's size_t
@@ -3618,4 +3658,3 @@ H5Fget_info(hid_t obj_id, H5F_info_t *finfo)
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_info() */
-
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 3f10e1a..288ef8a 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -142,6 +142,7 @@ typedef struct H5F_mtab_t {
struct H5F_t {
unsigned intent; /* The flags passed to H5F_open()*/
char *name; /* Name used to open file */
+ char *extpath; /* Path for searching target external link file */
H5F_file_t *shared; /* The shared file info */
unsigned nopen_objs; /* Number of open object headers*/
H5FO_t *obj_count; /* # of time each object is opened through top file structure */
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 1044b14..27b45f2 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -265,6 +265,7 @@ typedef struct H5F_t H5F_t;
#define H5F_GC_REF(F) ((F)->shared->gc_ref)
#define H5F_USE_LATEST_FORMAT(F) ((F)->shared->latest_format)
#define H5F_INTENT(F) ((F)->intent)
+#define H5F_EXTPATH(F) ((F)->extpath)
#define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree)
#define H5F_STORE_MSG_CRT_IDX(F) ((F)->shared->store_msg_crt_idx)
#define H5F_GET_FILENO(F,FILENUM) ((FILENUM) = (F)->shared->lf->fileno)
@@ -284,6 +285,7 @@ typedef struct H5F_t H5F_t;
#define H5F_GC_REF(F) (H5F_gc_ref(F))
#define H5F_USE_LATEST_FORMAT(F) (H5F_use_latest_format(F))
#define H5F_INTENT(F) (H5F_get_intent(F))
+#define H5F_EXTPATH(F) (H5F_get_extpath(F))
#define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F))
#define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F))
#define H5F_GET_FILENO(F,FILENUM) (H5F_get_filenum((F), &(FILENUM)))
@@ -417,6 +419,7 @@ H5_DLL herr_t H5F_try_close(H5F_t *f);
H5_DLL hid_t H5F_get_driver_id(const H5F_t *f);
H5_DLL hid_t H5F_get_access_plist(H5F_t *f);
H5_DLL unsigned H5F_get_intent(const H5F_t *f);
+H5_DLL char *H5F_get_extpath(const H5F_t *f);
H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum);
H5_DLL hid_t H5F_get_id(H5F_t *file);
H5_DLL unsigned H5F_get_obj_count(const H5F_t *f, unsigned types);
diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c
index 5a8eb33..4e355bb 100644
--- a/src/H5Lexternal.c
+++ b/src/H5Lexternal.c
@@ -76,6 +76,81 @@ H5L_init_extern_interface(void)
} /* H5L_init_extern_interface() */
+
+/*--------------------------------------------------------------------------
+ * Function: H5L_getenv_prefix_name --
+ *
+ * Purpose: Get the first pathname in the list of pathnames stored in ENV_PREFIX,
+ * which is separated by the environment delimiter.
+ * ENV_PREFIX is modified to point to the remaining pathnames
+ * in the list.
+ *
+ * Return: A pointer to a pathname
+ *
+ * Programmer: Vailin Choi, April 2, 2008
+ *
+--------------------------------------------------------------------------*/
+static char *
+H5L_getenv_prefix_name(char **env_prefix/*in,out*/)
+{
+ char *retptr=NULL;
+ char *strret=NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5L_getenv_prefix_name)
+
+ strret = HDstrchr(*env_prefix, COLON_SEPC);
+ if (strret == NULL) {
+ retptr = *env_prefix;
+ *env_prefix = strret;
+ } else {
+ retptr = *env_prefix;
+ *env_prefix = strret + 1;
+ *strret = '\0';
+ }
+ return(retptr);
+ FUNC_LEAVE_NOAPI(retptr)
+}
+
+
+/*--------------------------------------------------------------------------
+ * Function: H5L_build_name
+ *
+ * Purpose: Prepend PREFIX to FILE_NAME and store in FULL_NAME
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi, April 2, 2008
+ *
+--------------------------------------------------------------------------*/
+static herr_t
+H5L_build_name(char *prefix, char *file_name, char **full_name/*out*/)
+{
+ size_t prefix_len; /* length of prefix */
+ size_t fname_len; /* Length of external link file name */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_build_name)
+
+ prefix_len = HDstrlen(prefix);
+ fname_len = HDstrlen(file_name);
+
+ /* Allocate a buffer to hold the filename + prefix + possibly the delimiter + terminating null byte */
+ if(NULL == (*full_name = H5MM_malloc(prefix_len + fname_len + 2)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer")
+
+ /* Copy the prefix into the buffer */
+ HDstrcpy(*full_name, prefix);
+ if (!CHECK_DELIMITER(prefix[prefix_len-1]))
+ HDstrcat(*full_name, DIR_SEPS);
+
+ /* Add the external link's filename to the prefix supplied */
+ HDstrcat(*full_name, file_name);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5L_build_name() */
+
+
/*-------------------------------------------------------------------------
* Function: H5L_extern_traverse
*
@@ -92,6 +167,10 @@ H5L_init_extern_interface(void)
*
* Programmer: James Laird
* Monday, July 10, 2006
+ * Modifications:
+ * Vailin Choi, April 2, 2008
+ * Add handling to search for the target file
+ * See description in RM: H5Lcreate_external
*
*-------------------------------------------------------------------------
*/
@@ -114,6 +193,11 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
hid_t ext_obj = -1; /* ID for external link's object */
hid_t ret_value; /* Return value */
+ char *tempname=NULL, *ptr=NULL, *extpath=NULL;
+ char *env_prefix=NULL, *tmp_env_prefix=NULL;
+ char *out_prefix_name=NULL, *pp=NULL;
+
+
FUNC_ENTER_NOAPI(H5L_extern_traverse, FAIL)
/* Sanity checks */
@@ -135,28 +219,6 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
- /* Get the current prefix */
- if(H5P_get(plist, H5L_ACS_ELINK_PREFIX_NAME, &my_prefix) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external link prefix")
-
- /* Check for prefix being set, if so, prepend it to the filename */
- if(my_prefix) {
- size_t prefix_len = HDstrlen(my_prefix);
-
- /* Allocate a buffer to hold the filename plus prefix */
- if(NULL == (full_name = H5MM_malloc(prefix_len + fname_len + 1)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer")
-
- /* Copy the prefix into the buffer */
- HDstrcpy(full_name, my_prefix);
-
- /* Add the external link's filename to the prefix supplied */
- HDstrcat(full_name, (const char *)p);
-
- /* Point to name w/prefix */
- file_name = full_name;
- } /* end if */
-
/* Get the location for the group holding the external link */
if(H5G_loc(cur_group, &loc) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get object location")
@@ -183,10 +245,92 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
} /* end if */
- /* Open the external file */
- /* (extra work with file intent to mask off inappropriate flags) */
- if(NULL == (ext_file = H5F_open(file_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY), H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
- HGOTO_ERROR(H5E_LINK, H5E_CANTOPENFILE, FAIL, "unable to open external file")
+ /*
+ * Start searching for the target file
+ */
+ if ((tempname=H5MM_strdup(file_name)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* target file_name is an absolute pathname: see RM for detailed description */
+ if (CHECK_ABSOLUTE(file_name) || CHECK_ABS_PATH(file_name)) {
+ if(NULL == (ext_file = H5F_open(file_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id))) {
+ H5E_clear_stack(NULL);
+ /* get last component of file_name */
+ GET_LAST_DELIMITER(file_name, ptr)
+ HDassert(ptr);
+ HDstrcpy(tempname, ++ptr);
+ }
+ } else if (CHECK_ABS_DRIVE(file_name)) {
+ if(NULL == (ext_file = H5F_open(file_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id))) {
+ H5E_clear_stack(NULL);
+ /* strip "<drive-letter>:" */
+ HDstrcpy(tempname, &file_name[2]);
+ }
+ }
+
+ /* try searching from paths set in the environment variable */
+ if ((ext_file == NULL) && (env_prefix=HDgetenv("HDF5_EXT_PREFIX"))) {
+
+ tmp_env_prefix = H5MM_strdup(env_prefix);
+ pp = tmp_env_prefix;
+
+ while ((tmp_env_prefix) && (*tmp_env_prefix)) {
+ out_prefix_name = H5L_getenv_prefix_name(&tmp_env_prefix/*in,out*/);
+ if ((out_prefix_name) && (*out_prefix_name)) {
+
+ if (H5L_build_name(out_prefix_name, tempname, &full_name/*out*/) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
+
+ ext_file = H5F_open(full_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id);
+ if (full_name)
+ H5MM_xfree(full_name);
+ if (ext_file != NULL)
+ break;
+ H5E_clear_stack(NULL);
+ }
+ } /* end while */
+ if (pp)
+ H5MM_xfree(pp);
+ }
+
+ /* try searching from property list */
+ if (ext_file == NULL) {
+ if(H5P_get(plist, H5L_ACS_ELINK_PREFIX_NAME, &my_prefix) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external link prefix")
+ if (my_prefix) {
+ if (H5L_build_name(my_prefix, tempname, &full_name/*out*/) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
+ if ((ext_file=H5F_open(full_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL)
+ H5E_clear_stack(NULL);
+ if (full_name)
+ H5MM_xfree(full_name);
+ }
+ }
+
+ /* try searching from main file's "extpath":see description in H5F_open() & H5_build_extpath() */
+ if ((ext_file == NULL) && (extpath=H5F_EXTPATH(loc.oloc->file))) {
+ if (H5L_build_name(extpath, tempname, &full_name/*out*/) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
+ if ((ext_file = H5F_open(full_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL)
+ H5E_clear_stack(NULL);
+ if (full_name)
+ H5MM_xfree(full_name);
+ }
+
+ /* try the relative file_name stored in tempname */
+ if (ext_file == NULL) {
+ if ((ext_file=H5F_open(tempname, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTOPENFILE, FAIL, "unable to open external file")
+ }
+
+ if (tempname)
+ H5MM_xfree(tempname);
/* Increment the number of open objects, to hold the file open */
H5F_incr_nopen_objs(ext_file);
@@ -219,10 +363,6 @@ done:
if(ext_file && H5F_try_close(ext_file) < 0)
HDONE_ERROR(H5E_LINK, H5E_CANTCLOSEFILE, FAIL, "problem closing external file")
- /* Free full_name if it's been allocated */
- if(full_name)
- H5MM_xfree(full_name);
-
/* Close object if it's open and something failed */
if(ret_value < 0 && ext_obj >= 0 && H5I_dec_ref(ext_obj) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for external object")
diff --git a/src/H5config.h.in b/src/H5config.h.in
index 5c767ef..77a3b23 100644
--- a/src/H5config.h.in
+++ b/src/H5config.h.in
@@ -368,6 +368,9 @@
/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID
+/* Define if your system has window style path name. */
+#undef HAVE_WINDOW_PATH
+
/* Define to 1 if you have the <winsock.h> header file. */
#undef HAVE_WINSOCK_H
diff --git a/src/H5private.h b/src/H5private.h
index 11f3037..734290d 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -638,9 +638,19 @@ H5_DLL int HDfprintf (FILE *stream, const char *fmt, ...);
#define HDfwrite(M,Z,N,F) fwrite(M,Z,N,F)
#define HDgetc(F) getc(F)
#define HDgetchar() getchar()
+#ifdef _WIN32
+#define HDgetcwd(S,Z) _getcwd(S,Z)
+#define HDgetdcwd(D,S,Z) _getdcwd(D,S,Z)
+#define HDgetdrive() _getdrive()
+#else
#define HDgetcwd(S,Z) getcwd(S,Z)
+#define HDgetdcwd(D,S,Z) getcwd(S,Z)
+#define HDgetdrive() 0
+#endif
#define HDgetegid() getegid()
#define HDgetenv(S) getenv(S)
+#define HDsetenv(S,V,O) setenv(S,V,O)
+#define HDunsetenv(S) unsetenv(S)
#define HDgeteuid() geteuid()
#define HDgetgid() getgid()
#define HDgetgrgid(G) getgrgid(G)
@@ -911,6 +921,43 @@ extern char *strdup(const char *s);
#endif /* _WIN32 */
+#ifdef H5_HAVE_WINDOW_PATH
+
+/* directory delimiter for Windows: slash and backslash are acceptable on Windows */
+#define DIR_SLASH_SEPC '/'
+#define DIR_SEPC '\\'
+#define DIR_SEPS "\\"
+#define CHECK_DELIMITER(SS) ((SS == DIR_SEPC)||(SS == DIR_SLASH_SEPC))
+#define CHECK_ABSOLUTE(NAME) (((isalpha(NAME[0])) && (NAME[1] == ':') && CHECK_DELIMITER(NAME[2]))
+#define CHECK_ABS_DRIVE(NAME) ((isalpha(NAME[0])) && (NAME[1] == ':'))
+#define CHECK_ABS_PATH(NAME) (CHECK_DELIMITER(NAME[0]))
+
+#define GET_LAST_DELIMITER(NAME, ptr) { \
+ char *slash, *backslash; \
+ slash = strrchr(NAME, DIR_SLASH_SEPC); \
+ backslash = strrchr(NAME, DIR_SEPC); \
+ if (backslash > slash) \
+ (ptr = backslash); \
+ else \
+ (ptr = slash); \
+}
+
+
+#else
+
+#define DIR_SEPC '/'
+#define DIR_SEPS "/"
+#define CHECK_DELIMITER(SS) (SS == DIR_SEPC)
+#define CHECK_ABSOLUTE(NAME) (CHECK_DELIMITER(*NAME))
+#define CHECK_ABS_DRIVE(NAME) (0)
+#define CHECK_ABS_PATH(NAME) (0)
+#define GET_LAST_DELIMITER(NAME, ptr) ptr = strrchr(NAME, DIR_SEPC);
+
+#endif
+
+#define COLON_SEPC ':'
+H5_DLL herr_t H5_build_extpath(const char *, char **/*out*/);
+
/*
* These macros check whether debugging has been requested for a certain
diff --git a/src/H5system.c b/src/H5system.c
index 5eae11d..d65103a 100644
--- a/src/H5system.c
+++ b/src/H5system.c
@@ -35,6 +35,8 @@
#include "H5private.h" /* Generic Functions */
#include "H5Fprivate.h" /* File access */
#include "H5MMprivate.h" /* Memory management */
+#include "H5Eprivate.h"
+
/****************/
@@ -578,4 +580,98 @@ HDremove_all(const char *fname)
}
#endif
+
+/*
+ *
+ * Function: H5_build_extpath
+ *
+ * Purpose: To build the path for later searching of target file for external link.
+ * This path can be either:
+ * 1. The absolute path of NAME
+ * or
+ * 2. The current working directory + relative path of NAME
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * April 2, 2008
+ */
+#define MAX_PATH_LEN 1024
+
+herr_t
+H5_build_extpath(const char *name, char **extpath/*out*/)
+{
+ char *full_path=NULL, *ptr=NULL;
+ char *retcwd=NULL, *cwdpath=NULL, *new_name=NULL;
+ int drive;
+ size_t cwdlen, path_len;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5_build_extpath)
+
+ *extpath = NULL;
+
+ /*
+ * Unix: name[0] is a "/"
+ * Windows: name[0-2] is "<drive letter>:\" or "<drive-letter>:/"
+ */
+ if (CHECK_ABSOLUTE(name)) {
+ if ((full_path=H5MM_strdup(name)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } else { /* relative pathname */
+ if ((cwdpath=H5MM_malloc(MAX_PATH_LEN)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if ((new_name=H5MM_strdup(name)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /*
+ * Windows: name[0-1] is "<drive-letter>:"
+ * Get current working directory on the drive specified in NAME
+ * Unix: does not apply
+ */
+ if (CHECK_ABS_DRIVE(name)) {
+ drive = name[0] - 'A' + 1;
+ retcwd = HDgetdcwd(drive, cwdpath, MAX_PATH_LEN);
+ HDstrcpy(new_name, &name[2]);
+ /*
+ * Windows: name[0] is a '/' or '\'
+ * Get current drive
+ * Unix: does not apply
+ */
+ } else if (CHECK_ABS_PATH(name) && (drive=HDgetdrive())) {
+ sprintf(cwdpath, "%c:%c", (drive+'A'-1), name[0]);
+ retcwd = cwdpath;
+ HDstrcpy(new_name, &name[1]);
+ } else /* totally relative for both Unix and Windows: get current working directory */
+ retcwd = HDgetcwd(cwdpath, MAX_PATH_LEN);
+
+ if (retcwd != NULL) {
+ cwdlen = HDstrlen(cwdpath);
+ HDassert(cwdlen);
+ path_len = cwdlen + HDstrlen(new_name) + 2;
+ if ((full_path=H5MM_malloc(path_len)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ HDstrcpy(full_path, cwdpath);
+ if (!CHECK_DELIMITER(cwdpath[cwdlen-1]))
+ HDstrcat(full_path, DIR_SEPS);
+ HDstrcat(full_path, new_name);
+ }
+ }
+
+ /* strip out the last component (the file name itself) from the path */
+ if (full_path) {
+ GET_LAST_DELIMITER(full_path, ptr)
+ HDassert(ptr);
+ *++ptr = '\0';
+ *extpath = full_path;
+ }
+done:
+ if (cwdpath)
+ H5MM_xfree(cwdpath);
+ if (new_name)
+ H5MM_xfree(new_name);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5_build_extpath() */
diff --git a/test/Makefile.am b/test/Makefile.am
index 53df8bb..191e999 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -105,7 +105,8 @@ flush2.chkexe_: flush1.chkexe_
CHECK_CLEANFILES+=cmpd_dset.h5 compact_dataset.h5 dataset.h5 extend.h5 istore.h5\
tfile[1-4].h5 th5s[1-3].h5 lheap.h5 fheap.h5 ohdr.h5 stab.h5 \
extern_[1-3].h5 extern_[1-4][ab].raw gheap[0-4].h5 dt_arith[1-2]\
- links.h5 links[0-6]*.h5 big.data big[0-9][0-9][0-9][0-9][0-9].h5 \
+ links.h5 links[0-6]*.h5 extlinks[0-9].h5 tmp \
+ big.data big[0-9][0-9][0-9][0-9][0-9].h5 \
stdio.h5 sec2.h5 dtypes[1-8].h5 dt_arith[1-2].h5 tattr.h5 \
tselect.h5 mtime.h5 unlink.h5 unicode.h5 coord.h5 \
fillval_[0-9].h5 fillval.raw mount_[0-9].h5 testmeta.h5 ttime.h5 \
diff --git a/test/Makefile.in b/test/Makefile.in
index 7e47249..1297a44 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -595,8 +595,8 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog cmpd_dset.h5 \
compact_dataset.h5 dataset.h5 extend.h5 istore.h5 \
tfile[1-4].h5 th5s[1-3].h5 lheap.h5 fheap.h5 ohdr.h5 stab.h5 \
extern_[1-3].h5 extern_[1-4][ab].raw gheap[0-4].h5 \
- dt_arith[1-2] links.h5 links[0-6]*.h5 big.data \
- big[0-9][0-9][0-9][0-9][0-9].h5 stdio.h5 sec2.h5 \
+ dt_arith[1-2] links.h5 links[0-6]*.h5 extlinks[0-9].h5 tmp \
+ big.data big[0-9][0-9][0-9][0-9][0-9].h5 stdio.h5 sec2.h5 \
dtypes[1-8].h5 dt_arith[1-2].h5 tattr.h5 tselect.h5 mtime.h5 \
unlink.h5 unicode.h5 coord.h5 fillval_[0-9].h5 fillval.raw \
mount_[0-9].h5 testmeta.h5 ttime.h5 trefer[1-3].h5 tvltypes.h5 \
diff --git a/test/links.c b/test/links.c
index 1bff4c6..d517b4d 100644
--- a/test/links.c
+++ b/test/links.c
@@ -40,15 +40,38 @@ const char *FILENAME[] = {
"links1",
"links2",
"links3",
- "links4a",
- "links4b",
- "links4c",
- "links4d",
- "links5",
- "links6",
+ "links4a", /* 4 */
+ "links4b", /* 5 */
+ "links4c", /* 6 */
+ "links4d", /* 7 */
+ "links5", /* 8 */
+ "links6", /* 9 */
+ "links7", /* 10 */
+ "links8", /* 11 */
+ "extlinks0", /* 12: main files */
+ "tmp/extlinks0", /* 13: */
+ "extlinks1", /* 14: target files */
+ "tmp/extlinks1", /* 15: */
+ "extlinks2", /* 16: */
+ "tmp/extlinks2", /* 17: */
+ "extlinks3", /* 18: */
+ "tmp/extlinks3", /* 19: */
+ "extlinks4", /* 20: */
+ "tmp/extlinks4", /* 21: */
+ "extlinks5", /* 22: */
+ "tmp/extlinks6", /* 23: */
+ "extlinks7", /* 24: */
+ "tmp/extlinks7", /* 25: */
+ "tmp/extlinks8", /* 26: */
+ "extlinks9", /* 27: */
+ "tmp/extlinks9", /* 28: */
NULL
};
+#define TMPDIR "tmp"
+/* do not do check_all_closed() for "ext*" files and "tmp/ext*" */
+#define EXTSTOP 12
+
#define LINK_BUF_SIZE 1024
#define NAME_BUF_SIZE 1024
#define MAX_NAME_LEN ((64*1024)+1024)
@@ -2552,6 +2575,844 @@ external_link_dangling(hid_t fapl, hbool_t new_format)
return -1;
} /* end external_link_dangling() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: external_link_env: test 1
+ *
+ * Purpose: 1. Create target file in tmp directory ("tmp/extlinks1")
+ * 2. Create main file in current directory ("extlinks0")
+* 3. Create external link to target file ("extlinks1")
+ * 4. Set up environment variable "HDF5_EXT_PREFIX" to be ".:tmp"
+ * Should be able to access the target file in tmp directory through searching
+ * the pathnames set in HDF5_EXT_PREFIX
+ *
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * Feb. 20, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_link_env(hid_t fapl, hbool_t new_format)
+{
+ hid_t fid = (-1); /* File ID */
+ hid_t gid = (-1); /* Group IDs */
+ char *envval=NULL;
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE];
+
+ if(new_format)
+ TESTING("external links via environment variable (w/new group format)")
+ else
+ TESTING("external links via environment variable")
+
+
+ /* set up name for main file:"extlinks0" */
+ h5_fixname(FILENAME[12], fapl, filename1, sizeof filename1);
+ /* set up name for external linked target file: "extlinks1" */
+ h5_fixname(FILENAME[14], fapl, filename2, sizeof filename2);
+
+ if (HDmkdir(TMPDIR, (mode_t)0755) < 0 && errno != EEXIST)
+ TEST_ERROR
+
+ /* set up name for target file: "tmp/extlinks1" */
+ h5_fixname(FILENAME[15], fapl, filename3, sizeof filename3);
+
+ /* Create the target file */
+ if((fid=H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+ if((gid=H5Gcreate2(fid, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* closing for target file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+
+ /* Create the main file */
+ if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+
+ /* Create external link to target file */
+ if(H5Lcreate_external(filename2, "/A", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+ /* get original value for the HDF library environment variable for external link if set */
+ envval = HDgetenv("HDF5_EXT_PREFIX");
+ setenv("HDF5_EXT_PREFIX", ".:tmp", 1);
+
+ /* Open object through external link */
+ H5E_BEGIN_TRY {
+ gid = H5Gopen2(fid, "ext_link", H5P_DEFAULT);
+ } H5E_END_TRY;
+
+ /* restore value for the environment variable as needed */
+ if (envval)
+ HDsetenv("HDF5_EXT_PREFIX", envval, 1);
+ else
+ HDunsetenv("HDF5_EXT_PREFIX");
+
+ /* should be able to find the target file from pathnames set via environment variable */
+ if (gid < 0) {
+ H5_FAILED();
+ puts(" Should have found the file in tmp directory.");
+ goto error;
+ }
+
+ /* closing for main file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose (gid);
+ H5Fclose (fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end external_link_env() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: external_link_prefix: test 2
+ *
+ * Purpose: 1. Create the target file in tmp directory ("tmp/extlinks2")
+ * 2. Create the main file in current directory ("extlinks0")
+* 3. Create external link to target file ("extlinks2")
+ * 4. Set up external link prefix via H5Pset_elink_prefix() to be "tmp"
+ * Should be able to access the target file in tmp directory via the prefix set
+ * by H5Pset_elink_prefix()
+ *
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * Feb 19, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_link_prefix(hid_t fapl, hbool_t new_format)
+{
+ hid_t fid = (-1); /* File ID */
+ hid_t gid = (-1); /* Group IDs */
+ hid_t gapl_id = (-1);
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE];
+
+ if(new_format)
+ TESTING("external links via H5Pset_elink_prefix()(w/new group format)")
+ else
+ TESTING("external links via H5Pset_elink_prefix()")
+
+ /* set up name for main file: "extlinks0" */
+ h5_fixname(FILENAME[12], fapl, filename1, sizeof filename1);
+ /* set up name for external linked target file: "extlinks2" */
+ h5_fixname(FILENAME[16], fapl, filename2, sizeof filename2);
+
+ /* create tmp directory and get current working directory path */
+ if (HDmkdir(TMPDIR, (mode_t)0755) < 0 && errno != EEXIST)
+ TEST_ERROR
+
+ /* set up name for target file: "tmp/extlinks2" */
+ h5_fixname(FILENAME[17], fapl, filename3, sizeof filename3);
+
+ /* Create the target file */
+ if((fid=H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+ if((gid=H5Gcreate2(fid, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* closing for target file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+
+ /* Create the main file */
+ if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+
+ /* Create external link to target file (without the absolute path) */
+ if(H5Lcreate_external(filename2, "/A", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+ /* set up prefix for external link */
+ if((gapl_id = H5Pcreate(H5P_GROUP_ACCESS)) < 0) TEST_ERROR
+ if(H5Pset_elink_prefix(gapl_id, TMPDIR) < 0) TEST_ERROR
+
+ /* Open object through external link */
+ H5E_BEGIN_TRY {
+ gid = H5Gopen2(fid, "ext_link", gapl_id);
+ } H5E_END_TRY;
+
+ /* should be able to find the target file from pathnames set via H5Pset_elink_prefix() */
+ if (gid < 0) {
+ H5_FAILED();
+ puts(" Should have found the file in tmp directory.");
+ goto error;
+ }
+
+ /* closing for main file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose (gid);
+ H5Fclose (fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end external_link_prefix() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: external_link_abs_mainpath: test 3
+ *
+ * Purpose: 1. Create target file in tmp directory ("tmp/extlinks3")
+ * 2. Create main file (with absolute pathname) in tmp directory ("/CWD/tmp/extlinks0")
+ * 3. Create external link to target file without absolute path ("extlinks3")
+ * Should be able to access the target file via the main file's
+ * absolute pathname ("/CWD/tmp")
+ *
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * Feb 19, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_link_abs_mainpath(hid_t fapl, hbool_t new_format)
+{
+ hid_t fid = (-1); /* File ID */
+ hid_t gid = (-1); /* Group IDs */
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE],
+ tmpname[NAME_BUF_SIZE],
+ cwdpath[NAME_BUF_SIZE];
+
+ if(new_format)
+ TESTING("external links via main file's absolute path (w/new group format)")
+ else
+ TESTING("external links via main file's absolute path")
+
+ /* set up name for external linked target file: "extlinks3" */
+ h5_fixname(FILENAME[18], fapl, filename2, sizeof filename2);
+ /* set up name for target file: "tmp/extlinks3" */
+ h5_fixname(FILENAME[19], fapl, filename3, sizeof filename3);
+
+ /* create tmp directory and get current working directory path */
+ if ((HDmkdir(TMPDIR, (mode_t)0755) < 0 && errno != EEXIST) || (HDgetcwd(cwdpath, NAME_BUF_SIZE)==NULL))
+ TEST_ERROR
+
+ /* set up name for main file: "/CWD/tmp/extlinks0" */
+ HDstrcpy(tmpname, cwdpath);
+ HDstrcat(tmpname, "/");
+ HDstrcat(tmpname, FILENAME[13]);
+ h5_fixname(tmpname, fapl, filename1, sizeof filename1);
+
+ /* Create the target file */
+ if((fid=H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+ if((gid=H5Gcreate2(fid, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* closing for target file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+
+ /* Create the main file */
+ if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+
+ /* Create external link to target file */
+ if(H5Lcreate_external(filename2, "/A", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+ /* Open object through external link */
+ H5E_BEGIN_TRY {
+ gid = H5Gopen2(fid, "ext_link", H5P_DEFAULT);
+ } H5E_END_TRY;
+
+ /* should be able to find the target file from absolute path set for main file */
+ if (gid < 0) {
+ H5_FAILED();
+ puts(" Should have found the file in tmp directory.");
+ goto error;
+ }
+
+ /* closing for main file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose (gid);
+ H5Fclose (fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end external_link_abs_mainpath() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: external_link_rel_mainpath: test 4
+ *
+ * Purpose: 1. Create target file in tmp directory ("tmp/extlinks4")
+ * Purpose: 2. Create main file (with relative pathname) in tmp directory ("tmp/extlinks0")
+ * 3. Create external link to target file without the absolute pathname ("extlinks4")
+ * Should be able to access the target file via the main file's
+ * CWD+relative path ("/CWD/tmp")
+ *
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * Feb 19, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_link_rel_mainpath(hid_t fapl, hbool_t new_format)
+{
+ hid_t fid = (-1); /* File ID */
+ hid_t gid = (-1); /* Group IDs */
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE];
+
+ if(new_format)
+ TESTING("external links via main file's CWD + relative path(w/new group format)")
+ else
+ TESTING("external links via main file's CWD + relative path")
+
+ /* set up name for external linked target file: "extlinks4" */
+ h5_fixname(FILENAME[20], fapl, filename2, sizeof filename2);
+
+ if (HDmkdir(TMPDIR, (mode_t)0755) < 0 && errno != EEXIST)
+ TEST_ERROR
+
+ /* set up name for main file: "tmp/extlinks0" */
+ h5_fixname(FILENAME[13], fapl, filename1, sizeof filename1);
+ /* set up name for target file: "tmp/extlinks4" */
+ h5_fixname(FILENAME[21], fapl, filename3, sizeof filename3);
+
+ /* Create the target file */
+ if((fid=H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+ if((gid=H5Gcreate2(fid, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* closing for target file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+
+ /* Create the main file */
+ if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+
+ /* Create external link to target file */
+ if(H5Lcreate_external(filename2, "/A", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+ /* Open object through external link */
+ H5E_BEGIN_TRY {
+ gid = H5Gopen2(fid, "ext_link", H5P_DEFAULT);
+ } H5E_END_TRY;
+
+ /* should be able to find the target file from the main file's relative pathname */
+ if (gid < 0) {
+ H5_FAILED();
+ puts(" Should have found the file in current working directory");
+ goto error;
+ }
+
+ /* closing for main file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose (gid);
+ H5Fclose (fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end external_link_rel_mainpath() */
+
+/*-------------------------------------------------------------------------
+ * Function: external_link_cwd: test 5
+ *
+ * Purpose: 1. Create main file (with absolute path) in tmp directory ("/CWD/tmp/extlinks0")
+ * 2. Create target file in current working directory ("extlinks5")
+ * 3. Create external link to target file (without the absolute path) ("extlinks5")
+ * Should be able to access the target file in the current working directory
+ *
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * Feb 19, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_link_cwd(hid_t fapl, hbool_t new_format)
+{
+ hid_t fid = (-1); /* File ID */
+ hid_t gid = (-1); /* Group IDs */
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ tmpname[NAME_BUF_SIZE],
+ cwdpath[NAME_BUF_SIZE];
+
+
+ if(new_format)
+ TESTING("external links via current working directory(w/new group format)")
+ else
+ TESTING("external links via current working directory")
+
+ /* set up name for external linked target file: "extlinks5" */
+ /* set up name for target file: "extlinks5" */
+ h5_fixname(FILENAME[22], fapl, filename2, sizeof filename2);
+
+ if ((HDmkdir(TMPDIR, (mode_t)0755) < 0 && errno != EEXIST) || (HDgetcwd(cwdpath, NAME_BUF_SIZE)==NULL))
+ TEST_ERROR
+
+ /* set up name for main file: "/CWD/tmp/extlinks0" */
+ HDstrcpy(tmpname, cwdpath);
+ HDstrcat(tmpname, "/");
+ HDstrcat(tmpname, FILENAME[13]);
+ h5_fixname(tmpname, fapl, filename1, sizeof filename1);
+
+ /* Create the target file */
+ if((fid=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+ if((gid=H5Gcreate2(fid, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* closing for target file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+
+ /* Create the main file */
+ if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+
+ /* Create external link to target file */
+ if(H5Lcreate_external(filename2, "/A", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+ /* Open object through external link */
+ H5E_BEGIN_TRY {
+ gid = H5Gopen2(fid, "ext_link", H5P_DEFAULT);
+ } H5E_END_TRY;
+
+ /* should be able to find the target file from the current working directory */
+ if (gid < 0) {
+ H5_FAILED();
+ puts(" Should have found the file in current working directory");
+ goto error;
+ }
+
+ /* closing for main file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose (gid);
+ H5Fclose (fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end external_link_cwd() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: external_link_abstar: test 6
+ *
+ * Purpose: 1. Create target file in tmp directory (with absolute path) ("tmp/extlinks6")
+ * 2. Create main file in current directory ("extlinks0")
+ * 3. Create external link to target file (with absolute path) ("/CWD/tmp/extlinks6")
+ * Should be able to access the target file (with absolute path) directly
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * Feb. 20, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_link_abstar(hid_t fapl, hbool_t new_format)
+{
+ hid_t fid = (-1); /* File ID */
+ hid_t gid = (-1); /* Group IDs */
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE],
+ tmpname[NAME_BUF_SIZE],
+ cwdpath[NAME_BUF_SIZE];
+
+ if(new_format)
+ TESTING("external links via target's absolute path (w/new group format)")
+ else
+ TESTING("external links via target's absolute path")
+
+ /* set up name for main file: "extlinks0" */
+ h5_fixname(FILENAME[12], fapl, filename1, sizeof filename1);
+
+ /* create tmp directory and get current working directory path */
+ if ((HDmkdir(TMPDIR, (mode_t)0755) < 0 && errno != EEXIST) || (HDgetcwd(cwdpath, NAME_BUF_SIZE)==NULL))
+ TEST_ERROR
+
+ /* set up name for external linked target file: "/CWD/tmp/extlinks6" */
+ HDstrcpy(tmpname, cwdpath);
+ HDstrcat(tmpname, "/");
+ HDstrcat(tmpname, FILENAME[23]);
+ h5_fixname(tmpname, fapl, filename2, sizeof filename2);
+
+ /* set up name for target file: "tmp/extlinks6" */
+ h5_fixname(FILENAME[23], fapl, filename3, sizeof filename3);
+
+ /* Create the target file */
+ if((fid=H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+ if((gid=H5Gcreate2(fid, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* closing for target file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+
+ /* Create the main file */
+ if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+
+ /* Create external link to target file */
+ if(H5Lcreate_external(filename2, "/A", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+ /* Open object through external link */
+ H5E_BEGIN_TRY {
+ gid = H5Gopen2(fid, "ext_link", H5P_DEFAULT);
+ } H5E_END_TRY;
+
+ /* should be able to find the target file with abolute path */
+ if (gid < 0) {
+ H5_FAILED();
+ puts(" Should have found the file in tmp directory.");
+ goto error;
+ }
+
+ /* closing for main file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose (gid);
+ H5Fclose (fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end external_link_abstar() */
+
+/*-------------------------------------------------------------------------
+ * Function: external_link_abstar_cur: test 7
+ *
+ * Purpose: 1. Create target file in current working directory "extlinks7"
+ * 2. Create main file in current working directory "extlinks0"
+ * 3. Create external link to target file (with absolute path
+ * that does not exist in that directory) ("/CWD/tmp/extlinks7")
+ * Should be able to access the target file via the main file's CWD.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * Feb. 20, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_link_abstar_cur(hid_t fapl, hbool_t new_format)
+{
+ hid_t fid = (-1); /* File ID */
+ hid_t gid = (-1); /* Group IDs */
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE],
+ tmpname[NAME_BUF_SIZE],
+ cwdpath[NAME_BUF_SIZE];
+
+ if(new_format)
+ TESTING("external links via main file's CWD (w/new group format)")
+ else
+ TESTING("external links via main file's CWD")
+
+ /* set up name for main file: "extlinks0" */
+ h5_fixname(FILENAME[12], fapl, filename1, sizeof filename1);
+
+ /* set up name for target file name: "extlinks7" */
+ h5_fixname(FILENAME[24], fapl, filename3, sizeof filename3);
+
+ /* create tmp directory and get current working directory path */
+ if ((HDmkdir(TMPDIR, (mode_t)0755) < 0 && errno != EEXIST) || (HDgetcwd(cwdpath, NAME_BUF_SIZE)==NULL))
+ TEST_ERROR
+
+ /* set up name for external linked target file: "/CWD/tmp/extlinks7" */
+ HDstrcpy(tmpname, cwdpath);
+ HDstrcat(tmpname, "/");
+ HDstrcat(tmpname, FILENAME[25]);
+ h5_fixname(tmpname, fapl, filename2, sizeof filename2);
+
+ /* Create the target file */
+ if((fid=H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+ if((gid=H5Gcreate2(fid, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* closing for target file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+
+ /* Create the main file */
+ if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+
+ /* Create external link to target file */
+ if(H5Lcreate_external(filename2, "/A", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+ /* Open object through external link */
+ H5E_BEGIN_TRY {
+ gid = H5Gopen2(fid, "ext_link", H5P_DEFAULT);
+ } H5E_END_TRY;
+
+ /* should be able to find the target file from main file's current working directory */
+ if (gid < 0) {
+ H5_FAILED();
+ puts(" Should have found the file in current working directory.");
+ goto error;
+ }
+
+ /* closing for main file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose (gid);
+ H5Fclose (fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end external_link_abstar_cur() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: external_link_reltar: test 8
+ *
+ * Purpose: 1. Create target file in tmp directory ("tmp/extlinks8")
+ * 2. Create main file in current working directory ("extlinks0")
+ * 3. Create external link to target file with relative path ("tmp/extlinks8")
+ * Should be able to access the target file via the main file's
+ * relative pathname (CWD + relative path of targetfile: "/CWD/tmp/extlinks8")
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * Feb. 20, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_link_reltar(hid_t fapl, hbool_t new_format)
+{
+ hid_t fid = (-1); /* File ID */
+ hid_t gid = (-1); /* Group IDs */
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE];
+
+ if(new_format)
+ TESTING("external links via main file's CWD + target's relative path(w/new group format)")
+ else
+ TESTING("external links via main file's CWD + target's relative path")
+
+ /* set up name for main file: "extlinks0" */
+ h5_fixname(FILENAME[12], fapl, filename1, sizeof filename1);
+
+ /* create tmp directory */
+ if (HDmkdir(TMPDIR, (mode_t)0755) < 0 && errno != EEXIST)
+ TEST_ERROR
+
+ /* set up name for target file name: "tmp/extlinks8" */
+ /* set up name for external linked target file: "tmp/extlinks8" */
+ h5_fixname(FILENAME[26], fapl, filename2, sizeof filename2);
+
+ /* Create the target file */
+ if((fid=H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+ if((gid=H5Gcreate2(fid, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* closing for target file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+
+ /* Create the main file */
+ if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+
+ /* Create external link to target file */
+ if(H5Lcreate_external(filename2, "/A", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+ /* Open object through external link */
+ H5E_BEGIN_TRY {
+ gid = H5Gopen2(fid, "ext_link", H5P_DEFAULT);
+ } H5E_END_TRY;
+
+ /*
+ * Should be able to find the target file from:
+ * main file's current working directory + pathname of external linked targetfile
+ */
+ if (gid < 0) {
+ H5_FAILED();
+ puts(" Should have found the file in tmp directory.");
+ goto error;
+ }
+
+ /* closing for main file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose (gid);
+ H5Fclose (fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end external_link_reltar() */
+
+/*-------------------------------------------------------------------------
+ * Function: external_link_chdir: test 9
+ *
+ * Purpose: 1. Create target file in tmp directory ("tmp/extlinks9")
+ * 2. Create main file in current working directory ("extlinks0")
+ * 3. chdir "tmp"
+ * 3. Create external link to target file ("extlinks9")
+ * Should be able to access the target file in current working directory
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * Feb. 20, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_link_chdir(hid_t fapl, hbool_t new_format)
+{
+ hid_t fid = (-1); /* File ID */
+ hid_t gid = (-1); /* Group IDs */
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE];
+
+ if(new_format)
+ TESTING("external links via chdir and found in current working directory (w/new group format)")
+ else
+ TESTING("external links via chdir and found in current working directory")
+
+ /* set up name for main file: "extlinks0" */
+ h5_fixname(FILENAME[12], fapl, filename1, sizeof filename1);
+ /* set up name for external linked target file ("extlinks9") */
+ h5_fixname(FILENAME[27], fapl, filename2, sizeof filename2);
+
+ /* create tmp directory */
+ if (HDmkdir(TMPDIR, (mode_t)0755) < 0 && errno != EEXIST)
+ TEST_ERROR
+
+ /* set up name for target file name ("tmp/extlinks9") */
+ h5_fixname(FILENAME[28], fapl, filename3, sizeof filename3);
+
+ /* Create the target file */
+ if((fid=H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+ if((gid=H5Gcreate2(fid, "A", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* closing for target file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+
+ /* Create the main file */
+ if((fid=H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+
+ /* Create external link to target file */
+ if(H5Lcreate_external(filename2, "/A", fid, "ext_link", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+
+ if (HDchdir(TMPDIR) < 0) TEST_ERROR
+
+ /* Open object through external link */
+ H5E_BEGIN_TRY {
+ gid = H5Gopen2(fid, "ext_link", H5P_DEFAULT);
+ } H5E_END_TRY;
+
+ if (HDchdir("..") < 0) TEST_ERROR
+
+ /*
+ * Should be able to find the target file from:
+ * main file's current working directory + pathname of external linked targetfile
+ */
+ if (gid < 0) {
+ H5_FAILED();
+ puts(" Should have found the file in tmp directory.");
+ goto error;
+ }
+
+ /* closing for main file */
+ if(H5Gclose(gid) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Gclose (gid);
+ H5Fclose (fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end external_link_chdir() */
/*-------------------------------------------------------------------------
* Function: external_link_recursive
@@ -5284,7 +6145,7 @@ linkinfo(hid_t fapl, hbool_t new_format)
*-------------------------------------------------------------------------
*/
static int
-check_all_closed(hid_t fapl, hbool_t new_format)
+check_all_closed(hid_t fapl, hbool_t new_format, int stopat)
{
hid_t fid=-1;
char filename[NAME_BUF_SIZE];
@@ -5300,7 +6161,7 @@ check_all_closed(hid_t fapl, hbool_t new_format)
* To check this, try to create every file used in this test. If
* a file is already open, creating it will fail.
*/
- for(x=0; FILENAME[x] != NULL; x++)
+ for(x=0; FILENAME[x] != NULL && x < stopat; x++)
{
h5_fixname(FILENAME[x], fapl, filename, sizeof filename);
@@ -10225,6 +11086,8 @@ main(void)
my_fapl = fapl;
/* General tests... (on both old & new format groups */
+
+
nerrors += mklinks(my_fapl, new_format) < 0 ? 1 : 0;
nerrors += cklinks(my_fapl, new_format) < 0 ? 1 : 0;
nerrors += new_links(my_fapl, new_format) < 0 ? 1 : 0;
@@ -10263,6 +11126,17 @@ main(void)
nerrors += external_link_endian(my_fapl, new_format) < 0 ? 1 : 0;
nerrors += external_link_strong(my_fapl, new_format) < 0 ? 1 : 0;
+ /* tests for external link */
+ nerrors += external_link_env(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_prefix(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_abs_mainpath(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_rel_mainpath(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_cwd(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_abstar(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_abstar_cur(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_reltar(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_chdir(my_fapl, new_format) < 0 ? 1 : 0;
+
/* These tests assume that external links are a form of UD links,
* so assume that everything that passed for external links
* above has already been tested for UD links.
@@ -10284,7 +11158,8 @@ main(void)
nerrors += obj_visit_by_name(my_fapl, new_format) < 0 ? 1 : 0;
/* Keep this test last, it's testing files that are used above */
- nerrors += check_all_closed(my_fapl, new_format) < 0 ? 1 : 0;
+ /* do not do this for files used by external link tests */
+ nerrors += check_all_closed(my_fapl, new_format, EXTSTOP) < 0 ? 1 : 0;
} /* end for */
/* New group revision feature tests */
@@ -10324,6 +11199,8 @@ main(void)
}
printf("All link tests passed.\n");
h5_cleanup(FILENAME, fapl);
+ /* clean up tmp directory created by external link tests */
+ HDrmdir(TMPDIR);
}
else
puts("All link tests skipped - Incompatible with current Virtual File Driver");