Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
fopn.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines