unitclose.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/unitclose.c        92.2    06/18/99 18:38:26"
00039 
00040 #include <errno.h>
00041 #ifndef _ABSOFT
00042 #include <malloc.h>
00043 #else
00044 #include <stdlib.h>
00045 #endif
00046 #include <stdio.h>
00047 #include <string.h>
00048 #include <unistd.h>
00049 #include <liberrno.h>
00050 #include <cray/nassert.h>
00051 #include <sys/param.h>
00052 #include <sys/stat.h>
00053 #include "fio.h"
00054 
00055 extern short    _f_abort;       /* Abort flag - set in _f_sig() */
00056 
00057 /*
00058  *      _unit_close
00059  *
00060  *              Closes a Fortran unit.  On exit, the unit is closed and 
00061  *              optionally deallocated with the appropriate locks unlocked.
00062  *
00063  *              Upon entry, the unit pointer passed in must be locked, and
00064  *              the _openlock word must be locked.
00065  *
00066  *              This routine also posts CLOSE statistics for the unit if
00067  *              statistics gathering is active.
00068  *
00069  *      Arguments
00070  *
00071  *              cup     - Unit pointer
00072  *              cstat   - STATUS= specifier--CLST_UNSPEC, CLST_KEEP, or
00073  *                        CLST_DELETE.
00074  *
00075  *      Return value:
00076  *               0      normal return
00077  *              >0      system or library error status
00078  */
00079 
00080 int
00081 _unit_close(
00082         unit    *cup,   /* Unit table pointer */
00083         int     cstat,  /* STATUS= specifier value on CLOSE */
00084         FIOSPTR cssa)   /* non-NULL if called from _CLS() for explicit CLOSE */
00085 {
00086         register short  delete; /* 1 if file should be deleted          */
00087         register int    ret;    /* Return status                        */
00088         register int    errn;   /* Status from low-level close operation*/
00089         plock_t         *lockp; /* Copy of auxiliary lock pointer       */
00090         struct ffsw     fst;    /* ffclose() status                     */
00091         struct fiostate state;  /* Local Fortran I/O state structure    */
00092         FIOSPTR         css; 
00093 
00094         if (cup == NULL)        /* If unit not connected */
00095                 return(0);      
00096 
00097         assert ( cstat == CLST_UNSPEC ||
00098                  cstat ==   CLST_KEEP ||
00099                  cstat == CLST_DELETE );
00100 
00101         if (cssa != NULL)       /* If processing an explicit CLOSE */
00102                 css     = cssa;
00103         else {                  /* If implicit/automatic close */
00104                 (void) memset(&state, 0, sizeof(state)); /* be extra safe */
00105                 css     = &state;
00106 #ifdef  _UNICOS
00107                 css->f_rtbgn    = _rtc();
00108 #endif
00109         }
00110 
00111         cup->uend       = BEFORE_ENDFILE;
00112         errn            = 0;
00113         delete          = (cstat == CLST_DELETE || cup->uscrtch) ? 1 : 0;
00114 
00115         lockp   = cup->auxlockp; /* copy aux lock pointer for later */
00116 
00117         if (delete && !cup->utmpfil) {
00118                 ret     = _unit_scratch(cup);
00119                 errn    = errn ? errn : ret;
00120         }
00121 
00122 /*
00123  *      Write out the current record if the last I/O was a nonadvancing WRITE.
00124  */
00125         if (cup->pnonadv) {             /* There is a current record */
00126                 if (cup->uwrt) {
00127                         ret     = _nonadv_endrec(css, cup);
00128                         errn    = errn ? errn : ret;
00129                 }
00130                 cup->pnonadv    = 0;    /* Flag no current record */
00131         }
00132 
00133 /*
00134  *      Truncate sequential files after last write if cup->utrunc.
00135  */
00136         if (cup->useq && cup->uwrt && cup->utrunc) {
00137                 ret     = _unit_trunc(cup);
00138                 errn    = errn ? errn : ret;
00139         }
00140 
00141 /*
00142  *      Perform the close of the lower level file structure only if
00143  *      it is not a standard file.
00144  */
00145         if ( ! ((cup->ufs == STD || cup->ufs == FS_TEXT) &&
00146                 (cup->ufp.std == stdin ||
00147                  cup->ufp.std == stdout ||
00148                  cup->ufp.std == stderr)) ) {
00149 
00150                 switch (cup->ufs) {
00151 
00152                 case FS_FDC:
00153                         if ( !_f_abort || !(cup->uflagword & FFC_NOCLOSE))
00154                                 if (__ffclose(cup->ufp.fdc, &fst) < 0)
00155                                         errn    = errn ? errn : fst.sw_error;
00156                         break;
00157 
00158                 case FS_TEXT:
00159                 case STD:
00160                                 
00161                         if (fclose(cup->ufp.std) != 0)
00162                                 errn    = errn ? errn : errno;
00163                         break;
00164 
00165                 case FS_AUX:
00166                         errn    = errn ? errn : FEMIXAUX;
00167 
00168                 default:
00169                         errn    = errn ? errn : FEINTFST; /* Unknown file type */
00170                 } /* switch */
00171         }
00172 
00173 /*
00174  *      Unlock the lockp word.   This is a pointer to a lock word
00175  *      shared by another unit, usually cup->ufp.std->_lock.  
00176  */
00177         if (lockp != NULL)
00178                 MEM_UNLOCK(lockp);
00179 
00180 /*
00181  *      Post final statistics and deallocate the statistics packet.
00182  */
00183         FSTATS_POST(cup, T_CLOSE, css); /* Post CLOSE statistics */
00184 
00185         _ft_stclose(cup);               /* Send close packet to procstat
00186                                          * and then deallocate it.      */
00187 
00188 /* 
00189  *      Deallocation of structures pointed to by the unit table follows
00190  */
00191         if (cup->ulinebuf != NULL)
00192                 free(cup->ulinebuf);
00193 
00194         if (cup->upfcstk != NULL)
00195                 free(cup->upfcstk);
00196 
00197         if (cup->urepdata != NULL)
00198                 free(cup->urepdata);
00199 
00200 /*
00201  *      Free ufnm and alfnm.  
00202  */
00203         if (cup->ufnm != NULL)
00204                 free(cup->ufnm);
00205 
00206         if (cup->alfnm != NULL)
00207                 free(cup->alfnm);
00208  
00209 /*
00210  *      Mark the unit as unopen.
00211  */
00212         cup->ufs        = 0;
00213 
00214         return(errn);
00215 }
00216   
00217 /*
00218  *      _unit_scratch()
00219  *
00220  *              Unlink the file associated with a unit.  For some file types, 
00221  *              this operation affects subsequent close processing so as to
00222  *              suppress buffer flushing before the close.   
00223  *
00224  *      Return value
00225  *              0  on success
00226  *              >1 on error
00227  *
00228  *      Side effects
00229  *
00230  *              cup->uscrtch    is set to 1.
00231  *              cup->unlinked   is set to 1 if the file was unlinked.
00232  *              cup->usnglink   is set to 1 if the file is not a symbolic link 
00233  *                              and the file link count is 1.
00234  *
00235  *              The optimization in close processing to suppress buffer flushes
00236  *              may only occur if (cup->unlinked && cup->usnglink).
00237  */
00238 int 
00239 _unit_scratch(unit *cup)
00240 {
00241         register int    ret;
00242 
00243         cup->uscrtch    = 1;
00244 
00245 #ifdef  FC_SCRATCH
00246         if (cup->ufs == FS_FDC) {
00247                 int             scrflags;
00248                 struct ffsw     ffst;
00249 
00250                 cup->unlinked   = 0;
00251                 cup->usnglink   = 0;
00252 
00253 
00254                 /*
00255                  * Use the FC_SCRATCH request to unlink the file, check if it 
00256                  * is a linked file and possibly setup close processing to 
00257                  * suppress buffer flushes.
00258                  */
00259                 ret     = XRCALL(cup->ufp.fdc, fcntlrtn) cup->ufp.fdc,
00260                         FC_SCRATCH, &scrflags, &ffst);
00261 
00262                 if (ret == 0) {
00263                         cup->unlinked   = (scrflags & SCR_UNLINKED)   ? 1 : 0;
00264                         cup->usnglink   = (scrflags & SCR_SINGLELINK) ? 1 : 0;
00265                         return(0);
00266                 }
00267 
00268                 /* Fall through on error;  FC_SCRATCH might not be supported */
00269         }
00270 #endif
00271 
00272         cup->usnglink   = 0;    /* assume multiple links */
00273 
00274 /*
00275  *      Perform the unlink only if connected to a real file.  Permit ENOENT
00276  *      errors in case a layer like mr.scr had closed the file at open time
00277  *      even though STATUS='SCRATCH' might not have been specified on the OPEN.
00278  *
00279  *      If the file has already been unlinked, or if the file has been renamed
00280  *      and a different file is now there with the same name, ignore the error.
00281  */
00282         if (cup->alfnm != NULL && cup->usysfd >= 0) {
00283                 struct stat     sbuf;
00284 
00285                 ret     = stat(cup->alfnm, &sbuf);
00286 
00287                 if (ret != -1) {        /* If not already unlinked */
00288 
00289                         /*
00290                          * Ensure the device and inode number match before
00291                          * we pull the trigger.
00292                          */
00293 
00294                         if (sbuf.st_ino != cup->uinode ||
00295                             sbuf.st_dev != cup->udevice)
00296                                 return(FENODELT);       /* Can't delete file */
00297                         else {
00298 
00299                                 ret     = unlink(cup->alfnm);
00300 
00301                                 if (ret == -1 && errno != ENOENT)
00302                                         return(errno);
00303                         }
00304                 }
00305 
00306                 cup->unlinked   = 1;
00307         }
00308 
00309         return(0);
00310 }

Generated on Thu Dec 18 05:52:17 2008 for Open64 (mfef90, whirl2f, and IR tools) by  doxygen 1.5.7.1