Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001, Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2.1 of the GNU Lesser General Public License 00007 as published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU Lesser General Public 00021 License along with this program; if not, write the Free Software 00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 00023 USA. 00024 00025 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00026 Mountain View, CA 94043, or: 00027 00028 http://www.sgi.com 00029 00030 For further information regarding this notice, see: 00031 00032 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00033 00034 */ 00035 00036 00037 00038 #pragma ident "@(#) libf/fio/fopn.c 92.6 09/20/99 11:41:08" 00039 00040 #include <errno.h> 00041 #include <fcntl.h> 00042 #include <liberrno.h> 00043 #ifndef _ABSOFT 00044 #include <stdlib.h> 00045 #endif 00046 #include <stddef.h> 00047 #include <stdio.h> 00048 #include <string.h> 00049 #include <unistd.h> 00050 #include <stdlib.h> 00051 #include <sys/stat.h> 00052 #include <cray/nassert.h> 00053 #ifdef _UNICOS_MAX 00054 #include <mpp/globals.h> 00055 #endif 00056 #include <cray/assign.h> 00057 #include "fio.h" 00058 00059 #define TRACK (42*BLKSIZE) /* Most common track size */ 00060 #define FPARMAX 3 /* Number of numeric layer parameters */ 00061 #define SPECSZ (FPARMAX+2+1) /* Room for largest FFIO spec used */ 00062 /* FPARMAX + 1 for class + 1 for terminating zero spec */ 00063 /* + 1 for cachea layer shared cache specification */ 00064 /* (not used) */ 00065 #define ACCESS_PERMS 0666 /* Access permissions */ 00066 00067 #if defined(_LITTLE_ENDIAN) && !defined(__sv2) 00068 #ifndef IOWRT 00069 #define IOWRT = _IO_CURRENTLY_PUTTING 00070 #endif 00071 #ifndef IORW 00072 #define IORW = _IO_TIED_PUTGET 00073 #endif 00074 extern FILE *fdopen(int, const char*); 00075 #endif /* LITTLE_ENDIAN and not sv2 */ 00076 00077 extern int __fdctrace_enable; 00078 static int _defbufsiz_warning; /* set to 1 after first DEFBUFSIZ warning */ 00079 00080 static int 00081 make_fdspec(union spec_u *fdspec, char *layer, int intnum[FPARMAX]); 00082 00083 /* 00084 * _f_opn - fortran open 00085 * 00086 * Return value: 00087 * 0 if OK, -1 on error with errno set 00088 * 00089 * Side effects: 00090 * statp structure is made valid if not valid upon entry. 00091 */ 00092 00093 int 00094 _f_opn( 00095 char *actnam, /* actual file name */ 00096 unit *cup, 00097 FIOSPTR css, 00098 int tufs, /* used to store ufs till open is OK */ 00099 /* cup->ufs set indicates open was OK */ 00100 int aifound, /* 1 if aip is valid */ 00101 assign_info *aip, /* assign information */ 00102 struct stat *statp, /* pointer to stat buf */ 00103 int statp_valid, /* 1 if statp is valid upon entry, 0 if the 00104 * file has not yet been stat'ed */ 00105 int catcherr, /* nonzero if abort on errors */ 00106 int o_sysflgs) /* O_TRUNC/O_CREAT/O_EXCL */ 00107 { 00108 register short default_ftype; /* 1 iff no -s or -F assigned */ 00109 register short disk_file; 00110 register short i; 00111 register short not_open; 00112 register int fd; 00113 register int flags; 00114 register int opt_flags; 00115 register int acc_mode; 00116 int num[FPARMAX]; 00117 char *ffio_layer; 00118 union spec_u specspace[SPECSZ]; 00119 union spec_u *fdspec; 00120 struct fdinfo *fio; 00121 struct ffsw ffiostat; 00122 struct ffc_info_s info; 00123 struct ffc_stat_s ffio_statbuf; 00124 00125 extern int _def_cch_bufsiz; 00126 #ifdef _UNICOS_MAX 00127 extern int _def_cch_simbufsiz; 00128 #endif 00129 extern void _ffconvert_stat(struct ffc_stat_s *src, 00130 struct stat *dest); 00131 00132 disk_file = 1; /* assume a disk file */ 00133 not_open = 1; /* file is not yet open */ 00134 opt_flags = 0; /* set no optional flags */ 00135 flags = 0; 00136 fdspec = NULL; 00137 00138 /* 00139 * Lookup the environment variable which was used in UNICOS 6.0 to 00140 * set the default buffer size and issue a warning if the user has set it. 00141 */ 00142 if (_defbufsiz_warning == 0 && ((char *)getenv("DEFBUFSIZ") != NULL)) { 00143 _defbufsiz_warning = 1; /* suppress subsequent warnings */ 00144 _fwarn(FWDEFBSZ); 00145 } 00146 00147 /* 00148 * If -s and -F are not assigned, set flag to indicate that the default 00149 * file type is being used. 00150 */ 00151 if (! aifound || (! aip->s_fstrct_flg && ! aip->F_filter_flg)) 00152 default_ftype = 1; 00153 else 00154 default_ftype = 0; 00155 00156 /* 00157 * Initialize unit table fields ucharset and unumcvrt. 00158 */ 00159 if (aifound && aip->C_chrcnv_flg) 00160 cup->ucharset = aip->C_chrcnv; 00161 else 00162 cup->ucharset = 0; 00163 00164 if (aifound && aip->N_datcnv_flg) 00165 cup->unumcvrt = aip->N_datcnv; 00166 else 00167 cup->unumcvrt = 0; 00168 00169 if (cup->unumcvrt || cup->ucharset) { 00170 /* 00171 * Numeric conversion implies matching character 00172 * conversion if not otherwise specified. Also, 00173 * change NCV_NATIVE and CS_NATIVE to zero to 00174 * simplify run-time checking. 00175 */ 00176 _setup_cvrt(cup); 00177 } 00178 00179 #if NUMERIC_DATA_CONVERSION_ENABLED 00180 /* 00181 * cup->ualignmask is set to the alignment "granularity" - 1. This 00182 * provides a mask for fast checking of whether alignment is 00183 * needed. Note that a value of zero really implies a granularity 00184 * of 1 (ie no padding). 00185 */ 00186 cup->ualign = *__fndc_align[cup->unumcvrt]; 00187 00188 if (cup->unumcvrt == 0) 00189 cup->ualignmask = (sizeof(long) << 3) - 1; /* 63 */ 00190 else { 00191 cup->ualignmask = MAX(cup->ualign.gran, 1) - 1; 00192 /* 00193 * If granularity is not a power of 2, then we force a 00194 * computation in COMPADD on every unformatted I/O request. 00195 */ 00196 if ( ! POWER_OF_TWO(cup->ualignmask + 1) ) 00197 cup->ualignmask = ~0; /* mask of one's */ 00198 } 00199 #endif 00200 /* 00201 * Set up sequential file truncation flag and the flag for special 00202 * handling of muliply-accessed files. Stdout and stderr default 00203 * to no truncation after final write. This is to avoid problems 00204 * if SHMEM applications redirect stdout to a regular file. A truncation 00205 * at close time can result in lost output from another process 00206 * sharing the same stdout file. 00207 */ 00208 cup->utrunc = 1; 00209 00210 if (cup->ufp.std != NULL) { 00211 register int fd = fileno(cup->ufp.std); 00212 if (fd == STDOUT_FILENO || fd == STDERR_FILENO) 00213 cup->utrunc = 0; 00214 } 00215 00216 if (aifound && aip->T_utrunc_flg) 00217 cup->utrunc = aip->T_utrunc; 00218 00219 if (aifound && aip->m_multup_flg && aip->m_multup) { 00220 cup->umultup = 1; 00221 cup->utrunc = 0; 00222 } 00223 /* 00224 * Detect some cases of the file not being a disk file. 00225 */ 00226 if (statp_valid && ! S_ISREG(statp->st_mode)) 00227 disk_file = 0; /* file exists and isn't a regular file */ 00228 00229 /* 00230 * Now we check for specifications which are mapped to FFIO. 00231 */ 00232 ffio_layer = NULL; 00233 00234 for (i = 0; i < FPARMAX; i++) 00235 num[i] = -1; /* assume we'll use layer defaults */ 00236 00237 00238 switch (tufs) { 00239 00240 /* 00241 * Map '-s sbin' to '-s text' for formatted opens. 00242 */ 00243 case STD: 00244 if (cup->ufmt) { 00245 errno = FEOPNFMT; /* Can't open FORMATTED */ 00246 return(-1); 00247 } 00248 break; 00249 /* 00250 * Map '-s text' to '-F text' if doing implicit data conversion. 00251 */ 00252 case FS_TEXT: 00253 if (cup->ufmt && cup->useq && cup->ucharset) 00254 ffio_layer = "text"; 00255 break; 00256 /* 00257 * Map '-s u' to '-F syscall -T off' 00258 * Map '-s u -a SDS -n xx' to '-F sds.scr.novfl:xx:xx:0 -T off' 00259 */ 00260 case FS_U: 00261 if (! (aifound && aip->T_utrunc_flg)) 00262 cup->utrunc = 0; /* no trunc by default with -s U */ 00263 00264 opt_flags = O_RAW; 00265 00266 if (aifound && aip->a_sdsfil_flg) { /* '-a SDS' requested */ 00267 register int presize; 00268 00269 if (aip->n_preall_flg) 00270 presize = aip->n_preall; 00271 else { /* SDS allocation failure */ 00272 errno = FESDSFSS; 00273 return(-1); 00274 } 00275 00276 ffio_layer = "sds.scr.novfl"; 00277 num[0] = presize; 00278 num[1] = presize; 00279 num[2] = 0; 00280 } 00281 else 00282 ffio_layer = "syscall"; 00283 break; 00284 00285 /* 00286 * Map f77 blocking with -b xx to '-F f77::(xx*BLKSIZE)' 00287 */ 00288 case FS_F77: 00289 ffio_layer = "f77"; 00290 if (aifound && aip->b_bufsiz_flg) 00291 num[1] = aip->b_bufsiz * BLKSIZE; 00292 break; 00293 00294 /* 00295 * Map '-s COS -b xx' to '-F cos:xx' 00296 */ 00297 case FS_COS: 00298 ffio_layer = "cos"; 00299 if (aifound && aip->b_bufsiz_flg) 00300 num[0] = aip->b_bufsiz; 00301 break; 00302 00303 00304 #if !defined(_UNICOS) && !defined(__mips) && !defined(_LITTLE_ENDIAN) 00305 /* 00306 * Map '-s unblocked' to '-s sbin' on non-UNICOS systems 00307 * Map '-s bin' to '-s sbin -T off' on non-UNICOS systems 00308 */ 00309 case FS_UNBLOCKED: 00310 case FS_BIN: 00311 if (tufs == FS_BIN) { 00312 if (! (aifound && aip->T_utrunc_flg)) 00313 cup->utrunc = 0; 00314 } 00315 /* 00316 * The only buffering scheme available on Sparc for unblocked 00317 * files is stdio, so we use it. 00318 */ 00319 tufs = STD; 00320 break; 00321 #endif /* !_UNICOS && !__mips && !_LITTLE_ENDIAN */ 00322 00323 #if defined(_UNICOS) || defined(__mips) || defined(_LITTLE_ENDIAN) 00324 /* 00325 * Map '-s unblocked' to '-s sbin' for non-disk files 00326 * Map '-s unblocked -b bs' to '-F bufa:bs' for seq disk files on Unicos 00327 * Map '-s unblocked -b bs' to '-s sbin' for seq disk files on MIPS 00328 * Map '-s unblocked -b bs -u nb' to '-F cachea:bs:nb' for direct acc files 00329 * 00330 * Map '-s bin' to the same, plus set "-T off" by default. 00331 * 00332 * Map unformatted FORM='SYSTEM' and FORM='BINARY' to -s unblocked. 00333 * There are no record control images for these two forms. 00334 */ 00335 case FS_UNBLOCKED: 00336 case FS_BIN: 00337 if (!disk_file) { 00338 tufs = STD; /* ttys and pipes use stdio */ 00339 break; 00340 } 00341 00342 if (cup->useq) { /* If sequential access file */ 00343 ffio_layer = "bufa"; 00344 num[0] = SUBUFSZ; 00345 } 00346 else { 00347 #if defined(__mips) || defined(_LITTLE_ENDIAN) 00348 ffio_layer = "cache"; 00349 #else 00350 ffio_layer = "cachea"; 00351 #endif 00352 num[0] = DUBUFSZ; 00353 } 00354 00355 if (tufs == FS_BIN) { 00356 if (! (aifound && aip->T_utrunc_flg)) 00357 cup->utrunc = 0; 00358 num[0] = DEF_BIN_BS; 00359 } 00360 00361 #ifdef _UNICOS_MAX 00362 if (_MPP_MPPSIM > 0) { 00363 /* 00364 * Running on simulator in user virtual mode. 00365 * Simulator cannot handle large reads/writes, 00366 * so adjust the default buffer size smaller. 00367 */ 00368 num[0] = _VALUE(_def_cch_simbufsiz); 00369 } 00370 #endif 00371 #if !defined(__mips) && !defined(_LITTLE_ENDIAN) 00372 /* 00373 * If the user has not requested a buffer size 00374 * with assign, ensure that the buffer size is 00375 * at least as large as the record size up to 00376 * a "reasonable" limit. At some point, the 00377 * user must take responsibility for assigning 00378 * lots of memory to I/O buffers. 00379 */ 00380 00381 if (!cup->useq && default_ftype && 00382 (DUBUFSZ * BLKSIZE) < cup->urecl) { 00383 register int bsize; 00384 00385 bsize = (cup->urecl + (BLKSIZE - 1)) / BLKSIZE; 00386 00387 if (bsize > 100) 00388 bsize = 100; 00389 00390 num[0] = bsize; 00391 } 00392 00393 #endif 00394 00395 if (aifound && aip->b_bufsiz_flg) 00396 num[0] = aip->b_bufsiz; 00397 00398 if (aifound && aip->u_bufcnt_flg) 00399 num[1] = aip->u_bufcnt; 00400 00401 break; 00402 #endif /* _UNICOS || __mips || _LITTLE_ENDIAN */ 00403 00404 #ifdef _UNICOS 00405 /* 00406 * Map '-s [bmx, tape, tape50, bmx50] -b bs -u nm' to '-F tape:bs:nm' 00407 */ 00408 case FS_TAPE: 00409 cup->ubmx = 1; /* Indicate that '-s tape' or '-s bmx' 00410 * was selected by the user. */ 00411 00412 case FS_TAPE50: /* Fall-through! */ 00413 00414 ffio_layer = "tape"; 00415 00416 if (aifound && aip->b_bufsiz_flg) 00417 num[0] = aip->b_bufsiz; 00418 00419 if (aifound && aip->u_bufcnt_flg) 00420 num[1] = aip->u_bufcnt; 00421 break; 00422 #endif /* _UNICOS */ 00423 } /* end switch(tufs) */ 00424 00425 if (tufs == FS_FDC) 00426 fdspec = &aip->F_filter[0]; 00427 else if (ffio_layer != NULL) { 00428 fdspec = specspace; 00429 make_fdspec(fdspec, ffio_layer, num); 00430 tufs = FS_FDC; 00431 } 00432 00433 /* 00434 * Only the FS_FDC paths through _frwd/_fwwd/_frch/_fwch handle 00435 * data conversion. 00436 */ 00437 if (tufs != FS_FDC && 00438 (!cup->ufmt && cup->unumcvrt || (cup->ufmt && cup->ucharset))) { 00439 errno = FENOICNV; 00440 return(-1); 00441 } 00442 00443 /* 00444 * Open the file with permissions dictated by the ACTION= specifier and 00445 * the system file permissions. When ACTION= is unspecified on the open, 00446 * try read/write, read-only, and write-only. 00447 * 00448 * When ACTION='WRITE' is specified, try read/write and write-only if the 00449 * file is a disk file. Read permission may be needed for support of 00450 * backspace and read-before-write buffer caching. If the file is not a 00451 * disk file, open as write-only since backspace and read-before-write 00452 * caching support are not needed. 00453 */ 00454 if (cup->uaction == OS_READWRITE || 00455 (cup->uaction == OS_WRITE && disk_file) || 00456 cup->uaction == OS_ACTION_UNSPECIFIED) { 00457 00458 flags = O_RDWR | o_sysflgs | opt_flags; 00459 00460 if (_do_open(cup, css, tufs, actnam, flags, aifound, aip, 00461 fdspec, catcherr) == 0) 00462 not_open = 0; 00463 } 00464 00465 if (not_open && 00466 (cup->uaction == OS_READ || 00467 cup->uaction == OS_ACTION_UNSPECIFIED)) { 00468 00469 flags = O_RDONLY | o_sysflgs | opt_flags; 00470 00471 if (_do_open(cup, css, tufs, actnam, flags, aifound, aip, 00472 fdspec, catcherr) == 0) 00473 not_open = 0; 00474 #if defined(__mips) || defined(_LITTLE_ENDIAN) 00475 else { 00476 /* 00477 * There is a bug in NFS for IRIX 6.2 through 6.5 systems 00478 * whereby an open with O_RDONLY|O_CREAT aborted if the 00479 * process only had read-only access to an existing file. 00480 * The O_CREAT is supposed to be ignored if the file 00481 * already exists, but that wasn't happening. To work 00482 * around this bug, we remove the O_CREAT flag and retry 00483 * the open. Someday, when these systems are no longer 00484 * supported, this code can be removed. 00485 */ 00486 flags = flags & ~O_CREAT; /* Remove O_CREAT bit */ 00487 00488 if (_do_open(cup, css, tufs, actnam, flags, aifound, 00489 aip, fdspec, catcherr) == 0) 00490 not_open = 0; 00491 } 00492 #endif 00493 } 00494 00495 if (not_open && 00496 (cup->uaction == OS_WRITE || 00497 cup->uaction == OS_ACTION_UNSPECIFIED)) { 00498 00499 flags = O_WRONLY | o_sysflgs | opt_flags; 00500 00501 if (_do_open(cup, css, tufs, actnam, flags, aifound, aip, 00502 fdspec, catcherr) == 0) 00503 not_open = 0; 00504 } 00505 00506 if (not_open) { 00507 /* 00508 * Replace error code EACCES with FEFILACT only when 00509 * ACTION= was specified on OPEN. 00510 */ 00511 if (cup->uaction != OS_ACTION_UNSPECIFIED && errno == EACCES) 00512 errno = FEFILACT; /* invalid ACTION for this file */ 00513 return(-1); 00514 } 00515 00516 acc_mode = flags & O_ACCMODE; 00517 cup->usysread = (acc_mode == O_RDONLY || acc_mode == O_RDWR); 00518 cup->usyswrite = (acc_mode == O_WRONLY || acc_mode == O_RDWR); 00519 00520 /* 00521 * Be sure to set uaction if ACTION= was not specified on the OPEN. 00522 */ 00523 if (cup->uaction == OS_ACTION_UNSPECIFIED) 00524 cup->uaction = cup->uaction | 00525 (cup->usysread ? OS_READ : 0) | 00526 (cup->usyswrite ? OS_WRITE : 0); 00527 00528 /* 00529 * Set cup->ufs to indicate that the underlying open has succeeded. 00530 */ 00531 cup->ufs = tufs; 00532 00533 /* 00534 * Tape file setup for the assign -d option. 00535 */ 00536 if (aifound && aip->d_datrcv_flg) { 00537 register int ret; 00538 00539 if (tufs != FS_FDC) { 00540 errno = FENOSKPB; 00541 return(-1); 00542 } 00543 #if !defined(__mips) && !defined(_LITTLE_ENDIAN) 00544 ret = XRCALL(cup->ufp.fdc, fcntlrtn) cup->ufp.fdc, FC_AUTOBAD, 00545 ((aip->d_datrcv == AS_SKIPBAD) ? AUTO_SKIP : AUTO_ACPT), 00546 &cup->uffsw); 00547 00548 if (ret < 0) { 00549 errno = cup->uffsw.sw_error; 00550 return(-1); 00551 } 00552 #else 00553 return(-1); 00554 #endif 00555 } 00556 00557 /* 00558 * Initialize the asynchronous status structure. This word is 00559 * passed a little differently for async and for synchronous I/O. 00560 * The WAITIO macro is called anytime an outstanding request could 00561 * be pending, and appropriate processing done to ensure that the 00562 * the status field is set in the ffsw. 00563 */ 00564 FFSTAT(cup->uffsw) = FFBOD; /* at beginning of data */ 00565 cup->uffsw.sw_error = 0; 00566 cup->uffsw.sw_count = 0; 00567 00568 /* 00569 * Set cf77, cf90, irixf77, or irixf90 mode. Retain uft90 for 00570 * simple tests between f77 and f90. Use the ufcompat for other 00571 * differences. 00572 */ 00573 00574 cup->ufcompat = 0; 00575 00576 if ( aifound && aip->f_fortst_flg ) { 00577 (cup->uft90 = (aip->f_fortst == AS_FORTRAN90) ? 1 : 00578 (cup->uft90 = (aip->f_fortst == AS_IRIX_F90) ? 1 : 0)); 00579 cup->ufcompat = aip->f_fortst; 00580 } 00581 00582 if ( aifound && aip->t_tmpfil_flg ) { 00583 cup->uscrtch = 1; 00584 cup->utmpfil = 1; 00585 } 00586 00587 /* 00588 * Set up list-directed output format for MPP, PVP, and IRIX 00589 * systems. Set the global values first. Allow individual 00590 * flags to override the global flag. Note that default is 00591 * the same for all systems except for the namelist skip. 00592 * Also set the default for writing -0.0 for formatted io. 00593 */ 00594 cup->ufunilist = 0; 00595 cup->ufcomsep = 0; 00596 cup->ufcomplen = 0; 00597 cup->ufrptcnt = 0; 00598 #if !defined(__mips) && !defined(_LITTLE_ENDIAN) 00599 cup->ufnl_skip = 0; 00600 cup->ufnegzero = 0; 00601 #else 00602 cup->ufnl_skip = 1; 00603 cup->ufnegzero = 1; 00604 #endif 00605 00606 /* 00607 * If the global list-directed output flag is set for UNICOS, 00608 * set the individual flags to the same value as the global 00609 * flag. 00610 */ 00611 if ( aifound && aip->U_unicoslist_flg ) { 00612 cup->ufunilist = aip->U_unicoslist; 00613 cup->ufcomsep = aip->U_unicoslist; 00614 cup->ufcomplen = aip->U_unicoslist; 00615 cup->ufrptcnt = aip->U_unicoslist; 00616 } else if (aifound && aip->f_fortst == AS_IRIX_F77) { 00617 /* 00618 * If the global list-directed output flag is not set and 00619 * the f irixf77 option is specified, set the individual 00620 * individual flags to the MIPS f77 default values. 00621 */ 00622 cup->ufunilist = 1; 00623 cup->ufcomsep = 1; 00624 cup->ufcomplen = 1; 00625 cup->ufrptcnt = 1; 00626 } 00627 00628 /* Override the global list-directed output settings if 00629 * individual flags are set. 00630 */ 00631 if ( aifound && aip->S_comsep_flg ) { 00632 cup->ufcomsep = aip->S_comsep; 00633 } 00634 00635 if ( aifound && aip->W_compwidth_flg ) { 00636 cup->ufcomplen = aip->W_compwidth; 00637 } 00638 00639 if ( aifound && aip->y_reptcnt_flg ) { 00640 cup->ufrptcnt = aip->y_reptcnt; 00641 } 00642 00643 /* 00644 * Override global setting for writing -0.0 in formatted io. 00645 * Default setting for irix: Do not write minus sign for -0.0. 00646 * Default setting for all PVP,ieee platforms: Write minus sign 00647 * for -0.0. 00648 */ 00649 if ( aifound && aip->Z_neg_zero_flg ) { 00650 cup->ufnegzero = aip->Z_neg_zero; 00651 } 00652 00653 /* 00654 * Set up namelist input behavior for MPP, PVP, IRIX systems 00655 * when cilist namelist group name does not match the group 00656 * name provided in the namelist input record. The default 00657 * is to error on UNICOS and UNICOS/mk and to skip on IRIX. 00658 */ 00659 if ( aifound && aip->Y_nl_skip_flg ) { 00660 cup->ufnl_skip = aip->Y_nl_skip; 00661 } 00662 00663 /* 00664 * Set cup->ublkd and fd in a variety of ways. 00665 */ 00666 switch( cup->ufs ) { 00667 register int ret; 00668 00669 case FS_TEXT: 00670 fd = fileno ( cup->ufp.std ); 00671 if (cup->ufmt == 0) { 00672 errno = FEOPNUNF; /* Can't open UNFORMATTED */ 00673 return(-1); 00674 } 00675 cup->ublkd = 1; 00676 break; 00677 00678 case STD: 00679 fd = fileno ( cup->ufp.std ); 00680 if (cup->ufmt) 00681 cup->ublkd = 1; /* no stdio blocking if formatted */ 00682 else 00683 cup->ublkd = 0; /* no stdio blocking if unformtd */ 00684 break; 00685 00686 case FS_FDC: 00687 /* 00688 * Get file descriptor and other info for FDC files 00689 */ 00690 ret = XRCALL(cup->ufp.fdc, fcntlrtn) cup->ufp.fdc, 00691 FC_GETINFO, &info, &ffiostat); 00692 if (ret < 0) { 00693 errno = ffiostat.sw_error; 00694 return(-1); 00695 } 00696 00697 cup->uflagword = info.ffc_flags; 00698 00699 /* 00700 * Get stat information. 00701 */ 00702 ret = XRCALL(cup->ufp.fdc, fcntlrtn) cup->ufp.fdc, 00703 FC_STAT, &ffio_statbuf, &ffiostat); 00704 if (ret < 0) { 00705 errno = ffiostat.sw_error; 00706 return(-1); 00707 } 00708 00709 _ffconvert_stat(&ffio_statbuf, statp); 00710 statp_valid = 1; 00711 00712 /* 00713 * Indicate whether the file knows about EOR 00714 */ 00715 cup->ublkd = ((cup->uflagword & FFC_REC) ? 1 : 0); 00716 /* 00717 * Indicate whether the file permits multiple endfile records. 00718 * Assume that a file has a physical endfile representation if 00719 * and only if multiple endfile records are permitted. 00720 */ 00721 cup->umultfil = ((cup->uflagword & FFC_WEOF) ? 1 : 0); 00722 00723 if (cup->ufmt) { 00724 /* 00725 * Formatted files must be capable of handling text. 00726 */ 00727 if ((info.ffc_flags & FFC_CODED) == 0) { 00728 errno = FEOPNFMT; /* Can't open FORMATTED */ 00729 return(-1); 00730 } 00731 /* 00732 * Sequential formatted files must have a record 00733 * structure. 00734 */ 00735 if (cup->useq && (info.ffc_flags & FFC_REC) == 0) { 00736 errno = FEOPNFMT; /* Can't open FORMATTED */ 00737 return(-1); 00738 } 00739 } 00740 else { 00741 /* 00742 * Unformatted files must be capable of handling 00743 * binary data. 00744 */ 00745 if ((info.ffc_flags & FFC_BINARY) == 0) { 00746 errno = FEOPNUNF; /* Can't open UNFORMATTED */ 00747 return(-1); 00748 } 00749 } 00750 /* 00751 * Make sure the capabilities are right to do DA, if requested. 00752 */ 00753 if (cup->useq == 0) { /* If direct access */ 00754 /* 00755 * If layer has a fixed record length, make sure it 00756 * matches the REC= on the OPEN. 00757 */ 00758 if (info.ffc_reclen != 0) { 00759 if (info.ffc_reclen != (cup->urecl << 3)) { 00760 /* reclen does not match file */ 00761 errno = FEOPIVRL; 00762 return(-1); 00763 } 00764 } 00765 /* 00766 * If not fixed length records, it better be stream. 00767 * If not, (variable length recs?) blow the user off. 00768 */ 00769 else if ((cup->uflagword & FFC_STRM) == 0) { 00770 errno = FEOPNNDA; 00771 return(-1); 00772 } 00773 } 00774 /* 00775 * Make sure that user-requested suppression of truncation after 00776 * write is supported by the top FFIO layer. 00777 */ 00778 if (cup->useq && aifound && aip->T_utrunc_flg && 00779 aip->T_utrunc == 0 && 00780 (info.ffc_flags & FFC_WRTRUNC)) { 00781 00782 errno = FERQTRNC; /* must trunc after write */ 00783 return(-1); 00784 } 00785 00786 fd = info.ffc_fd; 00787 break; 00788 00789 default: 00790 errno = FEINTFST; 00791 return(-1); 00792 } 00793 00794 cup->usysfd = fd; 00795 00796 /* 00797 * From this point on, the stat buffer pointed to by statp will be valid 00798 * for ALL files. 00799 */ 00800 if (! statp_valid && fstat(fd, statp) == -1) 00801 return(-1); 00802 statp_valid = 1; 00803 00804 /* 00805 * The useek field is used only for STD files. 00806 */ 00807 if (fd != -1) { 00808 if ((S_ISREG(statp->st_mode) && !isatty(fd)) || 00809 _gsys_qtape(statp)) 00810 cup->useek = YES; 00811 else 00812 cup->useek = NO; 00813 } 00814 00815 #ifdef _UNICOS 00816 /* 00817 * Do preallocation as specified by -n/-p/-q 00818 */ 00819 if (fd != -1) { 00820 if (_prealloc(fd, aifound, aip, statp) == -1) 00821 return(-1); 00822 } 00823 #endif 00824 00825 /* 00826 * See if asynchronous I/O is OK. 00827 * Asynchronous I/O is only allowed if no data conversion is active and 00828 * some form of FFIO is being used. All FFIO should have an async 00829 * entry, even though it may not *actually* be asynchronous. 00830 */ 00831 cup->uasync = ASYNC_NOTOK; /* assume that async is NOT OK. */ 00832 00833 if ((cup->unumcvrt | cup->ucharset) == 0 && cup->ufs == FS_FDC) { 00834 cup->uasync = ASYNC_OK; /* async I/O is OK */ 00835 } 00836 00837 /* 00838 * Set up the udamax field. This is the 1-based maximum record number 00839 * for direct access files. 00840 */ 00841 if (cup->useq == 0) { /* If direct access */ 00842 long recl; 00843 recl = cup->urecl; 00844 if (cup->ufmt && cup->ufs != FS_FDC) 00845 recl++; 00846 /* allow the last record to be shorter than recl */ 00847 cup->udamax = (statp->st_size + recl - 1) / recl; 00848 } 00849 00850 return(0); 00851 } 00852 00853 /* 00854 * make_fdspec - assembles the fdspec which can be passed to _ffopen 00855 * 00856 * Return value 00857 * Always returns 0. 00858 */ 00859 static int 00860 make_fdspec( 00861 union spec_u *fdspec, /* output - receives the fdspec */ 00862 char *layer, /* the layer name */ 00863 int num[FPARMAX]) /* the numeric parameters; -1 00864 * indicates no parameter */ 00865 { 00866 register short i; 00867 register int ret; 00868 char buf[FPARMAX][30]; /* each must be big enough for MAXINT */ 00869 char ffio_str[20+FPARMAX*30];/* holds layer string and up to 3 00870 * integers */ 00871 00872 for (i = 0; i < FPARMAX; i++) { 00873 if (num[i] == -1) 00874 buf[i][0] = '\0'; /* empty string */ 00875 else 00876 sprintf(buf[i], "%d", num[i]); 00877 } 00878 00879 /* Assume FPARMAX is <= 3 */ 00880 00881 (void) sprintf(ffio_str, "%s:%s:%s:%s", layer, buf[0], buf[1], buf[2]); 00882 00883 ret = _parse_forstr(fdspec, ffio_str, SPECSZ, 0, _LELVL_RETURN); 00884 00885 if (ret < 0) 00886 _ferr(NULL, FEINTUNK); /* shouldn't happen */ 00887 00888 return(0); 00889 } 00890 00891 /* 00892 * According to the file structure make the appropriate call to 00893 * open the file. Open routines are file structure dependent. 00894 * 00895 * Return value is 0 on success, -1 on error with errno set. 00896 * 00897 * If catcherr == 0, some errors will abort here. Others do not cause 00898 * an abort because _do_open might be retried with different permissions. 00899 */ 00900 int 00901 _do_open( 00902 unit *cup, 00903 FIOSPTR css, 00904 int tufs, 00905 char *actnam, 00906 int flags, 00907 int aifound, 00908 assign_info *aip, 00909 union spec_u *fdspec, 00910 int catcherr) 00911 { 00912 long bs; 00913 register int cbits; 00914 register int cblks; 00915 register int i; 00916 long asave[(AFLAGSIZE + sizeof(long)) / sizeof(long)]; 00917 char *flagstr; 00918 char *attrstr; 00919 struct ffsw ffiostat; 00920 struct gl_o_inf gloinf; 00921 _ffopen_t otmp; 00922 00923 (void) memset(&gloinf, 0, sizeof(gloinf)); 00924 00925 gloinf.open_type = OT_FORTRAN; 00926 gloinf.aip = aifound ? aip : NULL; 00927 gloinf.u.fort.unum = cup->uid; 00928 gloinf.u.fort.is_seq = cup->useq; 00929 gloinf.u.fort.is_fmt = cup->ufmt; 00930 gloinf.u.fort.reclen = cup->urecl; 00931 00932 cbits = 0; 00933 cblks = 0; 00934 00935 /* 00936 * Handle -B, -r, -x, -w,-L, and -l assign options. 00937 */ 00938 if (aifound) 00939 _ae_setoflags(aip, &flags); 00940 00941 #ifdef _UNICOS 00942 /* 00943 * Handle -p and -q assign options. 00944 */ 00945 if (aifound && aip->pr_partit_flg) { 00946 flags = flags | O_PLACE; 00947 cbits = aip->pr_partit; 00948 } 00949 00950 if (aifound && (aip->n_stride_flg || aip->q_ocblks_flg)) { 00951 flags = flags | O_PLACE; 00952 00953 if (aip->q_ocblks_flg) 00954 cblks = aip->q_ocblks; 00955 else 00956 cblks = aip->n_stride; 00957 } 00958 #endif /* _UNICOS */ 00959 00960 switch ( tufs ) { 00961 00962 case FS_TEXT: 00963 case STD: 00964 00965 /* 00966 * If this is a standard file which is already open, skip 00967 * the open system call, but validate the flags. 00968 */ 00969 if (cup->ufp.std != NULL) { 00970 register int fdflags; 00971 00972 #if !defined(_LITTLE_ENDIAN) || (defined(_LITTLE_ENDIAN) && defined(__sv2)) 00973 if (cup->ufp.std->_flag & _IORW) 00974 fdflags = O_RDWR; 00975 else if (cup->ufp.std->_flag & _IOWRT) 00976 fdflags = O_WRONLY; 00977 else 00978 fdflags = O_RDONLY; 00979 00980 if ((fdflags & O_ACCMODE) != (flags & O_ACCMODE)) { 00981 errno = EACCES; 00982 return(-1); 00983 } 00984 #endif 00985 } 00986 else { 00987 00988 #ifdef _UNICOS 00989 /* 00990 * _stdio_open is a duplicate name for open() 00991 * It is used ONLY by code in libc/stdio and here, 00992 * because this is nearly equivalent to an 00993 * "fopen". _stdio_open is used so that the opens 00994 * from these routines will be unique. It was 00995 * requested by marketing. 00996 */ 00997 #ifndef _CRAYMPP 00998 i = _stdio_open( 00999 #else 01000 i = open( 01001 #endif 01002 actnam, flags, ACCESS_PERMS, cbits, cblks); 01003 #else /* ! _UNICOS */ 01004 i = open( actnam, flags, ACCESS_PERMS); 01005 #endif /* ! _UNICOS */ 01006 if (i < 0) 01007 return(-1); 01008 01009 if ((flags & O_ACCMODE) == O_RDWR) 01010 flagstr = "r+"; 01011 else if ((flags & O_ACCMODE) == O_WRONLY) { 01012 if (flags & O_APPEND) 01013 flagstr = "a"; 01014 else 01015 flagstr = "w"; 01016 } 01017 else 01018 flagstr = "r"; 01019 01020 MEM_LOCK(&_ioblock); /* Lock libf access to iob table*/ 01021 01022 cup->ufp.std = fdopen(i, flagstr); 01023 01024 MEM_UNLOCK(&_ioblock); /* Unlock iob table */ 01025 01026 if (cup->ufp.std == NULL) 01027 return(-1); 01028 } 01029 01030 /* 01031 * Set up buffer size. If file is direct access, then there 01032 * is no advantage in having a buffer size larger than the 01033 * record size because stdio ends up flushing each record 01034 * anyway. For formatted I/O, add one byte for the newline. 01035 * Finally, ensure than the buffer size is at least two words. 01036 */ 01037 bs = DEF_SBIN_BS * BLKSIZE; /* Set default size */ 01038 01039 #ifdef _UNICOS_MAX 01040 /* 01041 * If running on simulator in user virtual mode, restrict 01042 * the since since the simulation cannot handle large reads 01043 * and writes. 01044 */ 01045 if (_MPP_MPPSIM > 0) 01046 bs = DEF_SBINSIM_BS * BLKSIZE; 01047 #endif 01048 01049 if (aifound && aip->b_bufsiz_flg) 01050 bs = aip->b_bufsiz * BLKSIZE; 01051 else 01052 if (cup->useq == 0 && cup->urecl < bs) { 01053 bs = cup->urecl + (cup->ufmt ? 1 : 0); 01054 if (bs < 16) 01055 bs = 16; 01056 } 01057 01058 /* 01059 * We may only call setvbuf if the file has seen no read/write 01060 * activity. The buffer will not be allocated unless there 01061 * have been reads or writes. This check is necessary for 01062 * standard files. 01063 * 01064 * We do not allow DEF_SBIN_BS or the -b option to override 01065 * the _IONBF buffering mode for stderr or _IOLBF buffering 01066 * for tty files. In both cases, stdio picks appropriate 01067 * buffer sizes. 01068 */ 01069 #if defined(_LITTLE_ENDIAN) && !defined(__sv2) 01070 if (cup->ufp.std->_IO_buf_base == NULL && 01071 fileno(cup->ufp.std) != STDERR_FILENO && 01072 ! isatty(fileno(cup->ufp.std))) 01073 (void) setvbuf(cup->ufp.std, NULL, _IOFBF, bs); 01074 #else 01075 if (cup->ufp.std->_base == NULL && 01076 fileno(cup->ufp.std) != STDERR_FILENO && 01077 ! isatty(fileno(cup->ufp.std))) 01078 01079 (void) setvbuf(cup->ufp.std, NULL, _IOFBF, bs); 01080 #endif 01081 01082 break; /* DONE */ 01083 01084 case FS_FDC: 01085 01086 #ifdef _UNICOS 01087 /* 01088 * Set the raw bit. It is unlikely to hurt, and will 01089 * frequently help performance. 01090 */ 01091 flags = flags | O_RAW; 01092 #endif 01093 if (aifound) 01094 _attr_copy(aip, (assign_info *)&asave); 01095 01096 otmp = _ffopen(actnam, flags, ACCESS_PERMS, fdspec, 01097 &ffiostat, cbits, cblks, NULL, &gloinf); 01098 if (otmp == _FFOPEN_ERR) { 01099 /* 01100 * Restore the ATTR_USED flags in case _do_open 01101 * is called in a retry. 01102 */ 01103 if (aifound) 01104 _attr_copy((assign_info *)&asave, aip); 01105 01106 errno = ffiostat.sw_error; 01107 return(-1); 01108 } 01109 01110 cup->ufp.fdc = (struct fdinfo *) otmp; 01111 cup->useek = YES; 01112 attrstr = NULL; 01113 01114 if (aifound && _attr_used(aip, &attrstr) == -1) { 01115 if (catcherr == 0) 01116 _ferr(css, errno, attrstr); 01117 return(-1); 01118 } 01119 01120 break; 01121 01122 default: 01123 errno = FEINTFST; 01124 return(-1); 01125 01126 } 01127 return(0); 01128 } 01129 01130 /* 01131 * This function converts an "ffc_stat_s" structure to a "stat" structure. 01132 * Currently, these structures are identical. If they ever diverge, 01133 * this function would call sysconf() or in some other way detect which 01134 * version of struct stat was being used. Then the ffc_stat_s structure 01135 * would be translated into the stat structure. 01136 */ 01137 void 01138 _ffconvert_stat(struct ffc_stat_s *src, struct stat *dest) 01139 { 01140 assert ( sizeof(*src) == sizeof(*dest) ); 01141 01142 *dest = *(struct stat *)src; 01143 01144 return; 01145 }