hdf5/src/H5Fsec2.c
Robb Matzke 4bf629adc9 [svn-r435] ./INSTALL
./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.
1998-06-22 22:41:22 -05:00

333 lines
9.0 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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);
}