/* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* qread_vms.c Routines to read and write VMS fixed-length record files as * binary stream files. * * For non-VMS machines use qread.c instead of these routines. (The * standard VMS stream-I/O routines do not read the CD-ROM correctly in * some cases.) * * Summary of procedures: * * Opening and closing files: * * QFILE *qcreat(filename,recordsize,crrat) Creates file filename. * QFILE *qopen( filename,recordsize,crrat) Opens file filename. * void qclose(qfile) Closes qfile. * * Stream I/O: * * void qread(qfile, buffer, n) Reads next n bytes from qfile. * void qwrite(qfile, buffer, n) Writes n bytes to qfile. * void fillbuff(qfile) Fills record buffer from qfile. * void dumpbuff(qfile) Dumps record buffer to qfile. * int readint(qfile) Read a 4-byte integer from qfile. * void writeint(qfile,a) Write a 4-byte integer to qfile. * * All routines abort with an error message if there are problems. * * Programmer: R. White Date: 16 June 1992 */ #include #include #include "qfile.h" /* * ---------------- error exit ---------------- */ static void qerror(operation,qfile,rms_status) char *operation; QFILE *qfile; int rms_status; { fprintf(stderr, "VMS error: %s failed for file %s\n", operation, qfile->fab.fab$l_fna); exit(rms_status); } /* * --------------- create a fixed-record-length file --------------- */ extern QFILE *qcreat(filename,recordsize,crrat) char *filename; int recordsize; /* Record length in bytes */ int crrat; /* Carriage return attributes flag: 0 = no CRs */ { QFILE *qfile; int rms_status; /* * Allocate memory for file access block and copy filename * and FAB and RAB templates */ qfile = (QFILE *) malloc(sizeof(QFILE)); qfile->filename = filename; qfile->fab = cc$rms_fab; qfile->rab = cc$rms_rab; /* * Set up file attributes for fixed length records */ qfile->fab.fab$l_fna = filename; /* Filename */ qfile->fab.fab$b_fns = strlen(filename); /* Filename length */ qfile->fab.fab$b_rfm = FAB$C_FIX; /* Fixed record format */ qfile->fab.fab$w_mrs = recordsize; /* Record size */ qfile->fab.fab$b_fac = FAB$M_DEL | FAB$M_PUT; /* Delete or put access */ if (crrat != 0) { qfile->fab.fab$b_rat = FAB$M_CR; /* CR carriage control */ } /* * Set up record access block */ qfile->rab.rab$l_fab = &(qfile->fab); /* * Create the file */ rms_status = sys$create(&(qfile->fab)); if (rms_status != RMS$_NORMAL && rms_status != RMS$_CREATED) { qerror("Create",qfile,rms_status); } /* * Associate the record access block with the fab */ rms_status = sys$connect(&(qfile->rab)); if (rms_status != RMS$_NORMAL) { qerror("Connect",qfile,rms_status); } /* * Sequential access, fixed length records */ qfile->rab.rab$b_rac = RAB$C_SEQ; qfile->rab.rab$w_rsz = recordsize; /* * File attributes */ qfile->recordsize = recordsize; qfile->crrat = (crrat != 0); qfile->write = 1; /* * Create buffer, initialize pointer */ qfile->bufsize = recordsize; qfile->buffer = (unsigned char *) malloc(qfile->bufsize); qfile->bptr = 0; /* * Return pointer to structure */ return(qfile); } /* * --------------- open a fixed-record-length file --------------- */ extern QFILE *qopen(filename,recordsize,crrat) char *filename; int recordsize; int crrat; { QFILE *qfile; int rms_status; /* * Allocate memory for file access block and copy filename * and FAB and RAB templates */ qfile = (QFILE *) malloc(sizeof(QFILE)); qfile->filename = filename; qfile->fab = cc$rms_fab; qfile->rab = cc$rms_rab; /* * Set up file attributes for fixed length records */ qfile->fab.fab$l_fna = filename; /* Filename */ qfile->fab.fab$b_fns = strlen(filename); /* Filename length */ qfile->fab.fab$b_rfm = FAB$C_FIX; /* Fixed record format */ qfile->fab.fab$b_fac = FAB$M_GET; /* Get access */ if (crrat != 0) { qfile->fab.fab$b_rat = FAB$M_CR; /* CR carriage control */ } /* * Set up record access block */ qfile->rab.rab$l_fab = &(qfile->fab); /* * Open the file */ rms_status = sys$open(&(qfile->fab)); if (rms_status != RMS$_NORMAL) { qerror("Open",qfile,rms_status); } /* * Associate the record access block with the fab */ rms_status = sys$connect(&(qfile->rab)); if (rms_status != RMS$_NORMAL) { qerror("Connect",qfile,rms_status); } /* * Check that recordsize and record length from file header agree */ if (recordsize != qfile->fab.fab$w_mrs) { fprintf(stderr, "Warning: record length for %s is %d, should be %d\n", filename, qfile->fab.fab$w_mrs, recordsize); recordsize = qfile->fab.fab$w_mrs; } /* * Sequential access, fixed record length */ qfile->rab.rab$b_rac = RAB$C_SEQ; qfile->rab.rab$w_usz = recordsize; /* * File attributes */ qfile->recordsize = recordsize; qfile->crrat = (crrat != 0); qfile->write = 0; /* * Create buffer, initialize pointer */ qfile->bufsize = recordsize; qfile->buffer = (unsigned char *) malloc(qfile->bufsize); qfile->bptr = qfile->bufsize; /* * Return pointer to structure */ return(qfile); } /* * --------------- Close file --------------- */ extern void qclose(qfile) QFILE *qfile; { int rms_status; /* * If we're writing to file, dump partially full buffer */ if (qfile->write) dumpbuff(qfile); /* * Close the file */ rms_status = sys$close(&(qfile->fab)); if (rms_status != RMS$_NORMAL) { qerror("Close", qfile, rms_status); } /* * Free buffer and qfile structure */ free(qfile->buffer); free(qfile); return; } /* * --------------- Fill buffer from next record --------------- */ extern void fillbuff(qfile) QFILE *qfile; { int rms_status; qfile->rab.rab$l_ubf = qfile->buffer; rms_status = sys$get(&(qfile->rab)); qfile->bptr = 0; if (rms_status == RMS$_NORMAL) { return; } else if (rms_status == RMS$_EOF) { fprintf(stderr, "Error: unexpected EOF on %s\n", qfile->filename); } qerror("Read",qfile,rms_status); } /* * --------------- Dump (full or partial) buffer to file --------------- */ extern void dumpbuff(qfile) QFILE *qfile; { int rms_status; if (qfile->bptr > 0) { qfile->rab.rab$l_rbf = qfile->buffer; rms_status = sys$put(&(qfile->rab)); if (rms_status != RMS$_NORMAL) { qerror("Write",qfile,rms_status); } qfile->bptr = 0; } } /* * --------------- Buffered input: Get next n bytes from file --------------- */ extern void qread(qfile, buffer, n) QFILE *qfile; char *buffer; int n; { int i; for (i=0; ibptr >= qfile->bufsize) fillbuff(qfile); buffer[i] = qfile->buffer[qfile->bptr++]; } } /* * --------------- Buffered output: Put next n bytes to file --------------- */ extern void qwrite(qfile, buffer, n) QFILE *qfile; char *buffer; int n; { int i; for (i=0; ibptr >= qfile->bufsize) dumpbuff(qfile); qfile->buffer[qfile->bptr++] = buffer[i]; } } extern int readint(infile) QFILE *infile; { int a,i; unsigned char b[4]; /* Read integer A one byte at a time from infile. * * This is portable from Vax to Sun since it eliminates the * need for byte-swapping. */ for (i=0; i<4; i++) b[i] = qgetc(infile); a = b[0]; for (i=1; i<4; i++) a = (a<<8) + b[i]; return(a); } extern void writeint(outfile,a) QFILE *outfile; int a; { int i; unsigned char b[4]; /* Write integer A one byte at a time to outfile. * * This is portable from Vax to Sun since it eliminates the * need for byte-swapping. */ for (i=3; i>=0; i--) { b[i] = a & 0xff; a >>= 8; } for (i=0; i<4; i++) qputc(b[i],outfile); return; }