mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-02-11 16:01:00 +08:00
./INSTALL_MAINT ./README ./RELEASE Partially updated for second alpha, but haven't updated version numbers yet. ./src/H5.c ./src/H5A.c ./src/H5AC.c ./src/H5B.c ./src/H5D.c ./src/H5F.c ./src/H5Fcore.c ./src/H5Ffamily.c ./src/H5Fistore.c ./src/H5Fmpio.c ./src/H5Fsec2.c ./src/H5Fsplit.c ./src/H5Fstdio.c ./src/H5G.c ./src/H5Gnode.c ./src/H5HG.c ./src/H5HL.c ./src/H5I.c ./src/H5MM.c ./src/H5MMprivate.h ./src/H5O.c ./src/H5Oattr.c ./src/H5Ocomp.c ./src/H5Ocont.c ./src/H5Odtype.c ./src/H5Oefl.c ./src/H5Olayout.c ./src/H5Oname.c ./src/H5Osdspace.c ./src/H5Oshared.c ./src/H5Ostab.c ./src/H5P.c ./src/H5S.c ./src/H5T.c ./src/H5Tconv.c ./src/H5detect.c ./test/hyperslab.c ./test/istore.c Changed memory allocation functions so they fail instead of dumping core. The `x' was removed from the name to remind us of that: H5MM_xmalloc() -> H5MM_malloc(), etc. H5MM_calloc() takes one argument like H5MM_malloc() instead of two like calloc() because we almost always called it with `1' for one of the arguments anyway. The only difference between the two functions is that H5MM_calloc() returns memory which is initialized to zero. ./src/H5Gent.c ./src/H5Gprivate.h Removed H5G_ent_calloc() since it wasn't used. ./src/H5Fistore.c Fixed a bug found by Albert. Thanks, Albert! This fix combined with the changes to memory allocation prevent the library from failing an assertion if the application uses an unreasonable size for chunks (like Alberts 10000x10000x4). ./src/H5MF.c ./src/H5MFprivate.h Changed H5MF_free() to H5MF_xfree() since calling it with an undefined address is allowed.
333 lines
9.0 KiB
C
333 lines
9.0 KiB
C
/*
|
||
* Copyright (C) 1997 NCSA
|
||
* All rights reserved.
|
||
*
|
||
* Programmer: Robb Matzke <matzke@llnl.gov>
|
||
* Wednesday, October 22, 1997
|
||
*
|
||
* Purpose: This is the Posix section-2 I/O subclass of H5Flow.
|
||
*
|
||
* Notes: This driver keeps track of its own file position in order to
|
||
* minimize the number of calls to lseek(). We assume that
|
||
* opening a file sets the current file position to the beginning
|
||
* and that read() and write() modify the file position as
|
||
* expected when they return successfully (unsuccessful return
|
||
* leaves the file position undefined).
|
||
*/
|
||
#include <H5private.h>
|
||
#include <H5Eprivate.h>
|
||
#include <H5Fprivate.h>
|
||
#include <H5MMprivate.h>
|
||
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
|
||
#define PABLO_MASK H5F_sec2
|
||
static hbool_t interface_initialize_g = FALSE;
|
||
#define INTERFACE_INIT NULL
|
||
|
||
static H5F_low_t *H5F_sec2_open(const char *name,
|
||
const H5F_access_t *access_parms, uintn flags,
|
||
H5F_search_t *key/*out*/);
|
||
static herr_t H5F_sec2_close(H5F_low_t *lf, const H5F_access_t *access_parms);
|
||
static herr_t H5F_sec2_read(H5F_low_t *lf, const H5F_access_t *access_parms,
|
||
const H5D_transfer_t xfer_mode,
|
||
const haddr_t *addr, size_t size,
|
||
uint8 *buf/*out*/);
|
||
static herr_t H5F_sec2_write(H5F_low_t *lf, const H5F_access_t *access_parms,
|
||
const H5D_transfer_t xfer_mode,
|
||
const haddr_t *addr, size_t size,
|
||
const uint8 *buf);
|
||
|
||
const H5F_low_class_t H5F_LOW_SEC2_g[1] = {{
|
||
NULL, /* access method */
|
||
H5F_sec2_open, /* open method */
|
||
H5F_sec2_close, /* close method */
|
||
H5F_sec2_read, /* read method */
|
||
H5F_sec2_write, /* write method */
|
||
NULL, /* flush method */
|
||
NULL, /* extend method */
|
||
NULL, /* alloc method */
|
||
}};
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_sec2_open
|
||
*
|
||
* Purpose: Opens a file with name NAME. The FLAGS are a bit field with
|
||
* the possible values defined in H5F_low_open().
|
||
*
|
||
* Errors:
|
||
* IO CANTOPENFILE Open failed.
|
||
*
|
||
* Return: Success: Low-level file pointer
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Wednesday, October 22, 1997
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5F_low_t *
|
||
H5F_sec2_open(const char *name, const H5F_access_t __unused__ *access_parms,
|
||
uintn flags, H5F_search_t *key/*out*/)
|
||
{
|
||
intn oflags;
|
||
H5F_low_t *lf = NULL;
|
||
int fd;
|
||
struct stat sb;
|
||
|
||
FUNC_ENTER(H5F_sec2_open, NULL);
|
||
|
||
oflags = (flags & H5F_ACC_RDWR) ? O_RDWR : O_RDONLY;
|
||
oflags |= (flags & H5F_ACC_CREAT) ? O_CREAT : 0;
|
||
oflags |= (flags & H5F_ACC_EXCL) ? O_EXCL : 0;
|
||
oflags |= (flags & H5F_ACC_TRUNC) ? O_TRUNC : 0;
|
||
|
||
if ((fd = open(name, oflags, 0666)) < 0) {
|
||
HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "open failed");
|
||
}
|
||
if (NULL==(lf = H5MM_calloc(sizeof(H5F_low_t)))) {
|
||
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL,
|
||
"memory allocation failed");
|
||
}
|
||
lf->u.sec2.fd = fd;
|
||
lf->u.sec2.op = H5F_OP_SEEK;
|
||
lf->u.sec2.cur = 0;
|
||
fstat(fd, &sb);
|
||
lf->eof.offset = sb.st_size;
|
||
|
||
if (key) {
|
||
key->dev = sb.st_dev;
|
||
key->ino = sb.st_ino;
|
||
}
|
||
FUNC_LEAVE(lf);
|
||
}
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_sec2_close
|
||
*
|
||
* Purpose: Closes a file.
|
||
*
|
||
* Errors:
|
||
* IO CLOSEERROR Close failed.
|
||
*
|
||
* Return: Success: SUCCEED
|
||
*
|
||
* Failure: FAIL
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Wednesday, October 22, 1997
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_sec2_close(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms)
|
||
{
|
||
FUNC_ENTER(H5F_sec2_close, FAIL);
|
||
|
||
if (close(lf->u.sec2.fd) < 0) {
|
||
HRETURN_ERROR(H5E_IO, H5E_CLOSEERROR, FAIL, "close failed");
|
||
}
|
||
lf->u.sec2.fd = -1;
|
||
|
||
FUNC_LEAVE(SUCCEED);
|
||
}
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_sec2_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 Read failed.
|
||
* IO SEEKERROR Lseek failed.
|
||
*
|
||
* Return: Success: SUCCEED
|
||
*
|
||
* Failure: FAIL
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Wednesday, October 22, 1997
|
||
*
|
||
* Modifications:
|
||
* June 2, 1998 Albert Cheng
|
||
* Added xfer_mode argument
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_sec2_read(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms,
|
||
const H5D_transfer_t __unused__ xfer_mode,
|
||
const haddr_t *addr, size_t size, uint8 *buf)
|
||
{
|
||
ssize_t n;
|
||
uint64 mask;
|
||
#ifdef HAVE_LSEEK64
|
||
off64_t offset;
|
||
#else
|
||
off_t offset;
|
||
#endif
|
||
|
||
FUNC_ENTER(H5F_sec2_read, FAIL);
|
||
|
||
/* Check for overflow */
|
||
mask = (uint64)1 << (8*sizeof(offset)-1);
|
||
if (addr->offset >= mask ||
|
||
addr->offset+size < addr->offset ||
|
||
addr->offset+size >= mask) {
|
||
HRETURN_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed");
|
||
}
|
||
#ifdef HAVE_LSEEK64
|
||
offset = (off64_t)(addr->offset); /*checked for overflow above*/
|
||
#else
|
||
offset = (off_t)(addr->offset); /*checked for overflow above*/
|
||
#endif
|
||
|
||
/* Check easy cases */
|
||
if (0 == size) HRETURN(SUCCEED);
|
||
if ((uint64)offset >= lf->eof.offset) {
|
||
HDmemset(buf, 0, size);
|
||
HRETURN(SUCCEED);
|
||
}
|
||
|
||
/*
|
||
* Optimize seeking. If that optimization is disabled then always call
|
||
* lseek().
|
||
*/
|
||
if (!H5F_OPT_SEEK ||
|
||
lf->u.sec2.op == H5F_OP_UNKNOWN ||
|
||
lf->u.sec2.cur != offset) {
|
||
#ifdef HAVE_LSEEK64
|
||
if (lseek64 (lf->u.sec2.fd, offset, SEEK_SET)<0) {
|
||
HRETURN_ERROR (H5E_IO, H5E_SEEKERROR, FAIL, "lseek64 failed");
|
||
}
|
||
#else
|
||
if (lseek(lf->u.sec2.fd, offset, SEEK_SET) < 0) {
|
||
HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "lseek failed");
|
||
}
|
||
#endif
|
||
lf->u.sec2.cur = offset;
|
||
}
|
||
|
||
/*
|
||
* Read zeros past the logical end of file (physical is handled below)
|
||
*/
|
||
if ((size_t) offset + size > lf->eof.offset) {
|
||
size_t nbytes = (size_t)offset + size - lf->eof.offset;
|
||
HDmemset(buf + size - nbytes, 0, nbytes);
|
||
size -= nbytes;
|
||
}
|
||
|
||
/*
|
||
* Read the data. If a read error occurs then set the last file operation
|
||
* to UNKNOWN because the file position isn't guaranteed by Posix.
|
||
*/
|
||
if ((n = read(lf->u.sec2.fd, buf, size)) < 0) {
|
||
lf->u.sec2.op = H5F_OP_UNKNOWN;
|
||
HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, "read failed");
|
||
} else if ((size_t)n < size) {
|
||
HDmemset(buf + n, 0, size - n);
|
||
}
|
||
|
||
/*
|
||
* Update the file position with the number of bytes actually read. This
|
||
* might be different than the number requested.
|
||
*/
|
||
lf->u.sec2.op = H5F_OP_READ;
|
||
lf->u.sec2.cur = offset + n;
|
||
|
||
FUNC_LEAVE(SUCCEED);
|
||
}
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_sec2_write
|
||
*
|
||
* Purpose: Writes SIZE bytes from the beginning of BUF into file LF at
|
||
* file address ADDR.
|
||
*
|
||
* Errors:
|
||
* IO SEEKERROR Lseek failed.
|
||
* IO WRITEERROR Write failed.
|
||
*
|
||
* Return: Success: SUCCEED
|
||
*
|
||
* Failure: FAIL
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Wednesday, October 22, 1997
|
||
*
|
||
* Modifications:
|
||
* June 2, 1998 Albert Cheng
|
||
* Added xfer_mode argument
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5F_sec2_write(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms,
|
||
const H5D_transfer_t __unused__ xfer_mode,
|
||
const haddr_t *addr, size_t size, const uint8 *buf)
|
||
{
|
||
uint64 mask;
|
||
ssize_t n;
|
||
#ifdef HAVE_LSEEK64
|
||
off64_t offset;
|
||
#else
|
||
off_t offset;
|
||
#endif
|
||
|
||
FUNC_ENTER(H5F_sec2_write, FAIL);
|
||
|
||
/* Check for overflow */
|
||
mask = (uint64)1 << (8*sizeof(offset)-1);
|
||
if (addr->offset >= mask ||
|
||
addr->offset+size < addr->offset ||
|
||
addr->offset+size >= mask) {
|
||
HRETURN_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed");
|
||
}
|
||
#ifdef HAVE_LSEEK64
|
||
offset = (off64_t)(addr->offset); /*checked for overflow*/
|
||
n = (off64_t)size; /*checked for overflow*/
|
||
#else
|
||
offset = (off_t)(addr->offset); /*checked for overflow*/
|
||
n = (off_t)size; /*checked for overflow*/
|
||
#endif
|
||
|
||
/*
|
||
* Optimize seeking. If that optimization is disabled then always call
|
||
* lseek().
|
||
*/
|
||
if (!H5F_OPT_SEEK ||
|
||
lf->u.sec2.op == H5F_OP_UNKNOWN ||
|
||
lf->u.sec2.cur != offset) {
|
||
if (lseek(lf->u.sec2.fd, offset, SEEK_SET) < 0) {
|
||
HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "lseek failed");
|
||
}
|
||
lf->u.sec2.cur = offset;
|
||
}
|
||
|
||
/*
|
||
* Write the data to the file. If the write failed then set the
|
||
* operation back to UNKNOWN since Posix doesn't gurantee its value.
|
||
*/
|
||
if (n != write(lf->u.sec2.fd, buf, size)) {
|
||
lf->u.sec2.op = H5F_OP_UNKNOWN;
|
||
HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write failed");
|
||
}
|
||
|
||
/*
|
||
* Update the file position.
|
||
*/
|
||
lf->u.sec2.op = H5F_OP_WRITE;
|
||
lf->u.sec2.cur = offset + n;
|
||
|
||
FUNC_LEAVE(SUCCEED);
|
||
}
|