1 /* Fortran-callable routines to read and write characther (ba_cio) and */
2 /* numeric (banio) data byte addressably */
3 /* Robert Grumbine 16 March 1998 */
4 /* v1.1: Put diagnostic output under control of define VERBOSE or QUIET */
5 /* Add option of non-seeking read/write */
6 /* Return code for fewer data read/written than requested */
7 /* v1.2: Add cray compatibility 20 April 1998 */
10 #include <sys/types.h>
16 # define S_IRWXU 00700
17 # define S_IRWXG 00070
18 # define S_IRWXO 00007
21 #include <malloc/malloc.h>
28 /* Include the C library file for definition/control */
29 /* Things that might be changed for new systems are there. */
30 /* This source file should not (need to) be edited, merely recompiled */
36 /* -1 Tried to open read only _and_ write only */
37 /* -2 Tried to read and write in the same call */
38 /* -3 Internal failure in name processing */
39 /* -4 Failure in opening file */
40 /* -5 Tried to read on a write-only file */
41 /* -6 Failed in read to find the 'start' location */
42 /* -7 Tried to write to a read only file */
43 /* -8 Failed in write to find the 'start' location */
44 /* -9 Error in close */
45 /* -10 Read or wrote fewer data than requested */
47 /* Note: In your Fortran code, call ba_cio, not ba_cio_. */
48 /*int ba_cio_(int * mode, int * start, int * size, int * no, int * nactual, */
49 /* int * fdes, const char *fname, char *data, int namelen, */
50 /* int datanamelen) */
52 /* Mode is the integer specifying operations to be performed */
53 /* see the clib.inc file for the values. Mode is obtained */
54 /* by adding together the values corresponding to the operations */
55 /* The best method is to include the clib.inc file and refer to the */
56 /* names for the operations rather than rely on hard-coded values */
57 /* Start is the byte number to start your operation from. 0 is the first */
58 /* byte in the file, not 1. */
59 /* Newpos is the position in the file after a read or write has been */
60 /* performed. You'll need this if you're doing 'seeking' read/write */
61 /* Size is the size of the objects you are trying to read. Rely on the */
62 /* values in the locale.inc file. Types are CHARACTER, INTEGER, REAL, */
63 /* COMPLEX. Specify the correct value by using SIZEOF_type, where type */
64 /* is one of these. (After having included the locale.inc file) */
65 /* no is the number of things to read or write (characters, integers, */
67 /* nactual is the number of things actually read or written. Check that */
68 /* you got what you wanted. */
69 /* fdes is an integer 'file descriptor'. This is not a Fortran Unit Number */
70 /* You can use it, however, to refer to files you've previously opened. */
71 /* fname is the name of the file. This only needs to be defined when you */
72 /* are opening a file. It must be (on the Fortran side) declared as */
73 /* CHARACTER*N, where N is a length greater than or equal to the length */
74 /* of the file name. CHARACTER*1 fname[80] (for example) will fail. */
75 /* data is the name of the entity (variable, vector, array) that you want */
76 /* to write data out from or read it in to. The fact that C is declaring */
77 /* it to be a char * does not affect your fortran. */
78 /* namelen - Do NOT specify this. It is created automagically by the */
79 /* Fortran compiler */
80 /* datanamelen - Ditto */
83 /* What is going on here is that although the Fortran caller will always */
84 /* be calling ba_cio, the called C routine name will change from system */
86 #if defined _UNDERSCORE
88 (int * mode
, int * start
, int *newpos
, int * size
, int * no
,
89 int * nactual
, int * fdes
, const char *fname
, char *datary
,
90 int namelen
, int datanamelen
) {
91 #elif defined _DOUBLEUNDERSCORE
93 (int * mode
, int * start
, int *newpos
, int * size
, int * no
,
94 int * nactual
, int * fdes
, const char *fname
, char *datary
,
95 int namelen
, int datanamelen
) {
98 (int * mode
, int * start
, int *newpos
, int * size
, int * no
,
99 int * nactual
, int * fdes
, const char *fname
, char *datary
,
100 int namelen
, int datanamelen
) {
102 int i
, j
, jret
, seekret
;
103 char *realname
, *tempchar
;
107 /* Initialization(s) */
110 /* Check for illegal combinations of options */
111 if (( BAOPEN_RONLY
& *mode
) &&
112 ( (BAOPEN_WONLY
& *mode
) || (BAOPEN_WONLY_TRUNC
& *mode
) || (BAOPEN_WONLY_APPEND
& *mode
) ) ) {
114 printf("illegal -- trying to open both read only and write only\n");
118 if ( (BAREAD
& *mode
) && (BAWRITE
& *mode
) ) {
120 printf("illegal -- trying to both read and write in the same call\n");
125 /* This section handles Fortran to C translation of strings so as to */
126 /* be able to open the files Fortran is expecting to be opened. */
128 namelen
= _fcdlen(fcd_fname
);
129 fname
= _fcdtocp(fcd_fname
);
131 if ( (BAOPEN_RONLY
& *mode
) || (BAOPEN_WONLY
& *mode
) ||
132 (BAOPEN_WONLY_TRUNC
& *mode
) || (BAOPEN_WONLY_APPEND
& *mode
) ||
133 (BAOPEN_RW
& *mode
) ) {
135 printf("Will be opening a file %s %d\n", fname
, namelen
); fflush(stdout
);
136 printf("Strlen %d namelen %d\n", strlen(fname
), namelen
); fflush(stdout
);
138 realname
= (char *) malloc( namelen
* sizeof(char) ) ;
139 if (realname
== NULL
) {
141 printf("failed to mallocate realname %d = namelen\n", namelen
);
146 tempchar
= (char *) malloc(sizeof(char) * 1 ) ;
149 *tempchar
= fname
[i
];
150 tcharval
= *tempchar
;
151 while (i
== j
&& i
< namelen
) {
153 if ( isgraph(tcharval
) ) {
154 realname
[j
] = fname
[i
];
158 *tempchar
= fname
[i
];
159 tcharval
= *tempchar
;
162 printf("i,j = %d %d\n",i
,j
); fflush(stdout
);
167 /* Open files with correct read/write and file permission. */
168 if (BAOPEN_RONLY
& *mode
) {
170 printf("open read only %s\n", realname
);
172 *fdes
= open(realname
, O_RDONLY
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
174 else if (BAOPEN_WONLY
& *mode
) {
176 printf("open write only %s\n", realname
);
178 *fdes
= open(realname
, O_WRONLY
| O_CREAT
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
180 else if (BAOPEN_WONLY_TRUNC
& *mode
) {
182 printf("open write only with truncation %s\n", realname
);
184 *fdes
= open(realname
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
186 else if (BAOPEN_WONLY_APPEND
& *mode
) {
188 printf("open write only with append %s\n", realname
);
190 *fdes
= open(realname
, O_WRONLY
| O_CREAT
| O_APPEND
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
192 else if (BAOPEN_RW
& *mode
) {
194 printf("open read-write %s\n", realname
);
196 *fdes
= open(realname
, O_RDWR
| O_CREAT
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
200 printf("no openings\n");
205 printf("error in file descriptor! *fdes %d\n", *fdes
);
211 printf("file descriptor = %d\n",*fdes
);
216 /* Read data as requested */
217 if (BAREAD
& *mode
&&
218 ( (BAOPEN_WONLY
& *mode
) || (BAOPEN_WONLY_TRUNC
& *mode
) || (BAOPEN_WONLY_APPEND
& *mode
) ) ) {
220 printf("Error, trying to read while in write only mode!\n");
224 else if (BAREAD
& *mode
) {
225 /* Read in some data */
226 if (! (*mode
& NOSEEK
) ) {
227 seekret
= lseek(*fdes
, *start
, SEEK_SET
);
230 printf("error in seeking to %d\n",*start
);
236 printf("Seek successful, seek ret %d, start %d\n", seekret
, *start
);
241 datary
= _fcdtocp(fcd_datary
);
243 if (datary
== NULL
) {
244 printf("Massive catastrophe -- datary pointer is NULL\n");
248 printf("file descriptor, datary = %d %d\n", *fdes
, (int) datary
);
250 count
= (size_t) *no
;
251 jret
= read(*fdes
, (void *) datary
, count
);
254 printf("did not read in the requested number of bytes\n");
255 printf("read in %d bytes instead of %d \n",jret
, *no
);
260 printf("read in %d bytes requested \n", *no
);
264 *newpos
= *start
+ jret
;
266 /* Done with reading */
268 /* See if we should be writing */
269 if ( BAWRITE
& *mode
&& BAOPEN_RONLY
& *mode
) {
271 printf("Trying to write on a read only file \n");
275 else if ( BAWRITE
& *mode
) {
276 if (! (*mode
& NOSEEK
) ) {
277 seekret
= lseek(*fdes
, *start
, SEEK_SET
);
280 printf("error in seeking to %d\n",*start
);
286 datary
= _fcdtocp(fcd_datary
);
288 if (datary
== NULL
) {
289 printf("Massive catastrophe -- datary pointer is NULL\n");
293 printf("write file descriptor, datary = %d %d\n", *fdes
, (int) datary
);
295 count
= (size_t) *no
;
296 jret
= write(*fdes
, (void *) datary
, count
);
299 printf("did not write out the requested number of bytes\n");
300 printf("wrote %d bytes instead\n", jret
);
303 *newpos
= *start
+ jret
;
307 printf("wrote %d bytes \n", jret
);
310 *newpos
= *start
+ jret
;
313 /* Done with writing */
316 /* Close file if requested */
317 if (BACLOSE
& *mode
) {
321 printf("close failed! jret = %d\n",jret
);
328 /* Check that if we were reading or writing, that we actually got what */
329 /* we expected, else return a -10. Return 0 (success) if we're here */
330 /* and weren't reading or writing */
331 if ( (*mode
& BAREAD
|| *mode
& BAWRITE
) && (*nactual
!= *no
) ) {
338 #if defined _UNDERSCORE
340 (int * mode
, int * start
, int *newpos
, int * size
, int * no
,
341 int * nactual
, int * fdes
, const char *fname
, char *datary
,
343 #elif defined _DOUBLEUNDERSCORE
345 (int * mode
, int * start
, int *newpos
, int * size
, int * no
,
346 int * nactual
, int * fdes
, const char *fname
, char *datary
,
350 (int * mode
, int * start
, int *newpos
, int * size
, int * no
,
351 int * nactual
, int * fdes
, const char *fname
, char *datary
,
354 int i
, j
, jret
, seekret
;
355 char *realname
, *tempchar
;
358 /* Initialization(s) */
361 /* Check for illegal combinations of options */
362 if (( BAOPEN_RONLY
& *mode
) &&
363 ( (BAOPEN_WONLY
& *mode
) || (BAOPEN_WONLY_TRUNC
& *mode
) || (BAOPEN_WONLY_APPEND
& *mode
) ) ) {
365 printf("illegal -- trying to open both read only and write only\n");
369 if ( (BAREAD
& *mode
) && (BAWRITE
& *mode
) ) {
371 printf("illegal -- trying to both read and write in the same call\n");
376 /* This section handles Fortran to C translation of strings so as to */
377 /* be able to open the files Fortran is expecting to be opened. */
379 namelen
= _fcdlen(fcd_fname
);
380 fname
= _fcdtocp(fcd_fname
);
382 if ( (BAOPEN_RONLY
& *mode
) || (BAOPEN_WONLY
& *mode
) ||
383 (BAOPEN_WONLY_TRUNC
& *mode
) || (BAOPEN_WONLY_APPEND
& *mode
) ||
384 (BAOPEN_RW
& *mode
) ) {
386 printf("Will be opening a file %s %d\n", fname
, namelen
); fflush(stdout
);
387 printf("Strlen %d namelen %d\n", strlen(fname
), namelen
); fflush(stdout
);
389 realname
= (char *) malloc( namelen
* sizeof(char) ) ;
390 if (realname
== NULL
) {
392 printf("failed to mallocate realname %d = namelen\n", namelen
);
397 tempchar
= (char *) malloc(sizeof(char) * 1 ) ;
400 *tempchar
= fname
[i
];
401 tcharval
= *tempchar
;
402 while (i
== j
&& i
< namelen
) {
404 if ( isgraph(tcharval
) ) {
405 realname
[j
] = fname
[i
];
409 *tempchar
= fname
[i
];
410 tcharval
= *tempchar
;
413 printf("i,j = %d %d\n",i
,j
); fflush(stdout
);
418 /* Open files with correct read/write and file permission. */
419 if (BAOPEN_RONLY
& *mode
) {
421 printf("open read only %s\n", realname
);
423 *fdes
= open(realname
, O_RDONLY
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
425 else if (BAOPEN_WONLY
& *mode
) {
427 printf("open write only %s\n", realname
);
429 *fdes
= open(realname
, O_WRONLY
| O_CREAT
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
431 else if (BAOPEN_WONLY_TRUNC
& *mode
) {
433 printf("open write only with truncation %s\n", realname
);
435 *fdes
= open(realname
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
437 else if (BAOPEN_WONLY_APPEND
& *mode
) {
439 printf("open write only with append %s\n", realname
);
441 *fdes
= open(realname
, O_WRONLY
| O_CREAT
| O_APPEND
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
443 else if (BAOPEN_RW
& *mode
) {
445 printf("open read-write %s\n", realname
);
447 *fdes
= open(realname
, O_RDWR
| O_CREAT
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
451 printf("no openings\n");
456 printf("error in file descriptor! *fdes %d\n", *fdes
);
462 printf("file descriptor = %d\n",*fdes
);
467 /* Read data as requested */
468 if (BAREAD
& *mode
&&
469 ( (BAOPEN_WONLY
& *mode
) || (BAOPEN_WONLY_TRUNC
& *mode
) || (BAOPEN_WONLY_APPEND
& *mode
) ) ) {
471 printf("Error, trying to read while in write only mode!\n");
475 else if (BAREAD
& *mode
) {
476 /* Read in some data */
477 if (! (*mode
& NOSEEK
) ) {
478 seekret
= lseek(*fdes
, *start
, SEEK_SET
);
481 printf("error in seeking to %d\n",*start
);
487 printf("Seek successful, seek ret %d, start %d\n", seekret
, *start
);
491 jret
= read(*fdes
, datary
, *no
*(*size
) );
492 if (jret
!= *no
*(*size
) ) {
494 printf("did not read in the requested number of items\n");
495 printf("read in %d items of %d \n",jret
/(*size
), *no
);
497 *nactual
= jret
/(*size
);
498 *newpos
= *start
+ jret
;
501 printf("read in %d items \n", jret
/(*size
));
503 *nactual
= jret
/(*size
);
504 *newpos
= *start
+ jret
;
506 /* Done with reading */
508 /* See if we should be writing */
509 if ( BAWRITE
& *mode
&& BAOPEN_RONLY
& *mode
) {
511 printf("Trying to write on a read only file \n");
515 else if ( BAWRITE
& *mode
) {
516 if (! (*mode
& NOSEEK
) ) {
517 seekret
= lseek(*fdes
, *start
, SEEK_SET
);
520 printf("error in seeking to %d\n",*start
);
526 printf("Seek successful, seek ret %d, start %d\n", seekret
, *start
);
530 jret
= write(*fdes
, datary
, *no
*(*size
));
531 if (jret
!= *no
*(*size
)) {
533 printf("did not write out the requested number of items\n");
534 printf("wrote %d items instead\n", jret
/(*size
) );
536 *nactual
= jret
/(*size
) ;
537 *newpos
= *start
+ jret
;
541 printf("wrote %d items \n", jret
/(*size
) );
543 *nactual
= jret
/(*size
) ;
544 *newpos
= *start
+ jret
;
547 /* Done with writing */
550 /* Close file if requested */
551 if (BACLOSE
& *mode
) {
555 printf("close failed! jret = %d\n",jret
);
562 /* Check that if we were reading or writing, that we actually got what */
563 /* we expected, else return a -10. Return 0 (success) if we're here */
564 /* and weren't reading or writing */
565 if ( (*mode
& BAREAD
|| *mode
& BAWRITE
) && (*nactual
!= *no
) ) {