Hello,

currently relative file names set with H5Pset_external() will be interpreted as relative to the current directory.

The attached patch (against SVN trunk r24959) changes this to relative to the HDF5 file, which is probably what most users want when they use H5Pset_external().


Best regards,
Steffen Kieß
Index: src/H5Defl.c
===================================================================
--- src/H5Defl.c	(revision 24959)
+++ src/H5Defl.c	(working copy)
@@ -33,6 +33,7 @@
 #include "H5Eprivate.h"		/* Error handling		  	*/
 #include "H5Fprivate.h"		/* Files				*/
 #include "H5HLprivate.h"	/* Local Heaps				*/
+#include "H5MMprivate.h"	/* Memory management			*/
 #include "H5VMprivate.h"		/* Vector and array functions		*/
 
 
@@ -48,12 +49,14 @@
 /* Callback info for readvv operation */
 typedef struct H5D_efl_readvv_ud_t {
     const H5O_efl_t *efl;       /* Pointer to efl info */
+    H5F_t *file;                /* File the data set is in */
     unsigned char *rbuf;        /* Read buffer */
 } H5D_efl_readvv_ud_t;
 
 /* Callback info for writevv operation */
 typedef struct H5D_efl_writevv_ud_t {
     const H5O_efl_t *efl;       /* Pointer to efl info */
+    H5F_t *file;                /* File the data set is in */
     const unsigned char *wbuf;  /* Write buffer */
 } H5D_efl_writevv_ud_t;
 
@@ -75,9 +78,9 @@
     size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
 
 /* Helper routines */
-static herr_t H5D__efl_read(const H5O_efl_t *efl, haddr_t addr, size_t size,
+static herr_t H5D__efl_read(const H5O_efl_t *efl, H5F_t *file, haddr_t addr, size_t size,
     uint8_t *buf);
-static herr_t H5D__efl_write(const H5O_efl_t *efl, haddr_t addr, size_t size,
+static herr_t H5D__efl_write(const H5O_efl_t *efl, H5F_t *file, haddr_t addr, size_t size,
     const uint8_t *buf);
 
 
@@ -110,6 +113,48 @@
 
 
 
+/*--------------------------------------------------------------------------
+ * Function: H5D_build_name
+ *
+ * Purpose:  Prepend extpath to external file name (for relative files) and store in FULL_NAME
+ *
+ * Return:   Non-negative on success/Negative on failure
+--------------------------------------------------------------------------*/
+static herr_t
+H5D_build_name(const H5F_t *file, const char* filename, char **full_name/*out*/)
+{
+    char        *extpath;               /* absolute path of directory the HDF5 file is in */
+    size_t      extpath_len;            /* length of extpath */
+    size_t      filename_len;           /* length of external file name */
+    herr_t      ret_value = SUCCEED;    /* Return value */
+
+    FUNC_ENTER_NOAPI_NOINIT
+
+    HDassert(file);
+    extpath = H5F_EXTPATH(file);
+    HDassert(extpath);
+    extpath_len = HDstrlen(extpath);
+    filename_len = HDstrlen(filename);
+
+    if (H5_CHECK_ABSOLUTE(filename)) {
+      /* If the filename is absolute, simply use filename */
+      if(NULL == (*full_name = (char *)H5MM_strdup(filename)))
+        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+    } else {
+      /* Allocate a buffer to hold the filename + extpath + possibly the delimiter + terminating null byte */
+      if(NULL == (*full_name = (char *)H5MM_malloc(extpath_len + filename_len + 2)))
+        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer")
+
+      /* Compose the full file name */
+      HDsnprintf(*full_name, (extpath_len + filename_len + 2), "%s%s%s", extpath,
+          (H5_CHECK_DELIMITER(extpath[extpath_len - 1]) ? "" : H5_DIR_SEPS), filename);
+    }
+
+done:
+    FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_build_name() */
+
+
 /*-------------------------------------------------------------------------
  * Function:	H5D__efl_construct
  *
@@ -254,7 +299,7 @@
  *-------------------------------------------------------------------------
  */
 static herr_t
-H5D__efl_read(const H5O_efl_t *efl, haddr_t addr, size_t size, uint8_t *buf)
+H5D__efl_read(const H5O_efl_t *efl, H5F_t *file, haddr_t addr, size_t size, uint8_t *buf)
 {
     int		fd = -1;
     size_t	to_read;
@@ -266,6 +311,7 @@
     ssize_t	n;
     size_t      u;                      /* Local index variable */
     herr_t      ret_value = SUCCEED;    /* Return value */
+    char *full_name = NULL;             /* File name with prefix */
 
     FUNC_ENTER_STATIC
 
@@ -291,7 +337,9 @@
 	    HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "read past logical end of file")
 	if(H5F_OVERFLOW_HSIZET2OFFT(efl->slot[u].offset + skip))
 	    HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "external file address overflowed")
-	if((fd = HDopen(efl->slot[u].name, O_RDONLY, 0)) < 0)
+        if(H5D_build_name(file, efl->slot[u].name, &full_name/*out*/) < 0)
+          HGOTO_ERROR(H5E_EFL, H5E_CANTGET, FAIL, "can't build external file name")
+	if((fd = HDopen(full_name, O_RDONLY, 0)) < 0)
 	    HGOTO_ERROR(H5E_EFL, H5E_CANTOPENFILE, FAIL, "unable to open external raw data file")
 	if(HDlseek(fd, (off_t)(efl->slot[u].offset + skip), SEEK_SET) < 0)
 	    HGOTO_ERROR(H5E_EFL, H5E_SEEKERROR, FAIL, "unable to seek in external raw data file")
@@ -315,6 +363,7 @@
     } /* end while */
 
 done:
+    full_name = (char *)H5MM_xfree(full_name);
     if(fd >= 0)
         HDclose(fd);
 
@@ -341,7 +390,7 @@
  *-------------------------------------------------------------------------
  */
 static herr_t
-H5D__efl_write(const H5O_efl_t *efl, haddr_t addr, size_t size, const uint8_t *buf)
+H5D__efl_write(const H5O_efl_t *efl, H5F_t *file, haddr_t addr, size_t size, const uint8_t *buf)
 {
     int		fd = -1;
     size_t	to_write;
@@ -352,6 +401,7 @@
     hsize_t     skip = 0;
     size_t	u;                      /* Local index variable */
     herr_t      ret_value = SUCCEED;    /* Return value */
+    char *full_name = NULL;             /* File name with prefix */
 
     FUNC_ENTER_STATIC
 
@@ -377,8 +427,10 @@
 	    HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "write past logical end of file")
 	if(H5F_OVERFLOW_HSIZET2OFFT(efl->slot[u].offset + skip))
 	    HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "external file address overflowed")
