From 04c174bde0e54b4432c0502f63b279731dda2559 Mon Sep 17 00:00:00 2001 From: Vailin Choi Date: Wed, 2 Apr 2008 13:29:17 -0500 Subject: [svn-r14789] Add handling for external link: 1. src/H5F.c, src/H5system.c: formulate path for mainfile 2. src/H5Lexternal.c: add search for target file 3. configure.in: add H5_HAVE_WINDOW_PATH 4. test/links.c: add tests for external link --- configure.in | 18 ++ src/H5F.c | 41 ++- src/H5Fpkg.h | 1 + src/H5Fprivate.h | 3 + src/H5Lexternal.c | 200 ++++++++++-- src/H5config.h.in | 3 + src/H5private.h | 47 +++ src/H5system.c | 96 ++++++ test/Makefile.am | 3 +- test/Makefile.in | 4 +- test/links.c | 895 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 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 ":" */ + 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 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 ":\" or ":/" + */ + 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 ":" + * 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"); -- cgit v0.12