summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5FDstdio.c671
1 files changed, 343 insertions, 328 deletions
diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c
index 49e1957..4733eba 100644
--- a/src/H5FDstdio.c
+++ b/src/H5FDstdio.c
@@ -13,32 +13,24 @@
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/*
- * Programmer: Robb Matzke <matzke@llnl.gov>
- * Wednesday, October 22, 1997
- *
- * Purpose: This is the Posix stdio.h I/O subclass of H5Flow.
- * It also serves as an example of coding a simple file driver,
- * therefore, it should not use any non-public definitions.
+/* Programmer: Robb Matzke <matzke@llnl.gov>
+ * Wednesday, October 22, 1997
*
- * Notes: Ported to the new H5FD architecture on 10/18/99 - QAK
+ * Purpose: The C STDIO virtual file driver which only uses calls from stdio.h.
+ * This also serves as an example of coding a simple file driver,
+ * therefore, it should not use any non-public definitions.
*
+ * NOTE: This driver is not as well tested as the standard SEC2 driver
+ * and is not intended for production use!
*/
#include <assert.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
-/* Disable certain warnings in PC-Lint: */
-/*lint --emacro( {534, 830}, H5P_FILE_ACCESS) */
-/*lint --emacro( {534, 830}, H5F_ACC_RDWR, H5F_ACC_EXCL) */
-/*lint -esym( 534, H5Eclear2, H5Epush2) */
-
#include "hdf5.h"
-#ifdef H5_HAVE_STDIO_H
-#include <stdio.h>
-#endif
#ifdef H5_HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -58,7 +50,6 @@
#endif
-
#ifdef MAX
#undef MAX
#endif /* MAX */
@@ -67,6 +58,9 @@
/* The driver identification number, initialized at runtime */
static hid_t H5FD_STDIO_g = 0;
+/* The maximum number of bytes which can be written in a single I/O operation */
+static size_t H5_STDIO_MAX_IO_BYTES_g = (size_t)-1;
+
/* File operations */
typedef enum {
H5FD_STDIO_OP_UNKNOWN=0,
@@ -75,57 +69,71 @@ typedef enum {
H5FD_STDIO_OP_SEEK=3
} H5FD_stdio_file_op;
-/*
- * The description of a file belonging to this driver. The `eoa' and `eof'
+/* 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'
+ * 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
* 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
- * a file the `eof' will be set to the current file size, `eoa' will be set
- * to zero, `pos' will be set to H5F_ADDR_UNDEF (as it is when an error
- * occurs), and `op' will be set to H5F_OP_UNKNOWN.
+ * a file the 'eof' will be set to the current file size, 'eoa' will be set
+ * to zero, 'pos' will be set to H5F_ADDR_UNDEF (as it is when an error
+ * occurs), and 'op' will be set to H5F_OP_UNKNOWN.
*/
typedef struct H5FD_stdio_t {
- H5FD_t pub; /*public stuff, must be first */
- FILE * fp; /*the file handle */
- 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_stdio_file_op op; /*last operation */
- unsigned write_access; /* Flag to indicate the file was opened with write access */
+ H5FD_t pub; /* public stuff, must be first */
+ FILE *fp; /* the file handle */
+ int fd; /* file descriptor (for truncate) */
+ haddr_t eoa; /* end of allocated region */
+ haddr_t eof; /* end of file; current file size */
+ haddr_t pos; /* current file I/O position */
+ unsigned write_access; /* Flag to indicate the file was opened with write access */
+ H5FD_stdio_file_op op; /* last 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 */
- ino_t inode; /*file i-node number */
+ dev_t device; /* file device number */
+#ifdef H5_VMS
+ ino_t inode[3]; /* file i-node number */
+#else
+ 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
+ DWORD nFileIndexLow;
+ DWORD nFileIndexHigh;
+ DWORD dwVolumeSerialNumber;
+
+ HANDLE hFile; /* Native windows file handle */
+#endif /* H5_HAVE_WIN32_API */
} H5FD_stdio_t;
/* Use similar structure as in H5private.h by defining Windows stuff first. */
#ifdef H5_HAVE_WIN32_API
- #ifndef H5_HAVE_MINGW
- # define file_fseek _fseeki64
- # define file_offset_t __int64
- # define file_ftruncate _chsize_s /* Supported in VS 2005 or newer */
- # define file_ftell _ftelli64
- #endif
-#endif
+#ifndef H5_HAVE_MINGW
+ #define file_fseek _fseeki64
+ #define file_offset_t __int64
+ #define file_ftruncate _chsize_s /* Supported in VS 2005 or newer */
+ #define file_ftell _ftelli64
+#endif /* H5_HAVE_MINGW */
+#endif /* H5_HAVE_WIN32_API */
/* Use file_xxx to indicate these are local macros, avoiding confusing
* with the global HD_xxx macros.
@@ -134,20 +142,19 @@ typedef struct H5FD_stdio_t {
*/
#ifndef file_fseek
#ifdef H5_HAVE_FSEEKO64
- # define file_fseek fseeko64
- # define file_offset_t off64_t
- # define file_ftruncate ftruncate64
- # define file_ftell ftello64
+ #define file_fseek fseeko64
+ #define file_offset_t off64_t
+ #define file_ftruncate ftruncate64
+ #define file_ftell ftello64
#else
- # define file_fseek fseeko
- # define file_offset_t off_t
- # define file_ftruncate ftruncate
- # define file_ftell ftello
- #endif
-#endif
-
-/*
- * These macros check for overflow of various quantities. These macros
+ #define file_fseek fseeko
+ #define file_offset_t off_t
+ #define file_ftruncate ftruncate
+ #define file_ftell ftello
+ #endif /* H5_HAVE_FSEEKO64 */
+#endif /* file_fseek */
+
+/* These macros check for overflow of various quantities. These macros
* assume that file_offset_t is signed and haddr_t and size_t are unsigned.
*
* ADDR_OVERFLOW: Checks whether a file address of type `haddr_t'
@@ -188,38 +195,38 @@ static herr_t H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
static herr_t H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_stdio_g = {
- "stdio", /*name */
- MAXADDR, /*maxaddr */
- H5F_CLOSE_WEAK, /* fc_degree */
- H5FD_stdio_term, /*terminate */
- 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_stdio_open, /*open */
- H5FD_stdio_close, /*close */
- H5FD_stdio_cmp, /*cmp */
- H5FD_stdio_query, /*query */
- NULL, /*get_type_map */
- H5FD_stdio_alloc, /*alloc */
- NULL, /*free */
- H5FD_stdio_get_eoa, /*get_eoa */
- H5FD_stdio_set_eoa, /*set_eoa */
- H5FD_stdio_get_eof, /*get_eof */
- H5FD_stdio_get_handle, /*get_handle */
- H5FD_stdio_read, /*read */
- H5FD_stdio_write, /*write */
- H5FD_stdio_flush, /*flush */
- H5FD_stdio_truncate, /*truncate */
- NULL, /*lock */
- NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ "stdio", /* name */
+ MAXADDR, /* maxaddr */
+ H5F_CLOSE_WEAK, /* fc_degree */
+ H5FD_stdio_term, /* terminate */
+ 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_stdio_open, /* open */
+ H5FD_stdio_close, /* close */
+ H5FD_stdio_cmp, /* cmp */
+ H5FD_stdio_query, /* query */
+ NULL, /* get_type_map */
+ H5FD_stdio_alloc, /* alloc */
+ NULL, /* free */
+ H5FD_stdio_get_eoa, /* get_eoa */
+ H5FD_stdio_set_eoa, /* set_eoa */
+ H5FD_stdio_get_eof, /* get_eof */
+ H5FD_stdio_get_handle, /* get_handle */
+ H5FD_stdio_read, /* read */
+ H5FD_stdio_write, /* write */
+ H5FD_stdio_flush, /* flush */
+ H5FD_stdio_truncate, /* truncate */
+ NULL, /* lock */
+ NULL, /* unlock */
+ H5FD_FLMAP_SINGLE /* fl_map */
};
@@ -236,9 +243,6 @@ static const H5FD_class_t H5FD_stdio_g = {
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
hid_t
@@ -249,8 +253,8 @@ H5FD_stdio_init(void)
if (H5I_VFL!=H5Iget_type(H5FD_STDIO_g))
H5FD_STDIO_g = H5FDregister(&H5FD_stdio_g);
- return(H5FD_STDIO_g);
-}
+ return H5FD_STDIO_g;
+} /* end H5FD_stdio_init() */
/*---------------------------------------------------------------------------
@@ -269,7 +273,7 @@ static herr_t
H5FD_stdio_term(void)
{
/* Reset VFL ID */
- H5FD_STDIO_g=0;
+ H5FD_STDIO_g = 0;
return 0;
} /* end H5FD_stdio_term() */
@@ -287,15 +291,12 @@ H5FD_stdio_term(void)
* Programmer: Robb Matzke
* Thursday, February 19, 1998
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
herr_t
H5Pset_fapl_stdio(hid_t fapl_id)
{
- static const char *func="H5FDset_fapl_stdio"; /*for error reporting*/
+ static const char *func = "H5FDset_fapl_stdio"; /*for error reporting*/
/*NO TRACE*/
@@ -306,7 +307,7 @@ H5Pset_fapl_stdio(hid_t fapl_id)
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADTYPE, "not a file access property list", -1)
return H5Pset_driver(fapl_id, H5FD_STDIO, NULL);
-}
+} /* end H5Pset_fapl_stdio() */
/*-------------------------------------------------------------------------
@@ -314,50 +315,44 @@ H5Pset_fapl_stdio(hid_t fapl_id)
*
* Purpose: Create and/or opens a Standard C file as an HDF5 file.
*
- * Bugs: H5F_ACC_EXCL has a race condition. (? -QAK)
- *
* Errors:
- * IO CANTOPENFILE File doesn't exist and CREAT wasn't
- * specified.
- * IO CANTOPENFILE Fopen failed.
- * IO FILEEXISTS File exists but CREAT and EXCL were
- * specified.
+ * IO CANTOPENFILE File doesn't exist and CREAT wasn't
+ * specified.
+ * IO CANTOPENFILE fopen() failed.
+ * IO FILEEXISTS File exists but CREAT and EXCL were
+ * specified.
*
- * Return: Success: A pointer to a new file data structure. The
- * public fields will be initialized by the
- * caller, which is always H5FD_open().
+ * 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
+ * Failure: NULL
*
* Programmer: Robb Matzke
* Wednesday, October 22, 1997
*
- * Modifications:
- * Ported to VFL/H5FD layer - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static H5FD_t *
H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
haddr_t maxaddr)
{
- FILE *f = NULL;
- unsigned write_access=0; /* File opened with write access? */
- H5FD_stdio_t *file=NULL;
- static const char *func="H5FD_stdio_open"; /* Function Name for error reporting */
+ FILE *f = NULL;
+ unsigned write_access = 0; /* File opened with write access? */
+ H5FD_stdio_t *file = NULL;
+ static const char *func = "H5FD_stdio_open"; /* Function Name for error reporting */
#ifdef H5_HAVE_WIN32_API
- HFILE filehandle;
- struct _BY_HANDLE_FILE_INFORMATION fileinfo;
- int fd;
+ struct _BY_HANDLE_FILE_INFORMATION fileinfo;
#else /* H5_HAVE_WIN32_API */
- struct stat sb;
+ struct stat sb;
#endif /* H5_HAVE_WIN32_API */
/* Sanity check on file offsets */
- assert(sizeof(file_offset_t)>=sizeof(size_t));
+ assert(sizeof(file_offset_t) >= sizeof(size_t));
- /* Shut compiler up */
- fapl_id=fapl_id;
+ /* Quiet compiler */
+ fapl_id = fapl_id;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -365,15 +360,16 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
/* Check arguments */
if (!name || !*name)
H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_BADVALUE, "invalid file name", NULL)
- if (0==maxaddr || HADDR_UNDEF==maxaddr)
+ if (0 == maxaddr || HADDR_UNDEF == maxaddr)
H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_BADRANGE, "bogus maxaddr", NULL)
if (ADDR_OVERFLOW(maxaddr))
H5Epush_ret(func, H5E_ERR_CLS, H5E_ARGS, H5E_OVERFLOW, "maxaddr too large", NULL)
+ /* Attempt to open/create the file */
if (access(name, F_OK) < 0) {
if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_RDWR)) {
f = fopen(name, "wb+");
- write_access=1; /* Note the write access */
+ write_access = 1; /* Note the write access */
}
else
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_CANTOPENFILE, "file doesn't exist and CREAT wasn't specified", NULL)
@@ -384,7 +380,7 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
f = fopen(name, "wb+");
else
f = fopen(name, "rb+");
- write_access=1; /* Note the write access */
+ write_access = 1; /* Note the write access */
} else {
f = fopen(name, "rb");
}
@@ -399,30 +395,46 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
file->fp = f;
file->op = H5FD_STDIO_OP_SEEK;
file->pos = HADDR_UNDEF;
- file->write_access=write_access; /* Note the write_access for later */
+ file->write_access = write_access; /* Note the write_access for later */
if(file_fseek(file->fp, (file_offset_t)0, SEEK_END) < 0) {
file->op = H5FD_STDIO_OP_UNKNOWN;
} else {
- file_offset_t x = file_ftell (file->fp);
- assert (x>=0);
+ file_offset_t x = file_ftell(file->fp);
+ assert (x >= 0);
file->eof = (haddr_t)x;
}
- /* The unique key */
+ /* Get the file descriptor (needed for truncate and some Windows information) */
+ file->fd = fileno(file->fp);
+ if(file->fd < 0)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTOPENFILE, "unable to get file descriptor", NULL);
+
+
#ifdef H5_HAVE_WIN32_API
-/*#error "Needs correct fileindexhi & fileindexlo, code below is from sec2 driver"*/
- fd = _fileno(f);
- filehandle = _get_osfhandle(fd);
- (void)GetFileInformationByHandle((HANDLE)filehandle, &fileinfo);
- file->fileindexhi = fileinfo.nFileIndexHigh;
- file->fileindexlo = fileinfo.nFileIndexLow;
-#else
- fstat(fileno(file->fp), &sb);
+ file->hFile = (HANDLE)_get_osfhandle(file->fd);
+ if(INVALID_HANDLE_VALUE == file->hFile)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTOPENFILE, "unable to get Windows file handle", NULL);
+
+ if(!GetFileInformationByHandle((HANDLE)file->hFile, &fileinfo))
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTOPENFILE, "unable to get Windows file desinformationcriptor", NULL);
+
+ file->nFileIndexHigh = fileinfo.nFileIndexHigh;
+ file->nFileIndexLow = fileinfo.nFileIndexLow;
+ file->dwVolumeSerialNumber = fileinfo.dwVolumeSerialNumber;
+#else /* H5_HAVE_WIN32_API */
+ fstat(file->fd, &sb);
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 /* H5_VMS */
file->inode = sb.st_ino;
-#endif
- return((H5FD_t*)file);
-} /* end H5FD_stdio_open() */
+#endif /* H5_VMS */
+#endif /* H5_HAVE_WIN32_API */
+
+ return (H5FD_t*)file;
+} /* end H5FD_stdio_open() */
/*-------------------------------------------------------------------------
@@ -438,16 +450,13 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
* Programmer: Robb Matzke
* Wednesday, October 22, 1997
*
- * Modifications:
- * Ported to VFL/H5FD layer - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_stdio_close(H5FD_t *_file)
{
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
- static const char *func="H5FD_stdio_close"; /* Function Name for error reporting */
+ static const char *func = "H5FD_stdio_close"; /* Function Name for error reporting */
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -457,8 +466,8 @@ H5FD_stdio_close(H5FD_t *_file)
free(file);
- return(0);
-}
+ return 0;
+} /* end H5FD_stdio_close() */
/*-------------------------------------------------------------------------
@@ -467,17 +476,14 @@ H5FD_stdio_close(H5FD_t *_file)
* Purpose: Compares two files belonging to this driver using an
* arbitrary (but consistent) ordering.
*
- * Return: Success: A value like strcmp()
+ * Return:
+ * Success: A value like strcmp()
*
- * Failure: never fails (arguments were checked by the
- * caller).
+ * Failure: never fails (arguments were checked by the caller).
*
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static int
@@ -490,30 +496,37 @@ H5FD_stdio_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
H5Eclear2(H5E_DEFAULT);
#ifdef H5_HAVE_WIN32_API
- if (f1->fileindexhi < f2->fileindexhi) return -1;
- if (f1->fileindexhi > f2->fileindexhi) return 1;
+ if(f1->dwVolumeSerialNumber < f2->dwVolumeSerialNumber) return -1;
+ if(f1->dwVolumeSerialNumber > f2->dwVolumeSerialNumber) return 1;
- if (f1->fileindexlo < f2->fileindexlo) return -1;
- if (f1->fileindexlo > f2->fileindexlo) return 1;
+ if(f1->nFileIndexHigh < f2->nFileIndexHigh) return -1;
+ if(f1->nFileIndexHigh > f2->nFileIndexHigh) return 1;
-#else
+ if(f1->nFileIndexLow < f2->nFileIndexLow) return -1;
+ if(f1->nFileIndexLow > f2->nFileIndexLow) return 1;
+#else /* H5_HAVE_WIN32_API */
#ifdef H5_DEV_T_IS_SCALAR
- if (f1->device < f2->device) return -1;
- if (f1->device > f2->device) return 1;
+ if(f1->device < f2->device) return -1;
+ if(f1->device > f2->device) return 1;
#else /* H5_DEV_T_IS_SCALAR */
/* If dev_t isn't a scalar value on this system, just use memcmp to
* determine if the values are the same or not. The actual return value
* shouldn't really matter...
*/
- if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t))<0) return -1;
- if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t))>0) return 1;
+ if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t)) < 0) return -1;
+ if(memcmp(&(f1->device),&(f2->device),sizeof(dev_t)) > 0) return 1;
#endif /* H5_DEV_T_IS_SCALAR */
+#ifdef H5_VMS
+ if(memcmp(&(f1->inode), &(f2->inode), 3 * sizeof(ino_t)) < 0) return -1;
+ if(memcmp(&(f1->inode), &(f2->inode), 3 * sizeof(ino_t)) > 0) return 1;
+#else /* H5_VMS */
+ if(f1->inode < f2->inode) return -1;
+ if(f1->inode > f2->inode) return 1;
+#endif /* H5_VMS */
+#endif /* H5_HAVE_WIN32_API */
- if (f1->inode < f2->inode) return -1;
- if (f1->inode > f2->inode) return 1;
-#endif
return 0;
-}
+} /* H5FD_stdio_cmp() */
/*-------------------------------------------------------------------------
@@ -529,14 +542,12 @@ H5FD_stdio_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
* Programmer: Quincey Koziol
* Friday, August 25, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_stdio_query(const H5FD_t *_f, unsigned long *flags /* out */)
{
- /* Shut compiler up */
+ /* Quiet the compiler */
_f=_f;
/* Set the VFL feature flags that this driver supports */
@@ -548,37 +559,35 @@ H5FD_stdio_query(const H5FD_t *_f, unsigned long *flags /* out */)
*flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
}
- return(0);
-}
+ return 0;
+} /* end H5FD_stdio_query() */
/*-------------------------------------------------------------------------
* Function: H5FD_stdio_alloc
*
- * Purpose: Allocates file memory. If fseeko isn't available, makes
+ * Purpose: Allocates file memory. If fseeko isn't available, makes
* sure the file size isn't bigger than 2GB because the
* parameter OFFSET of fseek is of the type LONG INT, limiting
* the file size to 2GB.
*
- * Return: Success: Address of new memory
+ * Return:
+ * Success: Address of new memory
*
- * Failure: HADDR_UNDEF
+ * Failure: HADDR_UNDEF
*
* Programmer: Raymond Lu
* 30 March 2007
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static haddr_t
H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxpl_id, hsize_t size)
{
- H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
- haddr_t addr;
- haddr_t ret_value; /* Return value */
+ H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
+ haddr_t addr;
- /* Shut compiler up */
+ /* Quiet compiler */
type = type;
dxpl_id = dxpl_id;
@@ -597,19 +606,16 @@ H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxp
file->eoa = addr + size;
- /* Set return value */
- ret_value = addr;
-
- return(ret_value);
-} /* H5FD_stdio_alloc() */
+ return addr;
+} /* end H5FD_stdio_alloc() */
/*-------------------------------------------------------------------------
* Function: H5FD_stdio_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.
+ * is the first address past the last byte allocated in the
+ * format address space.
*
* Return: Success: The end-of-address marker.
*
@@ -618,28 +624,21 @@ H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxp
* Programmer: Robb Matzke
* Monday, August 2, 1999
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
*-------------------------------------------------------------------------
*/
static haddr_t
-H5FD_stdio_get_eoa(const H5FD_t *_file, H5FD_mem_t /*unused*/ type)
+H5FD_stdio_get_eoa(const H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type)
{
- const H5FD_stdio_t *file = (const H5FD_stdio_t *)_file;
+ const H5FD_stdio_t *file = (const H5FD_stdio_t *)_file;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
- /* Shut compiler up */
+ /* Quiet compiler */
type = type;
- return(file->eoa);
-}
+ return file->eoa;
+} /* end H5FD_stdio_get_eoa() */
/*-------------------------------------------------------------------------
@@ -651,33 +650,27 @@ H5FD_stdio_get_eoa(const H5FD_t *_file, H5FD_mem_t /*unused*/ type)
*
* Return: Success: 0
*
- * Failure: -1
+ * Failure: Does not fail
*
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_stdio_set_eoa(H5FD_t *_file, H5FD_mem_t /*unused*/ type, haddr_t addr)
+H5FD_stdio_set_eoa(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, haddr_t addr)
{
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
- /* Shut compiler up */
+ /* Quiet the compiler */
type = type;
file->eoa = addr;
- return(0);
+ return 0;
}
@@ -697,9 +690,6 @@ H5FD_stdio_set_eoa(H5FD_t *_file, H5FD_mem_t /*unused*/ type, haddr_t addr)
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- * Stolen from the sec2 driver - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static haddr_t
@@ -710,8 +700,8 @@ H5FD_stdio_get_eof(const H5FD_t *_file)
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
- return(MAX(file->eof, file->eoa));
-}
+ return MAX(file->eof, file->eoa);
+} /* end H5FD_stdio_get_eof() */
/*-------------------------------------------------------------------------
@@ -724,64 +714,56 @@ H5FD_stdio_get_eof(const H5FD_t *_file)
* Programmer: Raymond Lu
* Sept. 16, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_stdio_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle)
{
H5FD_stdio_t *file = (H5FD_stdio_t *)_file;
- static const char *func="H5FD_stdio_get_handle"; /* Function Name for error reporting */
+ static const char *func = "H5FD_stdio_get_handle"; /* Function Name for error reporting */
- /* Shut compiler up */
- fapl=fapl;
+ /* Quiet the compiler */
+ fapl = fapl;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
*file_handle = &(file->fp);
- if(*file_handle==NULL)
+ if(*file_handle == NULL)
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "get handle failed", -1)
- return(0);
-}
+
+ return 0;
+} /* end H5FD_stdio_get_handle() */
/*-------------------------------------------------------------------------
- * Function: H5F_stdio_read
+ * Function: H5FD_stdio_read
*
* Purpose: Reads SIZE bytes beginning at address ADDR in file LF and
* places them in buffer BUF. Reading past the logical or
* physical end of file returns zeros instead of failing.
*
* Errors:
- * IO READERROR Fread failed.
- * IO SEEKERROR Fseek failed.
+ * IO READERROR fread failed.
+ * IO SEEKERROR fseek failed.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Wednesday, October 22, 1997
*
- * Modifications:
- * June 2, 1998 Albert Cheng
- * Added xfer_mode argument
- *
- * Ported to VFL/H5FD layer - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_stdio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
void *buf/*out*/)
{
- size_t n;
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
- static const char *func="H5FD_stdio_read"; /* Function Name for error reporting */
+ static const char *func = "H5FD_stdio_read"; /* Function Name for error reporting */
- /* Shut compiler up */
- type=type;
- dxpl_id=dxpl_id;
+ /* Quiet the compiler */
+ type = type;
+ dxpl_id = dxpl_id;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -796,16 +778,14 @@ H5FD_stdio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, siz
/* Check easy cases */
if (0 == size)
- return(0);
+ return 0;
if ((haddr_t)addr >= file->eof) {
memset(buf, 0, size);
- return(0);
+ return 0;
}
- /*
- * Seek to the correct file position.
- */
- if (!(file->op == H5FD_STDIO_OP_READ || file->op==H5FD_STDIO_OP_SEEK) ||
+ /* Seek to the correct file position. */
+ if (!(file->op == H5FD_STDIO_OP_READ || file->op == H5FD_STDIO_OP_SEEK) ||
file->pos != addr) {
if (file_fseek(file->fp, (file_offset_t)addr, SEEK_SET) < 0) {
file->op = H5FD_STDIO_OP_UNKNOWN;
@@ -815,59 +795,70 @@ H5FD_stdio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, siz
file->pos = addr;
}
- /*
- * Read zeros past the logical end of file (physical is handled below)
- */
+ /* Read zeros past the logical end of file (physical is handled below) */
if (addr + size > file->eof) {
size_t nbytes = (size_t) (addr + size - file->eof);
memset((unsigned char *)buf + size - nbytes, 0, nbytes);
size -= nbytes;
}
- /*
- * Read the data. Since we're reading single-byte values, a partial read
+ /* Read the data. Since we're reading single-byte values, a partial read
* will advance the file position by N. If N is zero or an error
* occurs then the file position is undefined.
*/
- n = fread(buf, (size_t)1, size, file->fp);
- if(n == 0 && ferror(file->fp)) {
- file->op = H5FD_STDIO_OP_UNKNOWN;
- file->pos = HADDR_UNDEF;
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_READERROR, "fread failed", -1)
- } else if (n < size) {
- memset((unsigned char *)buf + n, 0, (size - n));
- }
+ while(size > 0) {
- /*
- * Update the file position data.
- */
+ size_t bytes_in = 0; /* # of bytes to read */
+ size_t bytes_read = 0; /* # of bytes actually read */
+ size_t item_size = 1; /* size of items in bytes */
+
+ if(size > H5_STDIO_MAX_IO_BYTES_g)
+ bytes_in = H5_STDIO_MAX_IO_BYTES_g;
+ else
+ bytes_in = size;
+
+ bytes_read = fread(buf, item_size, bytes_in, file->fp);
+
+ if(0 == bytes_read && ferror(file->fp)) { /* error */
+ file->op = H5FD_STDIO_OP_UNKNOWN;
+ file->pos = HADDR_UNDEF;
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_READERROR, "fread failed", -1)
+ } /* end if */
+
+ if(0 == bytes_read && feof(file->fp)) {
+ /* end of file but not end of format address space */
+ memset((unsigned char *)buf, 0, size);
+ break;
+ } /* end if */
+
+ size -= bytes_read;
+ addr += (haddr_t)bytes_read;
+ buf = (char *)buf + bytes_read;
+ } /* end while */
+
+ /* Update the file position data. */
file->op = H5FD_STDIO_OP_READ;
- file->pos = addr+n; /*checked for overflow above*/
- return(0);
+ file->pos = addr;
+
+ return 0;
}
/*-------------------------------------------------------------------------
- * Function: H5F_stdio_write
+ * Function: H5FD_stdio_write
*
* Purpose: Writes SIZE bytes from the beginning of BUF into file LF at
* file address ADDR.
*
* Errors:
- * IO SEEKERROR Fseek failed.
- * IO WRITEERROR Fwrite failed.
+ * IO SEEKERROR fseek failed.
+ * IO WRITEERROR fwrite failed.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Wednesday, October 22, 1997
*
- * Modifications:
- * June 2, 1998 Albert Cheng
- * Added xfer_mode argument
- *
- * Ported to VFL/H5FD layer - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -875,26 +866,24 @@ H5FD_stdio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
size_t size, const void *buf)
{
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
- static const char *func="H5FD_stdio_write"; /* Function Name for error reporting */
+ static const char *func = "H5FD_stdio_write"; /* Function Name for error reporting */
- /* Shut compiler up */
- dxpl_id=dxpl_id;
- type=type;
+ /* Quiet the compiler */
+ dxpl_id = dxpl_id;
+ type = type;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
/* Check for overflow conditions */
- if (HADDR_UNDEF==addr)
+ if (HADDR_UNDEF == addr)
H5Epush_ret (func, H5E_ERR_CLS, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1)
if (REGION_OVERFLOW(addr, size))
H5Epush_ret (func, H5E_ERR_CLS, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1)
- if (addr+size>file->eoa)
+ if (addr+size > file->eoa)
H5Epush_ret (func, H5E_ERR_CLS, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1)
- /*
- * Seek to the correct file position.
- */
+ /* Seek to the correct file position. */
if ((file->op != H5FD_STDIO_OP_WRITE && file->op != H5FD_STDIO_OP_SEEK) ||
file->pos != addr) {
if (file_fseek(file->fp, (file_offset_t)addr, SEEK_SET) < 0) {
@@ -905,33 +894,51 @@ H5FD_stdio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
file->pos = addr;
}
- /*
- * Write the buffer. On successful return, the file position will be
- * advanced by the number of bytes read. Otherwise nobody knows where it
- * is.
+ /* Write the buffer. On successful return, the file position will be
+ * advanced by the number of bytes read. On failure, the file position is
+ * undefined.
*/
- if(size != fwrite(buf, (size_t)1, size, file->fp)) {
- file->op = H5FD_STDIO_OP_UNKNOWN;
- file->pos = HADDR_UNDEF;
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fwrite failed", -1)
+ while(size > 0) {
+
+ size_t bytes_in = 0; /* # of bytes to write */
+ size_t bytes_wrote = 0; /* # of bytes written */
+ size_t item_size = 1; /* size of items in bytes */
+
+ if(size > H5_STDIO_MAX_IO_BYTES_g)
+ bytes_in = H5_STDIO_MAX_IO_BYTES_g;
+ else
+ bytes_in = size;
+
+ bytes_wrote = fwrite(buf, item_size, bytes_in, file->fp);
+
+ if(bytes_wrote != bytes_in || (0 == bytes_wrote && ferror(file->fp))) { /* error */
+ file->op = H5FD_STDIO_OP_UNKNOWN;
+ file->pos = HADDR_UNDEF;
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fwrite failed", -1)
+ } /* end if */
+
+ assert(bytes_wrote > 0);
+ assert((size_t)bytes_wrote <= size);
+
+ size -= bytes_wrote;
+ addr += (haddr_t)bytes_wrote;
+ buf = (const char *)buf + bytes_wrote;
}
- /*
- * Update seek optimizing data.
- */
+ /* Update seek optimizing data. */
file->op = H5FD_STDIO_OP_WRITE;
- file->pos = addr + size;
+ file->pos = addr;
/* Update EOF if necessary */
- if (file->pos>file->eof)
+ if (file->pos > file->eof)
file->eof = file->pos;
- return(0);
+ return 0;
}
/*-------------------------------------------------------------------------
- * Function: H5F_stdio_flush
+ * Function: H5FD_stdio_flush
*
* Purpose: Makes sure that all data is on disk.
*
@@ -952,7 +959,7 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
static const char *func = "H5FD_stdio_flush"; /* Function Name for error reporting */
- /* Shut compiler up */
+ /* Quiet the compiler */
dxpl_id = dxpl_id;
/* Clear the error stack */
@@ -960,7 +967,6 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
/* Only try to flush the file if we have write access */
if(file->write_access) {
- /* Flush */
if(!closing) {
if(fflush(file->fp) < 0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fflush failed", -1)
@@ -971,12 +977,12 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
} /* end if */
} /* end if */
- return(0);
+ return 0;
} /* end H5FD_stdio_flush() */
/*-------------------------------------------------------------------------
- * Function: H5F_stdio_truncate
+ * Function: H5FD_stdio_truncate
*
* Purpose: Makes sure that the true file size is the same (or larger)
* than the end-of-address.
@@ -990,9 +996,6 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
* Programmer: Quincey Koziol
* Thursday, January 31, 2008
*
- * Modifications:
- * Vailin Choi; June 2010
- * Fix for window failures manifested from tests in mf.c.
*-------------------------------------------------------------------------
*/
static herr_t
@@ -1001,7 +1004,7 @@ H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
static const char *func = "H5FD_stdio_truncate"; /* Function Name for error reporting */
- /* Shut compiler up */
+ /* Quiet the compiler */
dxpl_id = dxpl_id;
closing = closing;
@@ -1012,30 +1015,42 @@ H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
if(file->write_access) {
/* Makes sure that the true file size is the same as the end-of-address. */
if(file->eoa != file->eof) {
- int fd = fileno(file->fp); /* File descriptor for HDF5 file */
#ifdef H5_HAVE_WIN32_API
- HFILE filehandle; /* Windows file handle */
- LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */
+ 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 */
- /* Reset seek offset to beginning of file, so that file isn't re-extended later */
+ /* Reset seek offset to beginning of file, so that file isn't re-extended later */
rewind(file->fp);
- /* Map the posix file handle to a Windows file handle */
- filehandle = _get_osfhandle(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)
+ /* 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 )
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_FILEOPEN, "unable to set file pointer", -1)
+ }
+
+ bError = SetEndOfFile(file->hFile);
+ if(0 == bError)
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1)
#else /* H5_HAVE_WIN32_API */
/* Reset seek offset to beginning of file, so that file isn't re-extended later */
rewind(file->fp);
/* Truncate file to proper length */
- if(-1 == file_ftruncate(fd, (file_offset_t)file->eoa))
+ if(-1 == file_ftruncate(file->fd, (file_offset_t)file->eoa))
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1)
#endif /* H5_HAVE_WIN32_API */
@@ -1050,10 +1065,10 @@ H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
else {
/* Double-check for problems */
if(file->eoa > file->eof)
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_TRUNCATED, "eoa>eof!", -1)
- } /* end else */
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_TRUNCATED, "eoa > eof!", -1)
+ } /* end else */
- return(0);
+ return 0;
} /* end H5FD_stdio_truncate() */