-	if((fd = HDopen(efl->slot[u].name, O_CREAT | O_RDWR, 0666)) < 0) {
-	    if(HDaccess(efl->slot[u].name, F_OK) < 0)
+        if(H5D_build_name(file, efl->slot[u].name, &full_name/*out*/) < 0)
+          HGOTO_ERROR(H5E_EFL, H5E_CANTGET, FAIL, "can't build external file name")
+	if((fd = HDopen(full_name, O_CREAT | O_RDWR, 0666)) < 0) {
+	    if(HDaccess(full_name, F_OK) < 0)
 		HGOTO_ERROR(H5E_EFL, H5E_CANTOPENFILE, FAIL, "external raw data file does not exist")
 	    else
 		HGOTO_ERROR(H5E_EFL, H5E_CANTOPENFILE, FAIL, "unable to open external raw data file")
@@ -403,6 +455,7 @@
     } /* end while */
 
 done:
+    full_name = (char *)H5MM_xfree(full_name);
     if(fd >= 0)
         HDclose(fd);
 
@@ -431,7 +484,7 @@
     FUNC_ENTER_STATIC
 
     /* Read data */
-    if(H5D__efl_read(udata->efl, dst_off, len, (udata->rbuf + src_off)) < 0)
+    if(H5D__efl_read(udata->efl, udata->file, dst_off, len, (udata->rbuf + src_off)) < 0)
         HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "EFL read failed")
 
 done:
@@ -468,6 +521,8 @@
     HDassert(io_info);
     HDassert(io_info->store->efl.nused > 0);
     HDassert(io_info->u.rbuf);
+    HDassert(io_info->dset);
+    HDassert(io_info->dset->oloc.file);
     HDassert(dset_curr_seq);
     HDassert(dset_len_arr);
     HDassert(dset_off_arr);
@@ -477,6 +532,7 @@
 
     /* Set up user data for H5VM_opvv() */
     udata.efl = &(io_info->store->efl);
+    udata.file = io_info->dset->oloc.file;
     udata.rbuf = (unsigned char *)io_info->u.rbuf;
 
     /* Call generic sequence operation routine */
@@ -511,7 +567,7 @@
     FUNC_ENTER_STATIC
 
     /* Write data */
-    if(H5D__efl_write(udata->efl, dst_off, len, (udata->wbuf + src_off)) < 0)
+    if(H5D__efl_write(udata->efl, udata->file, dst_off, len, (udata->wbuf + src_off)) < 0)
         HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "EFL write failed")
 
 done:
@@ -548,6 +604,8 @@
     HDassert(io_info);
     HDassert(io_info->store->efl.nused > 0);
     HDassert(io_info->u.wbuf);
+    HDassert(io_info->dset);
+    HDassert(io_info->dset->oloc.file);
     HDassert(dset_curr_seq);
     HDassert(dset_len_arr);
     HDassert(dset_off_arr);
@@ -557,6 +615,7 @@
 
     /* Set up user data for H5VM_opvv() */
     udata.efl = &(io_info->store->efl);
+    udata.file = io_info->dset->oloc.file;
     udata.wbuf = (const unsigned char *)io_info->u.wbuf;
 
     /* Call generic sequence operation routine */
_______________________________________________
Hdf-forum is for HDF software users discussion.
[email protected]
http://mail.lists.hdfgroup.org/mailman/listinfo/hdf-forum_lists.hdfgroup.org

Reply via email to