summaryrefslogtreecommitdiffstats
path: root/src/H5FDsec2.c
diff options
context:
space:
mode:
authorDana Robinson <derobins@hdfgroup.org>2011-10-12 21:25:51 (GMT)
committerDana Robinson <derobins@hdfgroup.org>2011-10-12 21:25:51 (GMT)
commitb80f663629f73a8cd3fc46fd58b06c8bf4c528d7 (patch)
tree5166d84e980d08195adb525dd5b96bc3e67adc4e /src/H5FDsec2.c
parent3aa1b1d93cad549d092eba87826d207a5f04051b (diff)
downloadhdf5-b80f663629f73a8cd3fc46fd58b06c8bf4c528d7.zip
hdf5-b80f663629f73a8cd3fc46fd58b06c8bf4c528d7.tar.gz
hdf5-b80f663629f73a8cd3fc46fd58b06c8bf4c528d7.tar.bz2
[svn-r21531] Merge of 21501 and 21502 from trunk:
Note that this differs slightly from the trunk code since the VFL API won't be changed until 1.10. In the 1.8 branch, the term() function is public and this required some #defines for the Windows VFD. 21501: - Propagated Windows VFD tweaks to SEC2 and log VFDs. - Created typedefs and #defines to make POSIX I/O type-safe on Windows and true POSIX platforms. - Added pre-checks and removed post-checks for POSIX I/O sizes. When the number of bytes to be sent exceeds the maximum return value, the operation is split into smaller subsets. - General code tidying and cleanup. 21502: - Removed Windows VFD code. H5Pset_fapl_windows() actually sets the SEC2 driver, though it will still report H5FD_WINDOWS.
Diffstat (limited to 'src/H5FDsec2.c')
-rw-r--r--src/H5FDsec2.c605
1 files changed, 331 insertions, 274 deletions
diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c
index 14598d2..a7ae93e 100644
--- a/src/H5FDsec2.c
+++ b/src/H5FDsec2.c
@@ -17,36 +17,50 @@
* Programmer: Robb Matzke <matzke@llnl.gov>
* Thursday, July 29, 1999
*
- * Purpose: The POSIX unbuffered file driver using only the HDF5 public
- * API and with a few optimizations: the lseek() call is made
- * only when the current file position is unknown or needs to be
- * changed based on previous I/O through this driver (don't mix
- * I/O from this driver with I/O from other parts of the
- * application to the same file).
+ * Purpose: The POSIX unbuffered file driver using only the HDF5 public
+ * API and with a few optimizations: the lseek() call is made
+ * only when the current file position is unknown or needs to be
+ * changed based on previous I/O through this driver (don't mix
+ * I/O from this driver with I/O from other parts of the
+ * application to the same file).
*/
/* Interface initialization */
-#define H5_INTERFACE_INIT_FUNC H5FD_sec2_init_interface
+#define H5_INTERFACE_INIT_FUNC H5FD_sec2_init_interface
-#include "H5private.h" /* Generic Functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* File access */
-#include "H5FDprivate.h" /* File drivers */
-#include "H5FDsec2.h" /* Sec2 file driver */
-#include "H5FLprivate.h" /* Free Lists */
-#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5Pprivate.h" /* Property lists */
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* File access */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5FDsec2.h" /* Sec2 file driver */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Pprivate.h" /* Property lists */
/* The driver identification number, initialized at runtime */
static hid_t H5FD_SEC2_g = 0;
-/*
- * The description of a file belonging to this driver. The `eoa' and `eof'
+/* Since Windows doesn't follow the rest of the world when it comes
+ * to POSIX I/O types, some typedefs and constants are needed to avoid
+ * making the code messy with #ifdefs.
+ */
+#ifdef H5_HAVE_WIN32_API
+typedef unsigned int h5_sec2_io_t;
+typedef int h5_sec2_io_ret_t;
+static int H5_SEC2_MAX_IO_BYTES_g = INT_MAX;
+#else
+/* Unix, everyone else */
+typedef size_t h5_sec2_io_t;
+typedef ssize_t h5_sec2_io_ret_t;
+static size_t H5_SEC2_MAX_IO_BYTES_g = SSIZET_MAX;
+#endif /* H5_HAVE_WIN32_API */
+
+/* The description of a file belonging to this driver. The `eoa' and `eof'
* determine the amount of hdf5 address space in use and the high-water mark
- * of the file (the current size of the underlying Unix file). The `pos'
- * value is used to eliminate file position updates when they would be a
+ * of the file (the current size of the underlying filesystem file). The
+ * `pos' value is used to eliminate file position updates when they would be a
* no-op. Unfortunately we've found systems that use separate file position
* indicators for reading and writing so the lseek can only be eliminated if
* the current operation is the same as the previous operation. When opening
@@ -55,80 +69,82 @@ static hid_t H5FD_SEC2_g = 0;
* occurs), and `op' will be set to H5F_OP_UNKNOWN.
*/
typedef struct H5FD_sec2_t {
- H5FD_t pub; /*public stuff, must be first */
- int fd; /*the unix file */
- haddr_t eoa; /*end of allocated region */
- haddr_t eof; /*end of file; current file size*/
- haddr_t pos; /*current file I/O position */
- H5FD_file_op_t op; /*last operation */
- char filename[H5FD_MAX_FILENAME_LEN]; /* Copy of file name from open operation */
+ H5FD_t pub; /* public stuff, must be first */
+ int fd; /* the filesystem file descriptor */
+ haddr_t eoa; /* end of allocated region */
+ haddr_t eof; /* end of file; current file size */
+ haddr_t pos; /* current file I/O position */
+ H5FD_file_op_t op; /* last operation */
+ char filename[H5FD_MAX_FILENAME_LEN]; /* Copy of file name from open operation */
#ifndef H5_HAVE_WIN32_API
- /*
- * On most systems the combination of device and i-node number uniquely
- * identify a file.
+ /* On most systems the combination of device and i-node number uniquely
+ * identify a file. Note that Cygwin, MinGW and other Windows POSIX
+ * environments have the stat function (which fakes inodes)
+ * and will use the 'device + inodes' scheme as opposed to the
+ * Windows code further below.
*/
- dev_t device; /*file device number */
+ dev_t device; /* file device number */
#ifdef H5_VMS
- ino_t inode[3]; /*file i-node number */
+ ino_t inode[3]; /* file i-node number */
#else
- ino_t inode; /*file i-node number */
-#endif /*H5_VMS*/
+ ino_t inode; /* file i-node number */
+#endif /* H5_VMS */
#else
- /*
- * On H5_HAVE_WIN32_API the low-order word of a unique identifier associated with the
- * file and the volume serial number uniquely identify a file. This number
- * (which, both? -rpm) may change when the system is restarted or when the
- * file is opened. After a process opens a file, the identifier is
- * constant until the file is closed. An application can use this
- * identifier and the volume serial number to determine whether two
- * handles refer to the same file.
+ /* Files in windows are uniquely identified by the volume serial
+ * number and the file index (both low and high parts).
+ *
+ * There are caveats where these numbers can change, especially
+ * on FAT file systems. On NTFS, however, a file should keep
+ * those numbers the same until renamed or deleted (though you
+ * can use ReplaceFile() on NTFS to keep the numbers the same
+ * while renaming).
+ *
+ * See the MSDN "BY_HANDLE_FILE_INFORMATION Structure" entry for
+ * more information.
+ *
+ * http://msdn.microsoft.com/en-us/library/aa363788(v=VS.85).aspx
*/
- DWORD fileindexlo;
- DWORD fileindexhi;
-#endif
-
- /* Information from properties set by 'h5repart' tool */
- hbool_t fam_to_sec2; /* Whether to eliminate the family driver info
- * and convert this file to a single file */
+ DWORD nFileIndexLow;
+ DWORD nFileIndexHigh;
+ DWORD dwVolumeSerialNumber;
+
+ HANDLE hFile; /* Native windows file handle */
+#endif /* H5_HAVE_WIN32_API */
+
+ /* Information from properties set by 'h5repart' tool
+ *
+ * Whether to eliminate the family driver info and convert this file to
+ * a single file.
+ */
+ hbool_t fam_to_sec2;
} H5FD_sec2_t;
-
-/*
- * This driver supports systems that have the lseek64() function by defining
- * some macros here so we don't have to have conditional compilations later
- * throughout the code.
- *
- * HDoff_t: The datatype for file offsets, the second argument of
- * the lseek() or lseek64() call.
- *
- */
-
/*
* These macros check for overflow of various quantities. These macros
* assume that HDoff_t is signed and haddr_t and size_t are unsigned.
*
- * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t'
- * is too large to be represented by the second argument
- * of the file seek function.
+ * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t'
+ * is too large to be represented by the second argument
+ * of the file seek function.
*
- * SIZE_OVERFLOW: Checks whether a buffer size of type `hsize_t' is too
- * large to be represented by the `size_t' type.
+ * SIZE_OVERFLOW: Checks whether a buffer size of type `hsize_t' is too
+ * large to be represented by the `size_t' type.
*
- * REGION_OVERFLOW: Checks whether an address and size pair describe data
- * which can be addressed entirely by the second
- * argument of the file seek function.
+ * REGION_OVERFLOW: Checks whether an address and size pair describe data
+ * which can be addressed entirely by the second
+ * argument of the file seek function.
*/
#define MAXADDR (((haddr_t)1<<(8*sizeof(HDoff_t)-1))-1)
-#define ADDR_OVERFLOW(A) (HADDR_UNDEF==(A) || \
- ((A) & ~(haddr_t)MAXADDR))
-#define SIZE_OVERFLOW(Z) ((Z) & ~(hsize_t)MAXADDR)
-#define REGION_OVERFLOW(A,Z) (ADDR_OVERFLOW(A) || SIZE_OVERFLOW(Z) || \
- HADDR_UNDEF==(A)+(Z) || \
- (HDoff_t)((A)+(Z))<(HDoff_t)(A))
+#define ADDR_OVERFLOW(A) (HADDR_UNDEF==(A) || \
+ ((A) & ~(haddr_t)MAXADDR))
+#define SIZE_OVERFLOW(Z) ((Z) & ~(hsize_t)MAXADDR)
+#define REGION_OVERFLOW(A,Z) (ADDR_OVERFLOW(A) || SIZE_OVERFLOW(Z) || \
+ HADDR_UNDEF==(A)+(Z) || \
+ (HDoff_t)((A)+(Z))<(HDoff_t)(A))
/* Prototypes */
static H5FD_t *H5FD_sec2_open(const char *name, unsigned flags, hid_t fapl_id,
- haddr_t maxaddr);
+ haddr_t maxaddr);
static herr_t H5FD_sec2_close(H5FD_t *_file);
static int H5FD_sec2_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
static herr_t H5FD_sec2_query(const H5FD_t *_f1, unsigned long *flags);
@@ -137,43 +153,43 @@ static herr_t H5FD_sec2_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
static haddr_t H5FD_sec2_get_eof(const H5FD_t *_file);
static herr_t H5FD_sec2_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle);
static herr_t H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
- size_t size, void *buf);
+ size_t size, void *buf);
static herr_t H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
- size_t size, const void *buf);
+ size_t size, const void *buf);
static herr_t H5FD_sec2_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_sec2_g = {
- "sec2", /*name */
- MAXADDR, /*maxaddr */
- H5F_CLOSE_WEAK, /* fc_degree */
- NULL, /*sb_size */
- NULL, /*sb_encode */
- NULL, /*sb_decode */
- 0, /*fapl_size */
- NULL, /*fapl_get */
- NULL, /*fapl_copy */
- NULL, /*fapl_free */
- 0, /*dxpl_size */
- NULL, /*dxpl_copy */
- NULL, /*dxpl_free */
- H5FD_sec2_open, /*open */
- H5FD_sec2_close, /*close */
- H5FD_sec2_cmp, /*cmp */
- H5FD_sec2_query, /*query */
- NULL, /*get_type_map */
- NULL, /*alloc */
- NULL, /*free */
- H5FD_sec2_get_eoa, /*get_eoa */
- H5FD_sec2_set_eoa, /*set_eoa */
- H5FD_sec2_get_eof, /*get_eof */
+ "sec2", /*name */
+ MAXADDR, /*maxaddr */
+ H5F_CLOSE_WEAK, /* fc_degree */
+ NULL, /*sb_size */
+ NULL, /*sb_encode */
+ NULL, /*sb_decode */
+ 0, /*fapl_size */
+ NULL, /*fapl_get */
+ NULL, /*fapl_copy */
+ NULL, /*fapl_free */
+ 0, /*dxpl_size */
+ NULL, /*dxpl_copy */
+ NULL, /*dxpl_free */
+ H5FD_sec2_open, /*open */
+ H5FD_sec2_close, /*close */
+ H5FD_sec2_cmp, /*cmp */
+ H5FD_sec2_query, /*query */
+ NULL, /*get_type_map */
+ NULL, /*alloc */
+ NULL, /*free */
+ H5FD_sec2_get_eoa, /*get_eoa */
+ H5FD_sec2_set_eoa, /*set_eoa */
+ H5FD_sec2_get_eof, /*get_eof */
H5FD_sec2_get_handle, /*get_handle */
- H5FD_sec2_read, /*read */
- H5FD_sec2_write, /*write */
- NULL, /*flush */
- H5FD_sec2_truncate, /*truncate */
+ H5FD_sec2_read, /*read */
+ H5FD_sec2_write, /*write */
+ NULL, /*flush */
+ H5FD_sec2_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ H5FD_FLMAP_SINGLE /*fl_map */
};
/* Declare a free list to manage the H5FD_sec2_t struct */
@@ -203,15 +219,15 @@ H5FD_sec2_init_interface(void)
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_init
+ * Function: H5FD_sec2_init
*
- * Purpose: Initialize this driver by registering the driver with the
- * library.
+ * Purpose: Initialize this driver by registering the driver with the
+ * library.
*
- * Return: Success: The driver ID for the sec2 driver.
- * Failure: Negative.
+ * Return: Success: The driver ID for the sec2 driver.
+ * Failure: Negative.
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, July 29, 1999
*
*-------------------------------------------------------------------------
@@ -235,11 +251,11 @@ done:
/*---------------------------------------------------------------------------
- * Function: H5FD_sec2_term
+ * Function: H5FD_sec2_term
*
- * Purpose: Shut down the VFD
+ * Purpose: Shut down the VFD
*
- * Return: <none>
+ * Returns: <none>
*
* Programmer: Quincey Koziol
* Friday, Jan 30, 2004
@@ -259,16 +275,16 @@ H5FD_sec2_term(void)
/*-------------------------------------------------------------------------
- * Function: H5Pset_fapl_sec2
+ * Function: H5Pset_fapl_sec2
*
- * Purpose: Modify the file access property list to use the H5FD_SEC2
- * driver defined in this source file. There are no driver
- * specific properties.
+ * Purpose: Modify the file access property list to use the H5FD_SEC2
+ * driver defined in this source file. There are no driver
+ * specific properties.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
- * Thursday, February 19, 1998
+ * Programmer: Robb Matzke
+ * Thursday, February 19, 1998
*
*-------------------------------------------------------------------------
*/
@@ -292,16 +308,16 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_open
+ * Function: H5FD_sec2_open
*
- * Purpose: Create and/or opens a Unix file as an HDF5 file.
+ * Purpose: Create and/or opens a file as an HDF5 file.
*
- * Return: Success: A pointer to a new file data structure. The
- * public fields will be initialized by the
- * caller, which is always H5FD_open().
- * Failure: NULL
+ * Return: Success: A pointer to a new file data structure. The
+ * public fields will be initialized by the
+ * caller, which is always H5FD_open().
+ * Failure: NULL
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, July 29, 1999
*
*-------------------------------------------------------------------------
@@ -309,15 +325,14 @@ done:
static H5FD_t *
H5FD_sec2_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
{
- H5FD_sec2_t *file = NULL; /* sec2 VFD info */
- int fd = (-1); /* File descriptor */
- int o_flags; /* Flags for open() call */
+ H5FD_sec2_t *file = NULL; /* sec2 VFD info */
+ int fd = -1; /* File descriptor */
+ int o_flags; /* Flags for open() call */
#ifdef H5_HAVE_WIN32_API
- HFILE filehandle;
struct _BY_HANDLE_FILE_INFORMATION fileinfo;
#endif
- h5_stat_t sb;
- H5FD_t *ret_value; /* Return value */
+ h5_stat_t sb;
+ H5FD_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FD_sec2_open)
@@ -344,9 +359,9 @@ H5FD_sec2_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
/* Open the file */
if((fd = HDopen(name, o_flags, 0666)) < 0) {
int myerrno = errno;
-
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', errno = %d, error message = '%s', flags = %x, o_flags = %x", name, myerrno, HDstrerror(myerrno), flags, (unsigned)o_flags);
} /* end if */
+
if(HDfstat(fd, &sb) < 0)
HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, NULL, "unable to fstat file")
@@ -359,20 +374,25 @@ H5FD_sec2_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
file->pos = HADDR_UNDEF;
file->op = OP_UNKNOWN;
#ifdef H5_HAVE_WIN32_API
- filehandle = _get_osfhandle(fd);
- (void)GetFileInformationByHandle((HANDLE)filehandle, &fileinfo);
- file->fileindexhi = fileinfo.nFileIndexHigh;
- file->fileindexlo = fileinfo.nFileIndexLow;
+ file->hFile = (HANDLE)_get_osfhandle(fd);
+ if(INVALID_HANDLE_VALUE == file->hFile)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to get Windows file handle")
+
+ if(!GetFileInformationByHandle((HANDLE)file->hFile, &fileinfo))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to get Windows file information")
+
+ file->nFileIndexHigh = fileinfo.nFileIndexHigh;
+ file->nFileIndexLow = fileinfo.nFileIndexLow;
+ file->dwVolumeSerialNumber = fileinfo.dwVolumeSerialNumber;
#else /* H5_HAVE_WIN32_API */
file->device = sb.st_dev;
#ifdef H5_VMS
file->inode[0] = sb.st_ino[0];
file->inode[1] = sb.st_ino[1];
file->inode[2] = sb.st_ino[2];
-#else
+#else /* H5_VMS */
file->inode = sb.st_ino;
-#endif /*H5_VMS*/
-
+#endif /* H5_VMS */
#endif /* H5_HAVE_WIN32_API */
/* Retain a copy of the name used to open the file, for possible error reporting */
@@ -413,14 +433,14 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_close
+ * Function: H5FD_sec2_close
*
- * Purpose: Closes a Unix file.
+ * Purpose: Closes an HDF5 file.
*
- * Return: Success: 0
- * Failure: -1, file not closed.
+ * Return: Success: 0
+ * Failure: -1, file not closed.
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, July 29, 1999
*
*-------------------------------------------------------------------------
@@ -428,7 +448,7 @@ done:
static herr_t
H5FD_sec2_close(H5FD_t *_file)
{
- H5FD_sec2_t *file = (H5FD_sec2_t *)_file;
+ H5FD_sec2_t *file = (H5FD_sec2_t *)_file;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FD_sec2_close)
@@ -449,16 +469,16 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_cmp
+ * Function: H5FD_sec2_cmp
*
- * Purpose: Compares two files belonging to this driver using an
- * arbitrary (but consistent) ordering.
+ * Purpose: Compares two files belonging to this driver using an
+ * arbitrary (but consistent) ordering.
*
- * Return: Success: A value like strcmp()
- * Failure: never fails (arguments were checked by the
- * caller).
+ * Return: Success: A value like strcmp()
+ * Failure: never fails (arguments were checked by the
+ * caller).
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, July 29, 1999
*
*-------------------------------------------------------------------------
@@ -466,20 +486,22 @@ done:
static int
H5FD_sec2_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
{
- const H5FD_sec2_t *f1 = (const H5FD_sec2_t *)_f1;
- const H5FD_sec2_t *f2 = (const H5FD_sec2_t *)_f2;
+ const H5FD_sec2_t *f1 = (const H5FD_sec2_t *)_f1;
+ const H5FD_sec2_t *f2 = (const H5FD_sec2_t *)_f2;
int ret_value = 0;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_sec2_cmp)
#ifdef H5_HAVE_WIN32_API
- if(f1->fileindexhi < f2->fileindexhi) HGOTO_DONE(-1)
- if(f1->fileindexhi > f2->fileindexhi) HGOTO_DONE(1)
+ if(f1->dwVolumeSerialNumber < f2->dwVolumeSerialNumber) HGOTO_DONE(-1)
+ if(f1->dwVolumeSerialNumber > f2->dwVolumeSerialNumber) HGOTO_DONE(1)
- if(f1->fileindexlo < f2->fileindexlo) HGOTO_DONE(-1)
- if(f1->fileindexlo > f2->fileindexlo) HGOTO_DONE(1)
+ if(f1->nFileIndexHigh < f2->nFileIndexHigh) HGOTO_DONE(-1)
+ if(f1->nFileIndexHigh > f2->nFileIndexHigh) HGOTO_DONE(1)
-#else
+ if(f1->nFileIndexLow < f2->nFileIndexLow) HGOTO_DONE(-1)
+ if(f1->nFileIndexLow > f2->nFileIndexLow) HGOTO_DONE(1)
+#else /* H5_HAVE_WIN32_API */
#ifdef H5_DEV_T_IS_SCALAR
if(f1->device < f2->device) HGOTO_DONE(-1)
if(f1->device > f2->device) HGOTO_DONE(1)
@@ -491,16 +513,14 @@ H5FD_sec2_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
if(HDmemcmp(&(f1->device),&(f2->device),sizeof(dev_t)) < 0) HGOTO_DONE(-1)
if(HDmemcmp(&(f1->device),&(f2->device),sizeof(dev_t)) > 0) HGOTO_DONE(1)
#endif /* H5_DEV_T_IS_SCALAR */
-
-#ifndef H5_VMS
- if(f1->inode < f2->inode) HGOTO_DONE(-1)
- if(f1->inode > f2->inode) HGOTO_DONE(1)
-#else
+#ifdef H5_VMS
if(HDmemcmp(&(f1->inode), &(f2->inode), 3 * sizeof(ino_t)) < 0) HGOTO_DONE(-1)
if(HDmemcmp(&(f1->inode), &(f2->inode), 3 * sizeof(ino_t)) > 0) HGOTO_DONE(1)
-#endif /*H5_VMS*/
-
-#endif
+#else /* H5_VMS */
+ if(f1->inode < f2->inode) HGOTO_DONE(-1)
+ if(f1->inode > f2->inode) HGOTO_DONE(1)
+#endif /* H5_VMS */
+#endif /* H5_HAVE_WIN32_API */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -508,15 +528,15 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_query
+ * Function: H5FD_sec2_query
*
- * Purpose: Set the flags that this VFL driver is capable of supporting.
+ * Purpose: Set the flags that this VFL driver is capable of supporting.
* (listed in H5FDpublic.h)
*
- * Return: Success: non-negative
- * Failure: negative
+ * Return: Success: non-negative
+ * Failure: negative
*
- * Programmer: Quincey Koziol
+ * Programmer: Quincey Koziol
* Friday, August 25, 2000
*
*-------------------------------------------------------------------------
@@ -524,18 +544,18 @@ done:
static herr_t
H5FD_sec2_query(const H5FD_t *_file, unsigned long *flags /* out */)
{
- const H5FD_sec2_t *file = (const H5FD_sec2_t *)_file; /* sec2 VFD info */
+ const H5FD_sec2_t *file = (const H5FD_sec2_t *)_file; /* sec2 VFD info */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_sec2_query)
/* Set the VFL feature flags that this driver supports */
if(flags) {
*flags = 0;
- *flags |= H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
- *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */
- *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
- *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
- *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */
+ *flags |= H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
+ *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */
+ *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
+ *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
+ *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */
/* Check for flags that are set by h5repart */
if(file->fam_to_sec2)
@@ -547,24 +567,25 @@ H5FD_sec2_query(const H5FD_t *_file, unsigned long *flags /* out */)
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_get_eoa
+ * Function: H5FD_sec2_get_eoa
*
- * Purpose: Gets the end-of-address marker for the file. The EOA marker
- * is the first address past the last byte allocated in the
- * format address space.
+ * Purpose: Gets the end-of-address marker for the file. The EOA marker
+ * is the first address past the last byte allocated in the
+ * format address space.
*
- * Return: Success: The end-of-address marker.
- * Failure: HADDR_UNDEF
+ * Return: Success: The end-of-address marker.
+ * Failure: HADDR_UNDEF
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Monday, August 2, 1999
*
*-------------------------------------------------------------------------
*/
+/* ARGSUSED */
static haddr_t
H5FD_sec2_get_eoa(const H5FD_t *_file, H5FD_mem_t UNUSED type)
{
- const H5FD_sec2_t *file = (const H5FD_sec2_t *)_file;
+ const H5FD_sec2_t *file = (const H5FD_sec2_t *)_file;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_sec2_get_eoa)
@@ -573,24 +594,25 @@ H5FD_sec2_get_eoa(const H5FD_t *_file, H5FD_mem_t UNUSED type)
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_set_eoa
+ * Function: H5FD_sec2_set_eoa
*
- * Purpose: Set the end-of-address marker for the file. This function is
- * called shortly after an existing HDF5 file is opened in order
- * to tell the driver where the end of the HDF5 data is located.
+ * Purpose: Set the end-of-address marker for the file. This function is
+ * called shortly after an existing HDF5 file is opened in order
+ * to tell the driver where the end of the HDF5 data is located.
*
- * Return: Success: 0
- * Failure: -1
+ * Return: Success: 0
+ * Failure: -1
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, July 29, 1999
*
*-------------------------------------------------------------------------
*/
+/* ARGSUSED */
static herr_t
H5FD_sec2_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr)
{
- H5FD_sec2_t *file = (H5FD_sec2_t *)_file;
+ H5FD_sec2_t *file = (H5FD_sec2_t *)_file;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_sec2_set_eoa)
@@ -601,18 +623,18 @@ H5FD_sec2_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr)
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_get_eof
+ * Function: H5FD_sec2_get_eof
*
- * Purpose: Returns the end-of-file marker, which is the greater of
- * either the Unix end-of-file or the HDF5 end-of-address
- * markers.
+ * Purpose: Returns the end-of-file marker, which is the greater of
+ * either the filesystem end-of-file or the HDF5 end-of-address
+ * markers.
*
- * Return: Success: End of file address, the first address past
- * the end of the "file", either the Unix file
- * or the HDF5 file.
- * Failure: HADDR_UNDEF
+ * Return: Success: End of file address, the first address past
+ * the end of the "file", either the filesystem file
+ * or the HDF5 file.
+ * Failure: HADDR_UNDEF
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, July 29, 1999
*
*-------------------------------------------------------------------------
@@ -620,7 +642,7 @@ H5FD_sec2_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr)
static haddr_t
H5FD_sec2_get_eof(const H5FD_t *_file)
{
- const H5FD_sec2_t *file = (const H5FD_sec2_t *)_file;
+ const H5FD_sec2_t *file = (const H5FD_sec2_t *)_file;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_sec2_get_eof)
@@ -660,17 +682,17 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_read
+ * Function: H5FD_sec2_read
*
- * Purpose: Reads SIZE bytes of data from FILE beginning at address ADDR
- * into buffer BUF according to data transfer properties in
- * DXPL_ID.
+ * Purpose: Reads SIZE bytes of data from FILE beginning at address ADDR
+ * into buffer BUF according to data transfer properties in
+ * DXPL_ID.
*
- * Return: Success: Zero. Result is stored in caller-supplied
- * buffer BUF.
- * Failure: -1, Contents of buffer BUF are undefined.
+ * Return: Success: Zero. Result is stored in caller-supplied
+ * buffer BUF.
+ * Failure: -1, Contents of buffer BUF are undefined.
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, July 29, 1999
*
*-------------------------------------------------------------------------
@@ -678,11 +700,10 @@ done:
/* ARGSUSED */
static herr_t
H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id,
- haddr_t addr, size_t size, void *buf/*out*/)
+ haddr_t addr, size_t size, void *buf /*out*/)
{
- H5FD_sec2_t *file = (H5FD_sec2_t *)_file;
- ssize_t nbytes;
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FD_sec2_t *file = (H5FD_sec2_t *)_file;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FD_sec2_read)
@@ -704,33 +725,46 @@ H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id,
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
} /* end if */
- /*
- * Read data, being careful of interrupted system calls, partial results,
+ /* Read data, being careful of interrupted system calls, partial results,
* and the end of the file.
*/
while(size > 0) {
+
+ h5_sec2_io_t bytes_in = 0; /* # of bytes to read */
+ h5_sec2_io_ret_t bytes_read = -1; /* # of bytes actually read */
+
+ /* Trying to read more bytes than the return type can handle is
+ * undefined behavior in POSIX.
+ */
+ if(size > H5_SEC2_MAX_IO_BYTES_g)
+ bytes_in = H5_SEC2_MAX_IO_BYTES_g;
+ else
+ bytes_in = (h5_sec2_io_t)size;
+
do {
- nbytes = HDread(file->fd, buf, size);
- } while(-1 == nbytes && EINTR == errno);
- if(-1 == nbytes) { /* error */
+ bytes_read = HDread(file->fd, buf, bytes_in);
+ } while(-1 == bytes_read && EINTR == errno);
+
+ if(-1 == bytes_read) { /* error */
int myerrno = errno;
time_t mytime = HDtime(NULL);
HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, size = %lu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long)size, (unsigned long long)myoffset);
} /* end if */
- if(0 == nbytes) {
+
+ if(0 == bytes_read) {
/* end of file but not end of format address space */
HDmemset(buf, 0, size);
break;
} /* end if */
- HDassert(nbytes >= 0);
- HDassert((size_t)nbytes <= size);
- H5_CHECK_OVERFLOW(nbytes, ssize_t, size_t);
- size -= (size_t)nbytes;
- H5_CHECK_OVERFLOW(nbytes, ssize_t, haddr_t);
- addr += (haddr_t)nbytes;
- buf = (char *)buf + nbytes;
+
+ HDassert(bytes_read >= 0);
+ HDassert((size_t)bytes_read <= size);
+
+ size -= (size_t)bytes_read;
+ addr += (haddr_t)bytes_read;
+ buf = (char *)buf + bytes_read;
} /* end while */
/* Update current position */
@@ -749,28 +783,27 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_write
+ * Function: H5FD_sec2_write
*
- * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR
- * from buffer BUF according to data transfer properties in
- * DXPL_ID.
+ * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR
+ * from buffer BUF according to data transfer properties in
+ * DXPL_ID.
*
- * Return: Success: Zero
- * Failure: -1
+ * Return: Success: Zero
+ * Failure: -1
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Thursday, July 29, 1999
*
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
static herr_t
-H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, haddr_t addr,
- size_t size, const void *buf)
+H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id,
+ haddr_t addr, size_t size, const void *buf)
{
- H5FD_sec2_t *file = (H5FD_sec2_t *)_file;
- ssize_t nbytes;
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FD_sec2_t *file = (H5FD_sec2_t *)_file;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FD_sec2_write)
@@ -791,28 +824,40 @@ H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, had
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
} /* end if */
- /*
- * Write the data, being careful of interrupted system calls and partial
+ /* Write the data, being careful of interrupted system calls and partial
* results
*/
while(size > 0) {
+
+ h5_sec2_io_t bytes_in = 0; /* # of bytes to write */
+ h5_sec2_io_ret_t bytes_wrote = -1; /* # of bytes written */
+
+ /* Trying to write more bytes than the return type can handle is
+ * undefined behavior in POSIX.
+ */
+ if(size > H5_SEC2_MAX_IO_BYTES_g)
+ bytes_in = H5_SEC2_MAX_IO_BYTES_g;
+ else
+ bytes_in = (h5_sec2_io_t)size;
+
do {
- nbytes = HDwrite(file->fd, buf, size);
- } while(-1 == nbytes && EINTR == errno);
- if(-1 == nbytes) { /* error */
+ bytes_wrote = HDwrite(file->fd, buf, bytes_in);
+ } while(-1 == bytes_wrote && EINTR == errno);
+
+ if(-1 == bytes_wrote) { /* error */
int myerrno = errno;
time_t mytime = HDtime(NULL);
HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, size = %lu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long)size, (unsigned long long)myoffset);
} /* end if */
- HDassert(nbytes > 0);
- HDassert((size_t)nbytes <= size);
- H5_CHECK_OVERFLOW(nbytes, ssize_t, size_t);
- size -= (size_t)nbytes;
- H5_CHECK_OVERFLOW(nbytes, ssize_t, haddr_t);
- addr += (haddr_t)nbytes;
- buf = (const char *)buf + nbytes;
+
+ HDassert(bytes_wrote > 0);
+ HDassert((size_t)bytes_wrote <= size);
+
+ size -= (size_t)bytes_wrote;
+ addr += (haddr_t)bytes_wrote;
+ buf = (const char *)buf + bytes_wrote;
} /* end while */
/* Update current position and eof */
@@ -833,15 +878,15 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_truncate
+ * Function: H5FD_sec2_truncate
*
- * Purpose: Makes sure that the true file size is the same (or larger)
- * than the end-of-address.
+ * Purpose: Makes sure that the true file size is the same (or larger)
+ * than the end-of-address.
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Robb Matzke
+ * Programmer: Robb Matzke
* Wednesday, August 4, 1999
*
*-------------------------------------------------------------------------
@@ -860,17 +905,30 @@ H5FD_sec2_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
/* Extend the file to make sure it's large enough */
if(!H5F_addr_eq(file->eoa, file->eof)) {
#ifdef H5_HAVE_WIN32_API
- HFILE filehandle; /* Windows file handle */
- LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */
-
- /* Map the posix file handle to a Windows file handle */
- filehandle = _get_osfhandle(file->fd);
-
- /* Translate 64-bit integers into form Windows wants */
- /* [This algorithm is from the Windows documentation for SetFilePointer()] */
- li.QuadPart = (LONGLONG)file->eoa;
- (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN);
- if(SetEndOfFile((HANDLE)filehandle) == 0)
+ LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */
+ DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer()
+ * Only used as an error code here.
+ */
+ DWORD dwError; /* DWORD error code from GetLastError() */
+ BOOL bError; /* Boolean error flag */
+
+ /* Windows uses this odd QuadPart union for 32/64-bit portability */
+ li.QuadPart = (__int64)file->eoa;
+
+ /* Extend the file to make sure it's large enough.
+ *
+ * Since INVALID_SET_FILE_POINTER can technically be a valid return value
+ * from SetFilePointer(), we also need to check GetLastError().
+ */
+ dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(INVALID_SET_FILE_POINTER == dwPtrLow) {
+ dwError = GetLastError();
+ if(dwError != NO_ERROR )
+ HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to set file pointer")
+ }
+
+ bError = SetEndOfFile(file->hFile);
+ if(0 == bError)
HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#else /* H5_HAVE_WIN32_API */
#ifdef H5_VMS
@@ -879,7 +937,6 @@ H5FD_sec2_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
if(-1 == HDlseek(file->fd, (HDoff_t)0, SEEK_SET))
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
#endif
-
if(-1 == HDftruncate(file->fd, (HDoff_t)file->eoa))
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#endif /* H5_HAVE_WIN32_API */