/* * f o p e n x */ /*)LIBRARY */ #ifdef DOCUMENTATION Title fopenx Open a file (extended) Index Open a file (extended) synopsis .s.nf FILE * fopenx(name, mode, inisiz, recsiz); char *name; /* File to open */ char *mode; /* Open modes */ int inisiz; /* initial size of file */ int recsiz; /* record size for random access files */ .s.f Description Fopenx is an extended version of the standard DecusC fopen routine. It opens a new or existing file in the indicated mode: .s.nf r Read the existing file sequentially w Create and write the file sequentially a Append to the file n Not record oriented u RSX-mode "unbuffered i/o" .s.f "eXtended" modes are: .s.nf m Open existing file for modification p Preallocate file size x Open file as a random access file s Open file for shared access .s.f Either "r", "w", "a" or "m" must be given. "n" and "u" are optional. "n" should be given for "binary" files. Note that "n" mode will create fixed-block records on RSX systems with record size 512. .s Inisiz must be 0 unless the "p" option is given, then it should be the initial number of blocks to be allocated for the file. A positive value for inisiz requests a contiguous file, a negative value gives a non-contiguous file. .s Recsiz must be 0 unless the "x" option is given, then it is the record size for a random access file. The size should be given in bytes. .s The "p" and "x" options are only valid when creating a new file. .s Note that "n", "u", "m", "p" and "x" are not compatible with other Unix systems. Implementation Details On RSX, "u" mode files will be created with the "variable-length" attribute. .s On RSX, if the record type bits in the record attribute byte (F.RATT in the FDB) is zero, the file will be read as if the "n" was specified. Files created with the "x" option also have the F.RATT byte set to 0. Note that, if the file contains carriage-return line-feed sequences, the entire sequence will be passed to the user's program. If record attributes are understandable, the carriage-return will be deleted from sequences. .s Don't use fopenx on non-disk devices, the results are unpredicatable. .s Fopenx() returns NULL on errors -- $$ferr gets an error code. On RSX, this will be the FCS error code. .s Note that "no buffer space available" (IE.NBF or E$$NSP) and "invalid lun" (IE.ILU or E$$NOC) may be generated by fopen. .s The same file may not be used for both reading and writing except if the program writes a disk file and uses fgetb and fputb. As with the standard DecusC fopen, using regular sequential io (fget,fput) will work only if you write, then repositions and reads it using ftell()/fseek(). In this case, the program should call rewind() or freopen() to reinitialize the file before using fseek(). .s You can get the status block info from FCS by defining $$stbk as an external word array. Look in the FCS manual for the meaning of each word. Note this value is volatile, the next fopenx overwrites it. Bugs Only works with RSX FCS. You need to known what your doing. #endif #include #define IE_BAD -1 /* bad parameter ferr value */ /* file open types */ extern char *FO_RD; extern char *FO_WRT; extern char *FO_MFY; extern char *FO_UPD; extern char *FO_APD; extern char *FA_SHR; /* fdb offsets */ extern char *F_RTYP; extern char *F_RATT; extern char *F_RACC; extern char *F_FACC; extern char *F_CNTG; extern char *F_RSIZ; extern char *F_ERR; extern char *F_STBK; /* file attributes */ extern char *FD_RAN; extern char *R_FIX; extern char *R_VAR; extern int $$ferr; unsigned $$stbk[5]; FILE * fopenx(fnam, mode, inisiz, recsiz) char *fnam; char *mode; int inisiz; /* initial size of file */ int recsiz; /* record size for fixed length file */ { FILE *fp; char options[8]; /* options string */ char *p; /* genral pointer */ int ferr; /* place to save $$ferr on open err */ int facc; /* access type */ int af; /* access count - must be 1 */ /* special open flags */ char mf; /* modify flag */ char pf; /* preallocate flag */ char sf; /* shared access flag */ char xf; /* fixed length flag */ char cf; /* create flag */ facc = af = mf = pf = sf = xf = cf = 0; options[0] = NULL; /* make sure we have a null string */ /* scan for all file options */ for (p = mode; *p != NULL; p++) { switch (*p) { case 'r': { af++; facc = facc | ((int) &FO_RD); strcat(options, "r"); continue; } case 'w': { af++; facc = facc | ((int) &FO_WRT); strcat(options, "w"); cf++; continue; } case 'a': { af++; facc = facc | ((int) &FO_APD); strcat(options, "a"); continue; } case 'u': { strcat(options, "u"); continue; } case 'n': { strcat(options, "n"); continue; } case 'm': { af++; mf++; strcat(options, "r"); /* set "r" so fdbset works */ facc = facc | ((int) &FO_MFY); continue; } case 'p': { pf++; continue; } case 's': { sf++; facc = facc | ((int) &FA_SHR); continue; } case 'x': { xf++; /* fixed length records flag */ continue; } default: { $$ferr = IE_BAD; /* report bad args */ return(NULL); } } } /* end options string scan */ if (af != 1) { /* only one access type allowed */ $$ferr = IE_BAD; /* report bad args */ return(NULL); } /* set up fdb and iov, return if it fails */ if ((fp = fdbset(fnam, options)) == NULL) return(NULL); /* we have a good iov, now set up optional stuff */ p = fp->io_fdb; *(p + (int) &F_FACC) = facc; /* set access type */ *(p + (int) &F_RTYP) = (int) &R_VAR; /* assume var. length */ if (xf) { /* fixed length records, random access r/w */ *(p + (int) &F_RTYP) = (int) &R_FIX; *(p + (int) &F_RATT) = 0; *(p + (int) &F_RACC) = (int) &FD_RAN; *((int *) (p + (int) &F_RSIZ)) = recsiz; } if (pf) { /* preallocate file to size */ if (cf != 1) { /* must be creating file */ $$ferr = IE_BAD; /* report bad args */ return(NULL); } *((int *) (p + (int) &F_CNTG)) = inisiz; } *((int *) (p + (int) &F_STBK)) = $$stbk; /* point to statistics */ if (($$ferr = opnfnb(fp->io_fdb)) != 1) { ferr = $$ferr; /* save $$ferr across close */ fclose(fp); fp = NULL; $$ferr = ferr; } return(fp); }