/* Fortran-callable routines to read and write characther (bacio) and */
/* numeric (banio) data byte addressably */
/* Robert Grumbine 16 March 1998 */
/* v1.1: Put diagnostic output under control of define VERBOSE or QUIET */
/* Add option of non-seeking read/write */
/* Return code for fewer data read/written than requested */
/* v1.2: Add cray compatibility 20 April 1998 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <malloc.h>
#include <ctype.h>
#include <string.h>
/* Include the C library file for definition/control */
/* Things that might be changed for new systems are there. */
/* This source file should not (need to) be edited, merely recompiled */
#include "clib.h"
/* Return Codes: */
/* 0 All was well */
/* -1 Tried to open read only _and_ write only */
/* -2 Tried to read and write in the same call */
/* -3 Internal failure in name processing */
/* -4 Failure in opening file */
/* -5 Tried to read on a write-only file */
/* -6 Failed in read to find the 'start' location */
/* -7 Tried to write to a read only file */
/* -8 Failed in write to find the 'start' location */
/* -9 Error in close */
/* -10 Read or wrote fewer data than requested */
/* Note: In your Fortran code, call bacio, not bacio_. */
/*int bacio_(int * mode, int * start, int * size, int * no, int * nactual, */
/* int * fdes, const char *fname, char *data, int namelen, */
/* int datanamelen) */
/* Arguments: */
/* Mode is the integer specifying operations to be performed */
/* see the clib.inc file for the values. Mode is obtained */
/* by adding together the values corresponding to the operations */
/* The best method is to include the clib.inc file and refer to the */
/* names for the operations rather than rely on hard-coded values */
/* Start is the byte number to start your operation from. 0 is the first */
/* byte in the file, not 1. */
/* Newpos is the position in the file after a read or write has been */
/* performed. You'll need this if you're doing 'seeking' read/write */
/* Size is the size of the objects you are trying to read. Rely on the */
/* values in the locale.inc file. Types are CHARACTER, INTEGER, REAL, */
/* COMPLEX. Specify the correct value by using SIZEOF_type, where type */
/* is one of these. (After having included the locale.inc file) */
/* no is the number of things to read or write (characters, integers, */
/* whatever) */
/* nactual is the number of things actually read or written. Check that */
/* you got what you wanted. */
/* fdes is an integer 'file descriptor'. This is not a Fortran Unit Number */
/* You can use it, however, to refer to files you've previously opened. */
/* fname is the name of the file. This only needs to be defined when you */
/* are opening a file. It must be (on the Fortran side) declared as */
/* CHARACTER*N, where N is a length greater than or equal to the length */
/* of the file name. CHARACTER*1 fname[80] (for example) will fail. */
/* data is the name of the entity (variable, vector, array) that you want */
/* to write data out from or read it in to. The fact that C is declaring */
/* it to be a char * does not affect your fortran. */
/* namelen - Do NOT specify this. It is created automagically by the */
/* Fortran compiler */
/* datanamelen - Ditto */
/* What is going on here is that although the Fortran caller will always */
/* be calling bacio, the called C routine name will change from system */
/* to system. */
#ifdef CRAY90
#include <fortran.h>
int BACIO
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes,
_fcd fcd_fname, _fcd fcd_datary) {
char *fname, *datary;
int namelen;
#endif
#ifdef HP
int bacio
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, const char *fname, char *datary,
int namelen, int datanamelen) {
#endif
#ifdef SGI
int bacio_
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, const char *fname, char *datary,
int namelen, int datanamelen) {
#endif
#ifdef LINUX
int bacio_
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, const char *fname, char *datary,
int namelen, int datanamelen) {
#endif
#ifdef LINUXF90
int BACIO
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, const char *fname, char *datary,
int namelen, int datanamelen) {
#endif
#ifdef IBM4
int bacio
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, const char *fname, char *datary,
int namelen, int datanamelen) {
#endif
#ifdef IBM8
long long int bacio
(long long int * mode, long long int * start, long long int *newpos,
long long int * size, long long int * no,
long long int * nactual, long long int * fdes, const char *fname,
char *datary,
long long int namelen, long long int datanamelen) {
#endif
int i, j, jret, seekret;
char *realname, *tempchar;
int tcharval;
size_t count;
/* Initialization(s) */
*nactual = 0;
/* Check for illegal combinations of options */
if (( BAOPEN_RONLY & *mode) &&
( (BAOPEN_WONLY & *mode) || (BAOPEN_WONLY_TRUNC & *mode) || (BAOPEN_WONLY_APPEND & *mode) ) ) {
#ifdef VERBOSE
printf("illegal -- trying to open both read only and write only\n");
#endif
return -1;
}
if ( (BAREAD & *mode ) && (BAWRITE & *mode) ) {
#ifdef VERBOSE
printf("illegal -- trying to both read and write in the same call\n");
#endif
return -2;
}
/* This section handles Fortran to C translation of strings so as to */
/* be able to open the files Fortran is expecting to be opened. */
#ifdef CRAY90
namelen = _fcdlen(fcd_fname);
fname = _fcdtocp(fcd_fname);
#endif
if ( (BAOPEN_RONLY & *mode) || (BAOPEN_WONLY & *mode) ||
(BAOPEN_WONLY_TRUNC & *mode) || (BAOPEN_WONLY_APPEND & *mode) ||
(BAOPEN_RW & *mode) ) {
#ifdef VERBOSE
printf("Will be opening a file %s %d\n", fname, namelen); fflush(stdout);
printf("Strlen %d namelen %d\n", strlen(fname), namelen); fflush(stdout);
#endif
realname = (char *) malloc( namelen * sizeof(char) ) ;
if (realname == NULL) {
#ifdef VERBOSE
printf("failed to mallocate realname %d = namelen\n", namelen);
fflush(stdout);
#endif
return -3;
}
tempchar = (char *) malloc(sizeof(char) * 1 ) ;
i = 0;
j = 0;
*tempchar = fname[i];
tcharval = *tempchar;
while (i == j && i < namelen ) {
fflush(stdout);
if ( isgraph(tcharval) ) {
realname[j] = fname[i];
j += 1;
}
i += 1;
*tempchar = fname[i];
tcharval = *tempchar;
}
#ifdef VERBOSE
printf("i,j = %d %d\n",i,j); fflush(stdout);
#endif
realname[j] = '\0';
}
/* Open files with correct read/write and file permission. */
if (BAOPEN_RONLY & *mode) {
#ifdef VERBOSE
printf("open read only %s\n", realname);
#endif
*fdes = open(realname, O_RDONLY , S_IRWXU | S_IRWXG | S_IRWXO );
}
else if (BAOPEN_WONLY & *mode ) {
#ifdef VERBOSE
printf("open write only %s\n", realname);
#endif
*fdes = open(realname, O_WRONLY | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO );
}
else if (BAOPEN_WONLY_TRUNC & *mode ) {
#ifdef VERBOSE
printf("open write only with truncation %s\n", realname);
#endif
*fdes = open(realname, O_WRONLY | O_CREAT | O_TRUNC , S_IRWXU | S_IRWXG | S_IRWXO );
}
else if (BAOPEN_WONLY_APPEND & *mode ) {
#ifdef VERBOSE
printf("open write only with append %s\n", realname);
#endif
*fdes = open(realname, O_WRONLY | O_CREAT | O_APPEND , S_IRWXU | S_IRWXG | S_IRWXO );
}
else if (BAOPEN_RW & *mode) {
#ifdef VERBOSE
printf("open read-write %s\n", realname);
#endif
*fdes = open(realname, O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO );
}
else {
#ifdef VERBOSE
printf("no openings\n");
#endif
}
if (*fdes < 0) {
#ifdef VERBOSE
printf("error in file descriptor! *fdes %d\n", *fdes);
#endif
return -4;
}
else {
#ifdef VERBOSE
printf("file descriptor = %d\n",*fdes );
#endif
}
/* Read data as requested */
if (BAREAD & *mode &&
( (BAOPEN_WONLY & *mode) || (BAOPEN_WONLY_TRUNC & *mode) || (BAOPEN_WONLY_APPEND & *mode) ) ) {
#ifdef VERBOSE
printf("Error, trying to read while in write only mode!\n");
#endif
return -5;
}
else if (BAREAD & *mode ) {
/* Read in some data */
if (! (*mode & NOSEEK) ) {
seekret = lseek(*fdes, *start, SEEK_SET);
if (seekret == -1) {
#ifdef VERBOSE
printf("error in seeking to %d\n",*start);
#endif
return -6;
}
#ifdef VERBOSE
else {
printf("Seek successful, seek ret %d, start %d\n", seekret, *start);
}
#endif
}
#ifdef CRAY90
datary = _fcdtocp(fcd_datary);
#endif
if (datary == NULL) {
printf("Massive catastrophe -- datary pointer is NULL\n");
return -666;
}
#ifdef VERBOSE
printf("file descriptor, datary = %d %d\n", *fdes, (int) datary);
#endif
count = (size_t) *no;
jret = read(*fdes, (void *) datary, count);
if (jret != *no) {
#ifdef VERBOSE
printf("did not read in the requested number of bytes\n");
printf("read in %d bytes instead of %d \n",jret, *no);
#endif
}
else {
#ifdef VERBOSE
printf("read in %d bytes requested \n", *no);
#endif
}
*nactual = jret;
*newpos = *start + jret;
}
/* Done with reading */
/* See if we should be writing */
if ( BAWRITE & *mode && BAOPEN_RONLY & *mode ) {
#ifdef VERBOSE
printf("Trying to write on a read only file \n");
#endif
return -7;
}
else if ( BAWRITE & *mode ) {
if (! (*mode & NOSEEK) ) {
seekret = lseek(*fdes, *start, SEEK_SET);
if (seekret == -1) {
#ifdef VERBOSE
printf("error in seeking to %d\n",*start);
#endif
return -8;
}
}
#ifdef CRAY90
datary = _fcdtocp(fcd_datary);
#endif
if (datary == NULL) {
printf("Massive catastrophe -- datary pointer is NULL\n");
return -666;
}
#ifdef VERBOSE
printf("write file descriptor, datary = %d %d\n", *fdes, (int) datary);
#endif
count = (size_t) *no;
jret = write(*fdes, (void *) datary, count);
if (jret != *no) {
#ifdef VERBOSE
printf("did not write out the requested number of bytes\n");
printf("wrote %d bytes instead\n", jret);
#endif
*nactual = jret;
*newpos = *start + jret;
}
else {
#ifdef VERBOSE
printf("wrote %d bytes \n", jret);
#endif
*nactual = jret;
*newpos = *start + jret;
}
}
/* Done with writing */
/* Close file if requested */
if (BACLOSE & *mode ) {
jret = close(*fdes);
if (jret != 0) {
#ifdef VERBOSE
printf("close failed! jret = %d\n",jret);
#endif
return -9;
}
}
/* Done closing */
/* Check that if we were reading or writing, that we actually got what */
/* we expected, else return a -10. Return 0 (success) if we're here */
/* and weren't reading or writing */
if ( (*mode & BAREAD || *mode & BAWRITE) && (*nactual != *no) ) {
return -10;
}
else {
return 0;
}
}
#ifdef CRAY90
#include <fortran.h>
int BANIO
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, _fcd fcd_fname, void *datary) {
char *fname;
int namelen;
#endif
#ifdef HP
int banio
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, const char *fname, char *datary,
int namelen ) {
#endif
#ifdef SGI
int banio_
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, const char *fname, char *datary,
int namelen ) {
#endif
#ifdef LINUX
int banio_
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, const char *fname, char *datary,
int namelen ) {
#endif
#ifdef LINUXF90
int BANIO
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, const char *fname, char *datary,
int namelen ) {
#endif
#ifdef IBM4
int banio
(int * mode, int * start, int *newpos, int * size, int * no,
int * nactual, int * fdes, const char *fname, char *datary,
int namelen ) {
#endif
#ifdef IBM8
long long int banio
(long long int * mode, long long int * start, long long int *newpos,
long long int * size, long long int * no,
long long int * nactual, long long int * fdes, const char *fname,
char *datary,
long long int namelen ) {
#endif
int i, j, jret, seekret;
char *realname, *tempchar;
int tcharval;
/* Initialization(s) */
*nactual = 0;
/* Check for illegal combinations of options */
if (( BAOPEN_RONLY & *mode) &&
( (BAOPEN_WONLY & *mode) || (BAOPEN_WONLY_TRUNC & *mode) || (BAOPEN_WONLY_APPEND & *mode) ) ) {
#ifdef VERBOSE
printf("illegal -- trying to open both read only and write only\n");
#endif
return -1;
}
if ( (BAREAD & *mode ) && (BAWRITE & *mode) ) {
#ifdef VERBOSE
printf("illegal -- trying to both read and write in the same call\n");
#endif
return -2;
}
/* This section handles Fortran to C translation of strings so as to */
/* be able to open the files Fortran is expecting to be opened. */
#ifdef CRAY90
namelen = _fcdlen(fcd_fname);
fname = _fcdtocp(fcd_fname);
#endif
if ( (BAOPEN_RONLY & *mode) || (BAOPEN_WONLY & *mode) ||
(BAOPEN_WONLY_TRUNC & *mode) || (BAOPEN_WONLY_APPEND & *mode) ||
(BAOPEN_RW & *mode) ) {
#ifdef VERBOSE
printf("Will be opening a file %s %d\n", fname, namelen); fflush(stdout);
printf("Strlen %d namelen %d\n", strlen(fname), namelen); fflush(stdout);
#endif
realname = (char *) malloc( namelen * sizeof(char) ) ;
if (realname == NULL) {
#ifdef VERBOSE
printf("failed to mallocate realname %d = namelen\n", namelen);
fflush(stdout);
#endif
return -3;
}
tempchar = (char *) malloc(sizeof(char) * 1 ) ;
i = 0;
j = 0;
*tempchar = fname[i];
tcharval = *tempchar;
while (i == j && i < namelen ) {
fflush(stdout);
if ( isgraph(tcharval) ) {
realname[j] = fname[i];
j += 1;
}
i += 1;
*tempchar = fname[i];
tcharval = *tempchar;
}
#ifdef VERBOSE
printf("i,j = %d %d\n",i,j); fflush(stdout);
#endif
realname[j] = '\0';
}
/* Open files with correct read/write and file permission. */
if (BAOPEN_RONLY & *mode) {
#ifdef VERBOSE
printf("open read only %s\n", realname);
#endif
*fdes = open(realname, O_RDONLY , S_IRWXU | S_IRWXG | S_IRWXO );
}
else if (BAOPEN_WONLY & *mode ) {
#ifdef VERBOSE
printf("open write only %s\n", realname);
#endif
*fdes = open(realname, O_WRONLY | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO );
}
else if (BAOPEN_WONLY_TRUNC & *mode ) {
#ifdef VERBOSE
printf("open write only with truncation %s\n", realname);
#endif
*fdes = open(realname, O_WRONLY | O_CREAT | O_TRUNC , S_IRWXU | S_IRWXG | S_IRWXO );
}
else if (BAOPEN_WONLY_APPEND & *mode ) {
#ifdef VERBOSE
printf("open write only with append %s\n", realname);
#endif
*fdes = open(realname, O_WRONLY | O_CREAT | O_APPEND , S_IRWXU | S_IRWXG | S_IRWXO );
}
else if (BAOPEN_RW & *mode) {
#ifdef VERBOSE
printf("open read-write %s\n", realname);
#endif
*fdes = open(realname, O_RDWR | O_CREAT , S_IRWXU | S_IRWXG | S_IRWXO );
}
else {
#ifdef VERBOSE
printf("no openings\n");
#endif
}
if (*fdes < 0) {
#ifdef VERBOSE
printf("error in file descriptor! *fdes %d\n", *fdes);
#endif
return -4;
}
else {
#ifdef VERBOSE
printf("file descriptor = %d\n",*fdes );
#endif
}
/* Read data as requested */
if (BAREAD & *mode &&
( (BAOPEN_WONLY & *mode) || (BAOPEN_WONLY_TRUNC & *mode) || (BAOPEN_WONLY_APPEND & *mode) ) ) {
#ifdef VERBOSE
printf("Error, trying to read while in write only mode!\n");
#endif
return -5;
}
else if (BAREAD & *mode ) {
/* Read in some data */
if (! (*mode & NOSEEK) ) {
seekret = lseek(*fdes, *start, SEEK_SET);
if (seekret == -1) {
#ifdef VERBOSE
printf("error in seeking to %d\n",*start);
#endif
return -6;
}
#ifdef VERBOSE
else {
printf("Seek successful, seek ret %d, start %d\n", seekret, *start);
}
#endif
}
jret = read(*fdes, datary, *no*(*size) );
if (jret != *no*(*size) ) {
#ifdef VERBOSE
printf("did not read in the requested number of items\n");
printf("read in %d items of %d \n",jret/(*size), *no);
#endif
*nactual = jret/(*size);
*newpos = *start + jret;
}
#ifdef VERBOSE
printf("read in %d items \n", jret/(*size));
#endif
*nactual = jret/(*size);
*newpos = *start + jret;
}
/* Done with reading */
/* See if we should be writing */
if ( BAWRITE & *mode && BAOPEN_RONLY & *mode ) {
#ifdef VERBOSE
printf("Trying to write on a read only file \n");
#endif
return -7;
}
else if ( BAWRITE & *mode ) {
if (! (*mode & NOSEEK) ) {
seekret = lseek(*fdes, *start, SEEK_SET);
if (seekret == -1) {
#ifdef VERBOSE
printf("error in seeking to %d\n",*start);
#endif
return -8;
}
#ifdef VERBOSE
else {
printf("Seek successful, seek ret %d, start %d\n", seekret, *start);
}
#endif
}
jret = write(*fdes, datary, *no*(*size));
if (jret != *no*(*size)) {
#ifdef VERBOSE
printf("did not write out the requested number of items\n");
printf("wrote %d items instead\n", jret/(*size) );
#endif
*nactual = jret/(*size) ;
*newpos = *start + jret;
}
else {
#ifdef VERBOSE
printf("wrote %d items \n", jret/(*size) );
#endif
*nactual = jret/(*size) ;
*newpos = *start + jret;
}
}
/* Done with writing */
/* Close file if requested */
if (BACLOSE & *mode ) {
jret = close(*fdes);
if (jret != 0) {
#ifdef VERBOSE
printf("close failed! jret = %d\n",jret);
#endif
return -9;
}
}
/* Done closing */
/* Check that if we were reading or writing, that we actually got what */
/* we expected, else return a -10. Return 0 (success) if we're here */
/* and weren't reading or writing */
if ( (*mode & BAREAD || *mode & BAWRITE) && (*nactual != *no) ) {
return -10;
}
else {
return 0;
}
}