1999-10-21 01:51:03 +08:00
|
|
|
|
/*
|
|
|
|
|
* Copyright <EFBFBD> 1999 NCSA
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Programmer: Robb Matzke <matzke@llnl.gov>
|
|
|
|
|
* Wednesday, October 22, 1997
|
|
|
|
|
*
|
|
|
|
|
* Purpose: This is the Posix stdio.h I/O subclass of H5Flow.
|
|
|
|
|
*
|
|
|
|
|
* Notes: Ported to the new H5FD architecture on 10/18/99 - QAK
|
|
|
|
|
*
|
|
|
|
|
*/
|
1999-11-01 23:21:16 +08:00
|
|
|
|
#include <hdf5.h>
|
1999-10-21 01:51:03 +08:00
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <sys/stat.h>
|
1999-10-29 23:57:26 +08:00
|
|
|
|
|
1999-11-17 03:08:14 +08:00
|
|
|
|
#ifdef H5_HAVE_UNISTD_H
|
1999-10-21 01:51:03 +08:00
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WIN32
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef MAX
|
|
|
|
|
#undef MAX
|
|
|
|
|
#endif /* MAX */
|
|
|
|
|
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
|
1999-10-29 23:57:26 +08:00
|
|
|
|
#ifndef F_OK
|
|
|
|
|
#define F_OK 00
|
|
|
|
|
#define W_OK 02
|
|
|
|
|
#define R_OK 04
|
1999-10-21 01:51:03 +08:00
|
|
|
|
|
1999-10-29 23:57:26 +08:00
|
|
|
|
#endif
|
1999-10-21 01:51:03 +08:00
|
|
|
|
/* The driver identification number, initialized at runtime */
|
|
|
|
|
static hid_t H5FD_STDIO_g = 0;
|
|
|
|
|
|
|
|
|
|
/* File operations */
|
|
|
|
|
typedef enum {
|
|
|
|
|
H5FD_STDIO_OP_UNKNOWN=0,
|
|
|
|
|
H5FD_STDIO_OP_READ=1,
|
|
|
|
|
H5FD_STDIO_OP_WRITE=2,
|
|
|
|
|
H5FD_STDIO_OP_SEEK=3
|
|
|
|
|
} H5FD_stdio_file_op;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
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 */
|
|
|
|
|
#ifndef WIN32
|
|
|
|
|
/*
|
|
|
|
|
* On most systems the combination of device and i-node number uniquely
|
|
|
|
|
* identify a file.
|
|
|
|
|
*/
|
|
|
|
|
dev_t device; /*file device number */
|
|
|
|
|
ino_t inode; /*file i-node number */
|
|
|
|
|
#else
|
|
|
|
|
/*
|
|
|
|
|
* On WIN32 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.
|
|
|
|
|
*/
|
|
|
|
|
int fileindexlo;
|
|
|
|
|
int fileindexhi;
|
|
|
|
|
#endif
|
|
|
|
|
} H5FD_stdio_t;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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'
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* 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(long)-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) || \
|
|
|
|
|
sizeof(long)<sizeof(size_t) || HADDR_UNDEF==(A)+(Z) || (long)((A)+(Z))<(long)(A))
|
|
|
|
|
|
|
|
|
|
/* Prototypes */
|
|
|
|
|
static H5FD_t *H5FD_stdio_open(const char *name, unsigned flags,
|
|
|
|
|
hid_t fapl_id, haddr_t maxaddr);
|
|
|
|
|
static herr_t H5FD_stdio_close(H5FD_t *lf);
|
|
|
|
|
static int H5FD_stdio_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
|
2000-09-01 03:33:58 +08:00
|
|
|
|
static herr_t H5FD_stdio_query(const H5FD_t *_f1, unsigned long *flags);
|
1999-10-21 01:51:03 +08:00
|
|
|
|
static haddr_t H5FD_stdio_get_eoa(H5FD_t *_file);
|
|
|
|
|
static herr_t H5FD_stdio_set_eoa(H5FD_t *_file, haddr_t addr);
|
|
|
|
|
static haddr_t H5FD_stdio_get_eof(H5FD_t *_file);
|
|
|
|
|
static herr_t H5FD_stdio_read(H5FD_t *lf, hid_t fapl_id, haddr_t addr,
|
|
|
|
|
hsize_t size, void *buf);
|
2000-09-01 03:33:58 +08:00
|
|
|
|
static herr_t H5FD_stdio_write(H5FD_t *lf, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
|
1999-10-21 01:51:03 +08:00
|
|
|
|
hsize_t size, const void *buf);
|
|
|
|
|
static herr_t H5FD_stdio_flush(H5FD_t *_file);
|
|
|
|
|
|
|
|
|
|
static const H5FD_class_t H5FD_stdio_g = {
|
|
|
|
|
"stdio", /*name */
|
|
|
|
|
MAXADDR, /*maxaddr */
|
|
|
|
|
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 */
|
2000-09-01 03:33:58 +08:00
|
|
|
|
H5FD_stdio_query, /*query */
|
1999-10-21 01:51:03 +08:00
|
|
|
|
NULL, /*alloc */
|
|
|
|
|
NULL, /*free */
|
|
|
|
|
H5FD_stdio_get_eoa, /*get_eoa */
|
|
|
|
|
H5FD_stdio_set_eoa, /*set_eoa */
|
|
|
|
|
H5FD_stdio_get_eof, /*get_eof */
|
|
|
|
|
H5FD_stdio_read, /*read */
|
|
|
|
|
H5FD_stdio_write, /*write */
|
|
|
|
|
H5FD_stdio_flush, /*flush */
|
|
|
|
|
H5FD_FLMAP_SINGLE, /*fl_map */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5FD_stdio_init
|
|
|
|
|
*
|
|
|
|
|
* Purpose: Initialize this driver by registering the driver with the
|
|
|
|
|
* library.
|
|
|
|
|
*
|
|
|
|
|
* Return: Success: The driver ID for the stdio driver.
|
|
|
|
|
*
|
|
|
|
|
* Failure: Negative.
|
|
|
|
|
*
|
|
|
|
|
* Programmer: Robb Matzke
|
|
|
|
|
* Thursday, July 29, 1999
|
|
|
|
|
*
|
|
|
|
|
* Modifications:
|
|
|
|
|
* Stolen from the sec2 driver - QAK, 10/18/99
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
hid_t
|
|
|
|
|
H5FD_stdio_init(void)
|
|
|
|
|
{
|
1999-10-23 08:36:04 +08:00
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
if (H5I_VFL!=H5Iget_type(H5FD_STDIO_g))
|
|
|
|
|
H5FD_STDIO_g = H5FDregister(&H5FD_stdio_g);
|
|
|
|
|
return(H5FD_STDIO_g);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5Pset_fapl_stdio
|
|
|
|
|
*
|
|
|
|
|
* Purpose: Modify the file access property list to use the H5FD_STDIO
|
|
|
|
|
* driver defined in this source file. There are no driver
|
|
|
|
|
* specific properties.
|
|
|
|
|
*
|
|
|
|
|
* Return: Non-negative on success/Negative on failure
|
|
|
|
|
*
|
|
|
|
|
* 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)
|
|
|
|
|
{
|
1999-11-01 23:21:16 +08:00
|
|
|
|
static const char *func="H5FDset_fapl_stdio"; /*for error reporting*/
|
|
|
|
|
|
|
|
|
|
/*NO TRACE*/
|
1999-10-23 08:36:04 +08:00
|
|
|
|
|
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-11-01 23:21:16 +08:00
|
|
|
|
if (H5P_FILE_ACCESS!=H5Pget_class(fapl_id)) {
|
|
|
|
|
H5Epush_ret(func, H5E_PLIST, H5E_BADTYPE,
|
|
|
|
|
"not a file access property list", -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return H5Pset_driver(fapl_id, H5FD_STDIO, NULL);
|
1999-10-21 01:51:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5FD_stdio_open
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
* 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 */
|
|
|
|
|
#ifdef WIN32
|
|
|
|
|
HFILE filehandle;
|
|
|
|
|
struct _BY_HANDLE_FILE_INFORMATION fileinfo;
|
|
|
|
|
int results;
|
|
|
|
|
#else /* WIN32 */
|
|
|
|
|
struct stat sb;
|
|
|
|
|
#endif /* WIN32 */
|
|
|
|
|
|
|
|
|
|
/* Shut compiler up */
|
|
|
|
|
fapl_id=fapl_id;
|
|
|
|
|
|
1999-10-23 08:36:04 +08:00
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
/* Check arguments */
|
1999-10-23 08:36:04 +08:00
|
|
|
|
if (!name || !*name)
|
|
|
|
|
H5Epush_ret(func, H5E_ARGS, H5E_BADVALUE, "invalid file name", NULL);
|
|
|
|
|
if (0==maxaddr || HADDR_UNDEF==maxaddr)
|
|
|
|
|
H5Epush_ret(func, H5E_ARGS, H5E_BADRANGE, "bogus maxaddr", NULL);
|
|
|
|
|
if (ADDR_OVERFLOW(maxaddr))
|
|
|
|
|
H5Epush_ret(func, H5E_ARGS, H5E_OVERFLOW, "maxaddr too large", NULL);
|
1999-10-21 01:51:03 +08:00
|
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
} else {
|
1999-10-23 08:36:04 +08:00
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_CANTOPENFILE, "file doesn't exist and CREAT wasn't specified", NULL);
|
1999-10-21 01:51:03 +08:00
|
|
|
|
}
|
|
|
|
|
} else if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_EXCL)) {
|
1999-10-23 08:36:04 +08:00
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_FILEEXISTS, "file exists but CREAT and EXCL were specified", NULL);
|
1999-10-21 01:51:03 +08:00
|
|
|
|
} else if (flags & H5F_ACC_RDWR) {
|
|
|
|
|
if (flags & H5F_ACC_TRUNC)
|
|
|
|
|
f = fopen(name, "wb+");
|
|
|
|
|
else
|
|
|
|
|
f = fopen(name, "rb+");
|
|
|
|
|
write_access=1; /* Note the write access */
|
|
|
|
|
} else {
|
|
|
|
|
f = fopen(name, "rb");
|
|
|
|
|
}
|
|
|
|
|
if (!f)
|
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_CANTOPENFILE, "fopen failed", NULL);
|
|
|
|
|
|
|
|
|
|
/* Build the return value */
|
1999-10-23 08:36:04 +08:00
|
|
|
|
if (NULL==(file = calloc(1,sizeof(H5FD_stdio_t))))
|
|
|
|
|
H5Epush_ret(func, H5E_RESOURCE, H5E_NOSPACE, "memory allocation failed", NULL);
|
1999-10-21 01:51:03 +08:00
|
|
|
|
file->fp = f;
|
|
|
|
|
file->op = H5FD_STDIO_OP_SEEK;
|
|
|
|
|
file->pos = HADDR_UNDEF;
|
|
|
|
|
file->write_access=write_access; /* Note the write_access for later */
|
|
|
|
|
if (fseek(file->fp, 0, SEEK_END) < 0) {
|
|
|
|
|
file->op = H5FD_STDIO_OP_UNKNOWN;
|
|
|
|
|
} else {
|
|
|
|
|
long x = ftell (file->fp);
|
|
|
|
|
assert (x>=0);
|
|
|
|
|
file->eof = x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The unique key */
|
|
|
|
|
#ifdef WIN32
|
1999-10-28 03:04:23 +08:00
|
|
|
|
//#error "Needs correct fileindexhi & fileindexlo, code below is from sec2 driver"
|
|
|
|
|
filehandle = _get_osfhandle(f);
|
1999-10-21 01:51:03 +08:00
|
|
|
|
results = GetFileInformationByHandle(filehandle, &fileinfo);
|
|
|
|
|
file->fileindexhi = fileinfo.nFileIndexHigh;
|
|
|
|
|
file->fileindexlo = fileinfo.nFileIndexLow;
|
|
|
|
|
#else
|
|
|
|
|
fstat(fileno(file->fp), &sb);
|
|
|
|
|
file->device = sb.st_dev;
|
|
|
|
|
file->inode = sb.st_ino;
|
|
|
|
|
#endif
|
|
|
|
|
return((H5FD_t*)file);
|
|
|
|
|
} /* end H5FD_stdio_open() */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5F_stdio_close
|
|
|
|
|
*
|
|
|
|
|
* Purpose: Closes a file.
|
|
|
|
|
*
|
|
|
|
|
* Errors:
|
|
|
|
|
* IO CLOSEERROR Fclose failed.
|
|
|
|
|
*
|
|
|
|
|
* Return: Non-negative on success/Negative on failure
|
|
|
|
|
*
|
|
|
|
|
* 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 */
|
|
|
|
|
|
1999-10-23 08:36:04 +08:00
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
if (H5FD_stdio_flush(_file)<0)
|
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_WRITEERROR, "flush failed", -1);
|
|
|
|
|
if (fclose(file->fp) < 0)
|
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_CLOSEERROR, "fclose failed", -1);
|
|
|
|
|
|
|
|
|
|
free(file);
|
|
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5FD_stdio_cmp
|
|
|
|
|
*
|
|
|
|
|
* 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).
|
|
|
|
|
*
|
|
|
|
|
* Programmer: Robb Matzke
|
|
|
|
|
* Thursday, July 29, 1999
|
|
|
|
|
*
|
|
|
|
|
* Modifications:
|
|
|
|
|
* Stolen from the sec2 driver - QAK, 10/18/99
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static int
|
|
|
|
|
H5FD_stdio_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
|
|
|
|
|
{
|
|
|
|
|
const H5FD_stdio_t *f1 = (const H5FD_stdio_t*)_f1;
|
|
|
|
|
const H5FD_stdio_t *f2 = (const H5FD_stdio_t*)_f2;
|
|
|
|
|
|
1999-10-23 08:36:04 +08:00
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
#ifdef WIN32
|
|
|
|
|
if (f1->fileindexhi < f2->fileindexhi) return -1;
|
|
|
|
|
if (f1->fileindexhi > f2->fileindexhi) return 1;
|
|
|
|
|
|
|
|
|
|
if (f1->fileindexlo < f2->fileindexlo) return -1;
|
|
|
|
|
if (f1->fileindexlo > f2->fileindexlo) return 1;
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
if (f1->device < f2->device) return -1;
|
|
|
|
|
if (f1->device > f2->device) return 1;
|
|
|
|
|
|
|
|
|
|
if (f1->inode < f2->inode) return -1;
|
|
|
|
|
if (f1->inode > f2->inode) return 1;
|
|
|
|
|
#endif
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-09-01 03:33:58 +08:00
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5FD_stdio_query
|
|
|
|
|
*
|
|
|
|
|
* Purpose: Set the flags that this VFL driver is capable of supporting.
|
|
|
|
|
* (listed in H5FDpublic.h)
|
|
|
|
|
*
|
|
|
|
|
* Return: Success: non-negative
|
|
|
|
|
*
|
|
|
|
|
* Failure: negative
|
|
|
|
|
*
|
|
|
|
|
* Programmer: Quincey Koziol
|
|
|
|
|
* Friday, August 25, 2000
|
|
|
|
|
*
|
|
|
|
|
* Modifications:
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static herr_t
|
|
|
|
|
H5FD_stdio_query(const H5FD_t *_f, unsigned long *flags /* out */)
|
|
|
|
|
{
|
2000-09-20 05:08:15 +08:00
|
|
|
|
/* Shut compiler up */
|
|
|
|
|
_f=_f;
|
2000-09-01 03:33:58 +08:00
|
|
|
|
|
|
|
|
|
/* Set the VFL feature flags that this driver supports */
|
|
|
|
|
if(flags) {
|
|
|
|
|
*flags|=H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
|
|
|
|
|
*flags|=H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */
|
2000-09-27 06:50:18 +08:00
|
|
|
|
*flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
|
2000-09-01 03:33:58 +08:00
|
|
|
|
} /* end if */
|
|
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* Return: Success: The end-of-address marker.
|
|
|
|
|
*
|
|
|
|
|
* Failure: HADDR_UNDEF
|
|
|
|
|
*
|
|
|
|
|
* Programmer: Robb Matzke
|
|
|
|
|
* Monday, August 2, 1999
|
|
|
|
|
*
|
|
|
|
|
* Modifications:
|
|
|
|
|
* Stolen from the sec2 driver - QAK, 10/18/99
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static haddr_t
|
|
|
|
|
H5FD_stdio_get_eoa(H5FD_t *_file)
|
|
|
|
|
{
|
|
|
|
|
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
|
|
|
|
|
|
1999-10-23 08:36:04 +08:00
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
return(file->eoa);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5FD_stdio_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.
|
|
|
|
|
*
|
|
|
|
|
* Return: Success: 0
|
|
|
|
|
*
|
|
|
|
|
* Failure: -1
|
|
|
|
|
*
|
|
|
|
|
* Programmer: Robb Matzke
|
|
|
|
|
* Thursday, July 29, 1999
|
|
|
|
|
*
|
|
|
|
|
* Modifications:
|
|
|
|
|
* Stolen from the sec2 driver - QAK, 10/18/99
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static herr_t
|
|
|
|
|
H5FD_stdio_set_eoa(H5FD_t *_file, haddr_t addr)
|
|
|
|
|
{
|
|
|
|
|
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
|
|
|
|
|
|
1999-10-23 08:36:04 +08:00
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
file->eoa = addr;
|
|
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5FD_stdio_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.
|
|
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*
|
|
|
|
|
* Programmer: Robb Matzke
|
|
|
|
|
* Thursday, July 29, 1999
|
|
|
|
|
*
|
|
|
|
|
* Modifications:
|
|
|
|
|
* Stolen from the sec2 driver - QAK, 10/18/99
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static haddr_t
|
|
|
|
|
H5FD_stdio_get_eof(H5FD_t *_file)
|
|
|
|
|
{
|
|
|
|
|
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
|
|
|
|
|
|
1999-10-23 08:36:04 +08:00
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
return(MAX(file->eof, file->eoa));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5F_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.
|
|
|
|
|
*
|
|
|
|
|
* 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, hid_t dxpl_id, haddr_t addr, hsize_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 */
|
|
|
|
|
|
|
|
|
|
/* Shut compiler up */
|
|
|
|
|
dxpl_id=dxpl_id;
|
|
|
|
|
|
1999-10-23 08:36:04 +08:00
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
/* Check for overflow */
|
|
|
|
|
if (HADDR_UNDEF==addr)
|
|
|
|
|
H5Epush_ret (func, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1);
|
|
|
|
|
if (REGION_OVERFLOW(addr, size))
|
|
|
|
|
H5Epush_ret (func, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1);
|
|
|
|
|
if (addr+size>file->eoa)
|
|
|
|
|
H5Epush_ret (func, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1);
|
|
|
|
|
|
|
|
|
|
/* Check easy cases */
|
|
|
|
|
if (0 == size)
|
|
|
|
|
return(0);
|
1999-10-29 23:57:26 +08:00
|
|
|
|
if ((haddr_t)addr >= file->eof) {
|
1999-10-21 01:51:03 +08:00
|
|
|
|
memset(buf, 0, size);
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Seek to the correct file position.
|
|
|
|
|
*/
|
|
|
|
|
if (!(file->op == H5FD_STDIO_OP_READ || file->op==H5FD_STDIO_OP_SEEK) ||
|
|
|
|
|
file->pos != addr) {
|
1999-11-18 05:59:53 +08:00
|
|
|
|
if (fseek(file->fp, (long)addr, SEEK_SET) < 0) {
|
1999-10-21 01:51:03 +08:00
|
|
|
|
file->op = H5FD_STDIO_OP_UNKNOWN;
|
|
|
|
|
file->pos = HADDR_UNDEF;
|
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_SEEKERROR, "fseek failed", -1);
|
|
|
|
|
}
|
|
|
|
|
file->pos = addr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Read zeros past the logical end of file (physical is handled below)
|
|
|
|
|
*/
|
|
|
|
|
if ((size_t) 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
|
|
|
|
|
* will advance the file position by N. If N is negative or an error
|
|
|
|
|
* occurs then the file position is undefined.
|
|
|
|
|
*/
|
|
|
|
|
n = fread(buf, 1, size, file->fp);
|
|
|
|
|
if (n <= 0 && ferror(file->fp)) {
|
|
|
|
|
file->op = H5FD_STDIO_OP_UNKNOWN;
|
|
|
|
|
file->pos = HADDR_UNDEF;
|
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_READERROR, "fread failed", -1);
|
|
|
|
|
} else if (n < size) {
|
|
|
|
|
memset((unsigned char *)buf + n, 0, size - n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Update the file position data.
|
|
|
|
|
*/
|
|
|
|
|
file->op = H5FD_STDIO_OP_READ;
|
|
|
|
|
file->pos = addr+n; /*checked for overflow above*/
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5F_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.
|
|
|
|
|
*
|
|
|
|
|
* 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
|
2000-09-01 03:33:58 +08:00
|
|
|
|
H5FD_stdio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
|
1999-10-21 01:51:03 +08:00
|
|
|
|
hsize_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 */
|
|
|
|
|
|
|
|
|
|
/* Shut compiler up */
|
|
|
|
|
dxpl_id=dxpl_id;
|
2000-09-20 05:08:15 +08:00
|
|
|
|
type=type;
|
1999-10-21 01:51:03 +08:00
|
|
|
|
|
1999-10-23 08:36:04 +08:00
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
/* Check for overflow conditions */
|
|
|
|
|
if (HADDR_UNDEF==addr)
|
|
|
|
|
H5Epush_ret (func, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1);
|
|
|
|
|
if (REGION_OVERFLOW(addr, size))
|
|
|
|
|
H5Epush_ret (func, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1);
|
|
|
|
|
if (addr+size>file->eoa)
|
|
|
|
|
H5Epush_ret (func, H5E_IO, H5E_OVERFLOW, "file address overflowed", -1);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Seek to the correct file position.
|
|
|
|
|
*/
|
|
|
|
|
if (!(file->op == H5FD_STDIO_OP_WRITE || file->op==H5FD_STDIO_OP_SEEK) ||
|
|
|
|
|
file->pos != addr) {
|
1999-11-18 05:59:53 +08:00
|
|
|
|
if (fseek(file->fp, (long)addr, SEEK_SET) < 0) {
|
1999-10-21 01:51:03 +08:00
|
|
|
|
file->op = H5FD_STDIO_OP_UNKNOWN;
|
|
|
|
|
file->pos = HADDR_UNDEF;
|
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_SEEKERROR, "fseek failed", -1);
|
|
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
if (size != fwrite(buf, 1, size, file->fp)) {
|
|
|
|
|
file->op = H5FD_STDIO_OP_UNKNOWN;
|
|
|
|
|
file->pos = HADDR_UNDEF;
|
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_WRITEERROR, "fwrite failed", -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Update seek optimizing data.
|
|
|
|
|
*/
|
|
|
|
|
file->op = H5FD_STDIO_OP_WRITE;
|
|
|
|
|
file->pos = addr + size;
|
|
|
|
|
|
|
|
|
|
/* Update EOF if necessary */
|
|
|
|
|
if (file->pos>file->eof)
|
|
|
|
|
file->eof = file->pos;
|
|
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
* Function: H5F_stdio_flush
|
|
|
|
|
*
|
|
|
|
|
* Purpose: Makes sure that all data is on disk.
|
|
|
|
|
*
|
|
|
|
|
* Errors:
|
|
|
|
|
* IO SEEKERROR fseek failed.
|
|
|
|
|
* IO WRITEERROR fflush or fwrite failed.
|
|
|
|
|
*
|
|
|
|
|
* Return: Non-negative on success/Negative on failure
|
|
|
|
|
*
|
|
|
|
|
* Programmer: Robb Matzke
|
|
|
|
|
* Wednesday, October 22, 1997
|
|
|
|
|
*
|
|
|
|
|
* Modifications:
|
|
|
|
|
* Ported to VFL/H5FD layer - QAK, 10/18/99
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
static herr_t
|
|
|
|
|
H5FD_stdio_flush(H5FD_t *_file)
|
|
|
|
|
{
|
|
|
|
|
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
|
|
|
|
|
static const char *func="H5FD_stdio_flush"; /* Function Name for error reporting */
|
|
|
|
|
|
1999-10-23 08:36:04 +08:00
|
|
|
|
/* Clear the error stack */
|
|
|
|
|
H5Eclear();
|
|
|
|
|
|
1999-10-21 01:51:03 +08:00
|
|
|
|
/* Only try to flush the file if we have write access */
|
|
|
|
|
if(file->write_access) {
|
|
|
|
|
/* Makes sure that the true file size is the same (or larger) than the end-of-address. */
|
|
|
|
|
if (file->eoa>file->eof) {
|
1999-11-18 05:59:53 +08:00
|
|
|
|
if (fseek(file->fp, (long)(file->eoa-1), SEEK_SET)<0)
|
1999-10-21 01:51:03 +08:00
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_SEEKERROR, "fseek failed", -1);
|
|
|
|
|
if (fwrite("", 1, 1, file->fp)!=1)
|
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_SEEKERROR, "EOF fwrite failed", -1);
|
|
|
|
|
file->eof = file->eoa;
|
|
|
|
|
file->pos = file->eoa;
|
|
|
|
|
/* fall through to set the IO operation */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* What happens to the file position? Is it guaranteed to be the same
|
|
|
|
|
* after the fflush() as it was before?
|
|
|
|
|
*/
|
|
|
|
|
file->op = H5FD_STDIO_OP_UNKNOWN;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Flush
|
|
|
|
|
*/
|
|
|
|
|
if (fflush(file->fp) < 0)
|
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_WRITEERROR, "fflush failed", -1);
|
|
|
|
|
} /* end if */
|
|
|
|
|
else {
|
|
|
|
|
/* Double-check for problems */
|
|
|
|
|
if (file->eoa>file->eof)
|
|
|
|
|
H5Epush_ret(func, H5E_IO, H5E_TRUNCATED, "eoa>eof!", -1);
|
|
|
|
|
} /* end else */
|
|
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
|
}
|