1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 30*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include "synonyms.h" 34*7c478bd9Sstevel@tonic-gate #include "mtlib.h" 35*7c478bd9Sstevel@tonic-gate #include "file64.h" 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #define _iob __iob 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 40*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 41*7c478bd9Sstevel@tonic-gate #include <stdio.h> 42*7c478bd9Sstevel@tonic-gate #include <thread.h> 43*7c478bd9Sstevel@tonic-gate #include <synch.h> 44*7c478bd9Sstevel@tonic-gate #include <unistd.h> 45*7c478bd9Sstevel@tonic-gate #include <string.h> 46*7c478bd9Sstevel@tonic-gate #include "stdiom.h" 47*7c478bd9Sstevel@tonic-gate #include <wchar.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 49*7c478bd9Sstevel@tonic-gate #include <stddef.h> 50*7c478bd9Sstevel@tonic-gate #include <errno.h> 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #undef end 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #define FILE_ARY_SZ 8 /* a nice size for FILE array & end_buffer_ptrs */ 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #ifdef _LP64 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * Macros to declare and loop over a fp or fp/xfp combo to 60*7c478bd9Sstevel@tonic-gate * avoid some of the _LP64 ifdef hell. 61*7c478bd9Sstevel@tonic-gate */ 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #define FPDECL(fp) FILE *fp 64*7c478bd9Sstevel@tonic-gate #define FIRSTFP(lp, fp) fp = lp->iobp 65*7c478bd9Sstevel@tonic-gate #define NEXTFP(fp) fp++ 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate #define xFILE FILE 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #else 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate #define FPDECL(fp) FILE *fp; xFILE *x##fp 72*7c478bd9Sstevel@tonic-gate #define FIRSTFP(lp, fp) x##fp = lp->iobp; \ 73*7c478bd9Sstevel@tonic-gate fp = x##fp ? &x##fp->_iob : &_iob[0] 74*7c478bd9Sstevel@tonic-gate #define NEXTFP(fp) (x##fp ? fp = &(++x##fp)->_iob : ++fp) 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* The extended 32-bit file structure for use in link buffers */ 77*7c478bd9Sstevel@tonic-gate typedef struct xFILE { 78*7c478bd9Sstevel@tonic-gate FILE _iob; /* must be first! */ 79*7c478bd9Sstevel@tonic-gate struct xFILEdata _xdat; 80*7c478bd9Sstevel@tonic-gate } xFILE; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate #define xmagic _xdat._magic 83*7c478bd9Sstevel@tonic-gate #define xend _xdat._end 84*7c478bd9Sstevel@tonic-gate #define xlock _xdat._lock 85*7c478bd9Sstevel@tonic-gate #define xstate _xdat._state 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate #define FILEx(fp) ((struct xFILE *)(uintptr_t)fp) 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate /* 90*7c478bd9Sstevel@tonic-gate * The magic number stored is actually the pointer scrambled with 91*7c478bd9Sstevel@tonic-gate * a magic number. Pointers to data items live everywhere in memory 92*7c478bd9Sstevel@tonic-gate * so we scramble the pointer in order to avoid accidental collisions. 93*7c478bd9Sstevel@tonic-gate */ 94*7c478bd9Sstevel@tonic-gate #define XFILEMAGIC 0x63687367 95*7c478bd9Sstevel@tonic-gate #define XMAGIC(xfp) ((uintptr_t)(xfp) ^ XFILEMAGIC) 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate struct _link_ /* manages a list of streams */ 100*7c478bd9Sstevel@tonic-gate { 101*7c478bd9Sstevel@tonic-gate xFILE *iobp; /* the array of (x)FILE's */ 102*7c478bd9Sstevel@tonic-gate /* NULL for the __first_link in ILP32 */ 103*7c478bd9Sstevel@tonic-gate int niob; /* length of the arrays */ 104*7c478bd9Sstevel@tonic-gate struct _link_ *next; /* next in the list */ 105*7c478bd9Sstevel@tonic-gate }; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate /* 108*7c478bd9Sstevel@tonic-gate * With dynamic linking, iob may be in either the library or in the user's 109*7c478bd9Sstevel@tonic-gate * a.out, so the run time linker fixes up the first entry in __first_link at 110*7c478bd9Sstevel@tonic-gate * process startup time. 111*7c478bd9Sstevel@tonic-gate * 112*7c478bd9Sstevel@tonic-gate * In 32 bit processes, we don't have xFILE[FILE_ARY_SZ] but FILE[], 113*7c478bd9Sstevel@tonic-gate * and _xftab[] instead; this is denoted by having iobp set to NULL in 114*7c478bd9Sstevel@tonic-gate * 32 bit mode for the first link entry. 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate struct _link_ __first_link = /* first in linked list */ 117*7c478bd9Sstevel@tonic-gate { 118*7c478bd9Sstevel@tonic-gate #if !defined(_LP64) 119*7c478bd9Sstevel@tonic-gate NULL, 120*7c478bd9Sstevel@tonic-gate #else 121*7c478bd9Sstevel@tonic-gate &_iob[0], 122*7c478bd9Sstevel@tonic-gate #endif 123*7c478bd9Sstevel@tonic-gate _NFILE, 124*7c478bd9Sstevel@tonic-gate NULL 125*7c478bd9Sstevel@tonic-gate }; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* 128*7c478bd9Sstevel@tonic-gate * Information cached to speed up searches. We remember where we 129*7c478bd9Sstevel@tonic-gate * last found a free FILE* and we remember whether we saw any fcloses 130*7c478bd9Sstevel@tonic-gate * in between. We also count the number of chunks we allocated, see 131*7c478bd9Sstevel@tonic-gate * _findiop() for an explanation. 132*7c478bd9Sstevel@tonic-gate * These variables are all protected by _first_link_lock. 133*7c478bd9Sstevel@tonic-gate */ 134*7c478bd9Sstevel@tonic-gate static struct _link_ *lastlink = NULL; 135*7c478bd9Sstevel@tonic-gate static int fcloses; 136*7c478bd9Sstevel@tonic-gate static int nchunks; 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate static rwlock_t _first_link_lock = DEFAULTRWLOCK; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate static int _fflush_u_iops(void); 141*7c478bd9Sstevel@tonic-gate static FILE *getiop(FILE *, rmutex_t *, mbstate_t *); 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate #define GETIOP(fp, lk, mb) {FILE *ret; \ 144*7c478bd9Sstevel@tonic-gate if ((ret = getiop((fp), __threaded ? (lk) : NULL, (mb))) != NULL) { \ 145*7c478bd9Sstevel@tonic-gate if (__threaded) \ 146*7c478bd9Sstevel@tonic-gate (void) __rw_unlock(&_first_link_lock); \ 147*7c478bd9Sstevel@tonic-gate return (ret); \ 148*7c478bd9Sstevel@tonic-gate }; \ 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate /* 152*7c478bd9Sstevel@tonic-gate * All functions that understand the linked list of iob's follow. 153*7c478bd9Sstevel@tonic-gate */ 154*7c478bd9Sstevel@tonic-gate #pragma weak _cleanup = __cleanup 155*7c478bd9Sstevel@tonic-gate void 156*7c478bd9Sstevel@tonic-gate __cleanup(void) /* called at process end to flush ouput streams */ 157*7c478bd9Sstevel@tonic-gate { 158*7c478bd9Sstevel@tonic-gate (void) fflush(NULL); 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* 162*7c478bd9Sstevel@tonic-gate * For fork1-safety (see libc_prepare_atfork(), etc). 163*7c478bd9Sstevel@tonic-gate */ 164*7c478bd9Sstevel@tonic-gate void 165*7c478bd9Sstevel@tonic-gate stdio_locks() 166*7c478bd9Sstevel@tonic-gate { 167*7c478bd9Sstevel@tonic-gate (void) __rw_wrlock(&_first_link_lock); 168*7c478bd9Sstevel@tonic-gate /* 169*7c478bd9Sstevel@tonic-gate * XXX: We should acquire all of the iob locks here. 170*7c478bd9Sstevel@tonic-gate */ 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate void 174*7c478bd9Sstevel@tonic-gate stdio_unlocks() 175*7c478bd9Sstevel@tonic-gate { 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * XXX: We should release all of the iob locks here. 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate (void) __rw_unlock(&_first_link_lock); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate void 183*7c478bd9Sstevel@tonic-gate _flushlbf(void) /* fflush() all line-buffered streams */ 184*7c478bd9Sstevel@tonic-gate { 185*7c478bd9Sstevel@tonic-gate FPDECL(fp); 186*7c478bd9Sstevel@tonic-gate int i; 187*7c478bd9Sstevel@tonic-gate struct _link_ *lp; 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate if (__threaded) 190*7c478bd9Sstevel@tonic-gate (void) __rw_rdlock(&_first_link_lock); 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate lp = &__first_link; 193*7c478bd9Sstevel@tonic-gate do { 194*7c478bd9Sstevel@tonic-gate FIRSTFP(lp, fp); 195*7c478bd9Sstevel@tonic-gate for (i = lp->niob; --i >= 0; NEXTFP(fp)) { 196*7c478bd9Sstevel@tonic-gate if ((fp->_flag & (_IOLBF | _IOWRT)) == 197*7c478bd9Sstevel@tonic-gate (_IOLBF | _IOWRT)) 198*7c478bd9Sstevel@tonic-gate (void) _fflush_u(fp); 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate } while ((lp = lp->next) != NULL); 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate if (__threaded) 203*7c478bd9Sstevel@tonic-gate (void) __rw_unlock(&_first_link_lock); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate /* allocate an unused stream; NULL if cannot */ 207*7c478bd9Sstevel@tonic-gate FILE * 208*7c478bd9Sstevel@tonic-gate _findiop(void) 209*7c478bd9Sstevel@tonic-gate { 210*7c478bd9Sstevel@tonic-gate struct _link_ *lp, **prev; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate /* used so there only needs to be one malloc() */ 213*7c478bd9Sstevel@tonic-gate #ifdef _LP64 214*7c478bd9Sstevel@tonic-gate typedef struct { 215*7c478bd9Sstevel@tonic-gate struct _link_ hdr; 216*7c478bd9Sstevel@tonic-gate FILE iob[FILE_ARY_SZ]; 217*7c478bd9Sstevel@tonic-gate } Pkg; 218*7c478bd9Sstevel@tonic-gate #else 219*7c478bd9Sstevel@tonic-gate typedef union { 220*7c478bd9Sstevel@tonic-gate struct { /* Normal */ 221*7c478bd9Sstevel@tonic-gate struct _link_ hdr; 222*7c478bd9Sstevel@tonic-gate xFILE iob[FILE_ARY_SZ]; 223*7c478bd9Sstevel@tonic-gate } Pkgn; 224*7c478bd9Sstevel@tonic-gate struct { /* Reversed */ 225*7c478bd9Sstevel@tonic-gate xFILE iob[FILE_ARY_SZ]; 226*7c478bd9Sstevel@tonic-gate struct _link_ hdr; 227*7c478bd9Sstevel@tonic-gate } Pkgr; 228*7c478bd9Sstevel@tonic-gate } Pkg; 229*7c478bd9Sstevel@tonic-gate uintptr_t delta; 230*7c478bd9Sstevel@tonic-gate #endif 231*7c478bd9Sstevel@tonic-gate Pkg *pkgp; 232*7c478bd9Sstevel@tonic-gate struct _link_ *hdr; 233*7c478bd9Sstevel@tonic-gate FPDECL(fp); 234*7c478bd9Sstevel@tonic-gate int i; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate if (__threaded) 237*7c478bd9Sstevel@tonic-gate (void) __rw_wrlock(&_first_link_lock); 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate if (lastlink == NULL) { 240*7c478bd9Sstevel@tonic-gate rescan: 241*7c478bd9Sstevel@tonic-gate fcloses = 0; 242*7c478bd9Sstevel@tonic-gate lastlink = &__first_link; 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate lp = lastlink; 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate /* 248*7c478bd9Sstevel@tonic-gate * lock to make testing of fp->_flag == 0 and acquiring the fp atomic 249*7c478bd9Sstevel@tonic-gate * and for allocation of new links 250*7c478bd9Sstevel@tonic-gate * low contention expected on _findiop(), hence coarse locking. 251*7c478bd9Sstevel@tonic-gate * for finer granularity, use fp->_lock for allocating an iop 252*7c478bd9Sstevel@tonic-gate * and make the testing of lp->next and allocation of new link atomic 253*7c478bd9Sstevel@tonic-gate * using lp->_lock 254*7c478bd9Sstevel@tonic-gate */ 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate do { 257*7c478bd9Sstevel@tonic-gate prev = &lp->next; 258*7c478bd9Sstevel@tonic-gate FIRSTFP(lp, fp); 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate for (i = lp->niob; --i >= 0; NEXTFP(fp)) { 261*7c478bd9Sstevel@tonic-gate #ifdef _LP64 262*7c478bd9Sstevel@tonic-gate GETIOP(fp, &fp->_lock, &fp->_state); 263*7c478bd9Sstevel@tonic-gate #else 264*7c478bd9Sstevel@tonic-gate GETIOP(fp, 265*7c478bd9Sstevel@tonic-gate xfp ? &xfp->xlock : &_xftab[IOPIND(fp)]._lock, 266*7c478bd9Sstevel@tonic-gate xfp ? &xfp->xstate : &_xftab[IOPIND(fp)]._state); 267*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate } while ((lastlink = lp = lp->next) != NULL); 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * If there was a sufficient number of fcloses since we last started 273*7c478bd9Sstevel@tonic-gate * at __first_link, we rescan all fp's again. We do not rescan for 274*7c478bd9Sstevel@tonic-gate * all fcloses; that would simplify the algorithm but would make 275*7c478bd9Sstevel@tonic-gate * search times near O(n) again. 276*7c478bd9Sstevel@tonic-gate * Worst case behaviour would still be pretty bad (open a full set, 277*7c478bd9Sstevel@tonic-gate * then continously opening and closing one FILE * gets you a full 278*7c478bd9Sstevel@tonic-gate * scan each time). That's why we over allocate 1 FILE for each 279*7c478bd9Sstevel@tonic-gate * 32 chunks. More over allocation is better; this is a nice 280*7c478bd9Sstevel@tonic-gate * empirical value which doesn't cost a lot of memory, doesn't 281*7c478bd9Sstevel@tonic-gate * overallocate until we reach 256 FILE *s and keeps the performance 282*7c478bd9Sstevel@tonic-gate * pretty close to the optimum. 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate if (fcloses > nchunks/32) 285*7c478bd9Sstevel@tonic-gate goto rescan; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* 288*7c478bd9Sstevel@tonic-gate * Need to allocate another and put it in the linked list. 289*7c478bd9Sstevel@tonic-gate */ 290*7c478bd9Sstevel@tonic-gate if ((pkgp = malloc(sizeof (Pkg))) == NULL) { 291*7c478bd9Sstevel@tonic-gate if (__threaded) 292*7c478bd9Sstevel@tonic-gate (void) __rw_unlock(&_first_link_lock); 293*7c478bd9Sstevel@tonic-gate return (NULL); 294*7c478bd9Sstevel@tonic-gate } 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate (void) memset(pkgp, 0, sizeof (Pkg)); 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate #ifdef _LP64 299*7c478bd9Sstevel@tonic-gate hdr = &pkgp->hdr; 300*7c478bd9Sstevel@tonic-gate hdr->iobp = &pkgp->iob[0]; 301*7c478bd9Sstevel@tonic-gate #else 302*7c478bd9Sstevel@tonic-gate /* 303*7c478bd9Sstevel@tonic-gate * The problem with referencing a word after a FILE* is the possibility 304*7c478bd9Sstevel@tonic-gate * of a SIGSEGV if a non-stdio issue FILE structure ends on a page 305*7c478bd9Sstevel@tonic-gate * boundary. We run this check so we never need to run an expensive 306*7c478bd9Sstevel@tonic-gate * check like mincore() in order to know whether it is 307*7c478bd9Sstevel@tonic-gate * safe to dereference ((xFILE*)fp)->xmagic. 308*7c478bd9Sstevel@tonic-gate * We allocate the block with two alternative layouts; if one 309*7c478bd9Sstevel@tonic-gate * layout is not properly aligned for our purposes, the other layout 310*7c478bd9Sstevel@tonic-gate * will be because the size of _link_ is small compared to 311*7c478bd9Sstevel@tonic-gate * sizeof (xFILE). 312*7c478bd9Sstevel@tonic-gate * The check performed is this: 313*7c478bd9Sstevel@tonic-gate * If the distance from pkgp to the end of the page is 314*7c478bd9Sstevel@tonic-gate * less than the the offset of the last xmagic field in the 315*7c478bd9Sstevel@tonic-gate * xFILE structure, (the 0x1000 boundary is inside our just 316*7c478bd9Sstevel@tonic-gate * allocated structure) and the distance modulo the size of xFILE 317*7c478bd9Sstevel@tonic-gate * is identical to the offset of the first xmagic in the 318*7c478bd9Sstevel@tonic-gate * structure (i.e., XXXXXX000 points to an xmagic field), 319*7c478bd9Sstevel@tonic-gate * we need to use the reverse structure. 320*7c478bd9Sstevel@tonic-gate */ 321*7c478bd9Sstevel@tonic-gate if ((delta = 0x1000 - ((uintptr_t)pkgp & 0xfff)) <= 322*7c478bd9Sstevel@tonic-gate offsetof(Pkg, Pkgn.iob[FILE_ARY_SZ-1].xmagic) && 323*7c478bd9Sstevel@tonic-gate delta % sizeof (struct xFILE) == 324*7c478bd9Sstevel@tonic-gate offsetof(Pkg, Pkgn.iob[0].xmagic)) { 325*7c478bd9Sstevel@tonic-gate /* Use reversed structure */ 326*7c478bd9Sstevel@tonic-gate hdr = &pkgp->Pkgr.hdr; 327*7c478bd9Sstevel@tonic-gate hdr->iobp = &pkgp->Pkgr.iob[0]; 328*7c478bd9Sstevel@tonic-gate } else { 329*7c478bd9Sstevel@tonic-gate /* Use normal structure */ 330*7c478bd9Sstevel@tonic-gate hdr = &pkgp->Pkgn.hdr; 331*7c478bd9Sstevel@tonic-gate hdr->iobp = &pkgp->Pkgn.iob[0]; 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate hdr->niob = FILE_ARY_SZ; 336*7c478bd9Sstevel@tonic-gate nchunks++; 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate #ifdef _LP64 339*7c478bd9Sstevel@tonic-gate fp = hdr->iobp; 340*7c478bd9Sstevel@tonic-gate for (i = 0; i < FILE_ARY_SZ; i++) 341*7c478bd9Sstevel@tonic-gate _private_mutex_init(&fp[i]._lock, 342*7c478bd9Sstevel@tonic-gate USYNC_THREAD|LOCK_RECURSIVE, NULL); 343*7c478bd9Sstevel@tonic-gate #else 344*7c478bd9Sstevel@tonic-gate xfp = hdr->iobp; 345*7c478bd9Sstevel@tonic-gate fp = &xfp->_iob; 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate for (i = 0; i < FILE_ARY_SZ; i++) { 348*7c478bd9Sstevel@tonic-gate xfp[i].xmagic = XMAGIC(&xfp[i]); 349*7c478bd9Sstevel@tonic-gate _private_mutex_init(&xfp[i].xlock, 350*7c478bd9Sstevel@tonic-gate USYNC_THREAD|LOCK_RECURSIVE, NULL); 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate lastlink = *prev = hdr; 355*7c478bd9Sstevel@tonic-gate fp->_ptr = 0; 356*7c478bd9Sstevel@tonic-gate fp->_base = 0; 357*7c478bd9Sstevel@tonic-gate fp->_flag = 0377; /* claim the fp by setting low 8 bits */ 358*7c478bd9Sstevel@tonic-gate if (__threaded) 359*7c478bd9Sstevel@tonic-gate (void) __rw_unlock(&_first_link_lock); 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate return (fp); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate static void 365*7c478bd9Sstevel@tonic-gate isseekable(FILE *iop) 366*7c478bd9Sstevel@tonic-gate { 367*7c478bd9Sstevel@tonic-gate struct stat64 fstatbuf; 368*7c478bd9Sstevel@tonic-gate int save_errno; 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate save_errno = errno; 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate if (fstat64(iop->_file, &fstatbuf) != 0) { 373*7c478bd9Sstevel@tonic-gate /* 374*7c478bd9Sstevel@tonic-gate * when we don't know what it is we'll 375*7c478bd9Sstevel@tonic-gate * do the old behaviour and flush 376*7c478bd9Sstevel@tonic-gate * the stream 377*7c478bd9Sstevel@tonic-gate */ 378*7c478bd9Sstevel@tonic-gate SET_SEEKABLE(iop); 379*7c478bd9Sstevel@tonic-gate errno = save_errno; 380*7c478bd9Sstevel@tonic-gate return; 381*7c478bd9Sstevel@tonic-gate } 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate /* 384*7c478bd9Sstevel@tonic-gate * check for what is non-SEEKABLE 385*7c478bd9Sstevel@tonic-gate * otherwise assume it's SEEKABLE so we get the old 386*7c478bd9Sstevel@tonic-gate * behaviour and flush the stream 387*7c478bd9Sstevel@tonic-gate */ 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate if (S_ISFIFO(fstatbuf.st_mode) || S_ISCHR(fstatbuf.st_mode) || 390*7c478bd9Sstevel@tonic-gate S_ISSOCK(fstatbuf.st_mode) || S_ISDOOR(fstatbuf.st_mode)) { 391*7c478bd9Sstevel@tonic-gate CLEAR_SEEKABLE(iop); 392*7c478bd9Sstevel@tonic-gate } else { 393*7c478bd9Sstevel@tonic-gate SET_SEEKABLE(iop); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate errno = save_errno; 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate #ifdef _LP64 400*7c478bd9Sstevel@tonic-gate void 401*7c478bd9Sstevel@tonic-gate _setbufend(FILE *iop, Uchar *end) /* set the end pointer for this iop */ 402*7c478bd9Sstevel@tonic-gate { 403*7c478bd9Sstevel@tonic-gate iop->_end = end; 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate isseekable(iop); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate #undef _realbufend 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate Uchar * 411*7c478bd9Sstevel@tonic-gate _realbufend(FILE *iop) /* get the end pointer for this iop */ 412*7c478bd9Sstevel@tonic-gate { 413*7c478bd9Sstevel@tonic-gate return (iop->_end); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate #else /* _LP64 */ 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate /* 419*7c478bd9Sstevel@tonic-gate * Awkward functions not needed for the sane 64 bit environment. 420*7c478bd9Sstevel@tonic-gate */ 421*7c478bd9Sstevel@tonic-gate /* 422*7c478bd9Sstevel@tonic-gate * xmagic must not be aligned on a 4K boundary. We guarantee this in 423*7c478bd9Sstevel@tonic-gate * _findiop(). 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate #define VALIDXFILE(xfp) \ 426*7c478bd9Sstevel@tonic-gate (((uintptr_t)&(xfp)->xmagic & 0xfff) && \ 427*7c478bd9Sstevel@tonic-gate (xfp)->xmagic == XMAGIC(FILEx(xfp))) 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate static struct xFILEdata * 430*7c478bd9Sstevel@tonic-gate getxfdat(FILE *iop) 431*7c478bd9Sstevel@tonic-gate { 432*7c478bd9Sstevel@tonic-gate if (STDIOP(iop)) 433*7c478bd9Sstevel@tonic-gate return (&_xftab[IOPIND(iop)]); 434*7c478bd9Sstevel@tonic-gate else if (VALIDXFILE(FILEx(iop))) 435*7c478bd9Sstevel@tonic-gate return (&FILEx(iop)->_xdat); 436*7c478bd9Sstevel@tonic-gate else 437*7c478bd9Sstevel@tonic-gate return (NULL); 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate void 441*7c478bd9Sstevel@tonic-gate _setbufend(FILE *iop, Uchar *end) /* set the end pointer for this iop */ 442*7c478bd9Sstevel@tonic-gate { 443*7c478bd9Sstevel@tonic-gate struct xFILEdata *dat = getxfdat(iop); 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate if (dat != NULL) 446*7c478bd9Sstevel@tonic-gate dat->_end = end; 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate isseekable(iop); 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate /* 451*7c478bd9Sstevel@tonic-gate * For binary compatibility with user programs using the 452*7c478bd9Sstevel@tonic-gate * old _bufend macro. This is *so* broken, fileno() 453*7c478bd9Sstevel@tonic-gate * is not the proper index. 454*7c478bd9Sstevel@tonic-gate */ 455*7c478bd9Sstevel@tonic-gate if (iop->_file < _NFILE) 456*7c478bd9Sstevel@tonic-gate _bufendtab[iop->_file] = end; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate Uchar * 461*7c478bd9Sstevel@tonic-gate _realbufend(FILE *iop) /* get the end pointer for this iop */ 462*7c478bd9Sstevel@tonic-gate { 463*7c478bd9Sstevel@tonic-gate struct xFILEdata *dat = getxfdat(iop); 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate if (dat != NULL) 466*7c478bd9Sstevel@tonic-gate return (dat->_end); 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate return (NULL); 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate /* 472*7c478bd9Sstevel@tonic-gate * _reallock() is invoked in each stdio call through the IOB_LCK() macro, 473*7c478bd9Sstevel@tonic-gate * it is therefor extremely performance sensitive. We get better performance 474*7c478bd9Sstevel@tonic-gate * by inlining the STDIOP check in IOB_LCK and inlining a custom version 475*7c478bd9Sstevel@tonic-gate * of getfxdat() here. 476*7c478bd9Sstevel@tonic-gate */ 477*7c478bd9Sstevel@tonic-gate rmutex_t * 478*7c478bd9Sstevel@tonic-gate _reallock(FILE *iop) 479*7c478bd9Sstevel@tonic-gate { 480*7c478bd9Sstevel@tonic-gate if (VALIDXFILE(FILEx(iop))) 481*7c478bd9Sstevel@tonic-gate return (&FILEx(iop)->xlock); 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate return (NULL); 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate /* make sure _cnt, _ptr are correct */ 489*7c478bd9Sstevel@tonic-gate void 490*7c478bd9Sstevel@tonic-gate _bufsync(FILE *iop, Uchar *bufend) 491*7c478bd9Sstevel@tonic-gate { 492*7c478bd9Sstevel@tonic-gate ssize_t spaceleft; 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate spaceleft = bufend - iop->_ptr; 495*7c478bd9Sstevel@tonic-gate if (bufend < iop->_ptr) { 496*7c478bd9Sstevel@tonic-gate iop->_ptr = bufend; 497*7c478bd9Sstevel@tonic-gate iop->_cnt = 0; 498*7c478bd9Sstevel@tonic-gate } else if (spaceleft < iop->_cnt) 499*7c478bd9Sstevel@tonic-gate iop->_cnt = spaceleft; 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate /* really write out current buffer contents */ 503*7c478bd9Sstevel@tonic-gate int 504*7c478bd9Sstevel@tonic-gate _xflsbuf(FILE *iop) 505*7c478bd9Sstevel@tonic-gate { 506*7c478bd9Sstevel@tonic-gate ssize_t n; 507*7c478bd9Sstevel@tonic-gate Uchar *base = iop->_base; 508*7c478bd9Sstevel@tonic-gate Uchar *bufend; 509*7c478bd9Sstevel@tonic-gate ssize_t num_wrote; 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate /* 512*7c478bd9Sstevel@tonic-gate * Hopefully, be stable with respect to interrupts... 513*7c478bd9Sstevel@tonic-gate */ 514*7c478bd9Sstevel@tonic-gate n = iop->_ptr - base; 515*7c478bd9Sstevel@tonic-gate iop->_ptr = base; 516*7c478bd9Sstevel@tonic-gate bufend = _bufend(iop); 517*7c478bd9Sstevel@tonic-gate if (iop->_flag & (_IOLBF | _IONBF)) 518*7c478bd9Sstevel@tonic-gate iop->_cnt = 0; /* always go to a flush */ 519*7c478bd9Sstevel@tonic-gate else 520*7c478bd9Sstevel@tonic-gate iop->_cnt = bufend - base; 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate if (_needsync(iop, bufend)) /* recover from interrupts */ 523*7c478bd9Sstevel@tonic-gate _bufsync(iop, bufend); 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate if (n > 0) { 526*7c478bd9Sstevel@tonic-gate while ((num_wrote = 527*7c478bd9Sstevel@tonic-gate write(iop->_file, base, (size_t)n)) != n) { 528*7c478bd9Sstevel@tonic-gate if (num_wrote <= 0) { 529*7c478bd9Sstevel@tonic-gate iop->_flag |= _IOERR; 530*7c478bd9Sstevel@tonic-gate return (EOF); 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate n -= num_wrote; 533*7c478bd9Sstevel@tonic-gate base += num_wrote; 534*7c478bd9Sstevel@tonic-gate } 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate return (0); 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate /* flush (write) buffer */ 540*7c478bd9Sstevel@tonic-gate int 541*7c478bd9Sstevel@tonic-gate fflush(FILE *iop) 542*7c478bd9Sstevel@tonic-gate { 543*7c478bd9Sstevel@tonic-gate int res; 544*7c478bd9Sstevel@tonic-gate rmutex_t *lk; 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate if (iop) { 547*7c478bd9Sstevel@tonic-gate FLOCKFILE(lk, iop); 548*7c478bd9Sstevel@tonic-gate res = _fflush_u(iop); 549*7c478bd9Sstevel@tonic-gate FUNLOCKFILE(lk); 550*7c478bd9Sstevel@tonic-gate } else { 551*7c478bd9Sstevel@tonic-gate res = _fflush_u_iops(); /* flush all iops */ 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate return (res); 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate static int 557*7c478bd9Sstevel@tonic-gate _fflush_u_iops(void) /* flush all buffers */ 558*7c478bd9Sstevel@tonic-gate { 559*7c478bd9Sstevel@tonic-gate FPDECL(iop); 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate int i; 562*7c478bd9Sstevel@tonic-gate struct _link_ *lp; 563*7c478bd9Sstevel@tonic-gate int res = 0; 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate if (__threaded) 566*7c478bd9Sstevel@tonic-gate (void) __rw_rdlock(&_first_link_lock); 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate lp = &__first_link; 569*7c478bd9Sstevel@tonic-gate 570*7c478bd9Sstevel@tonic-gate do { 571*7c478bd9Sstevel@tonic-gate /* 572*7c478bd9Sstevel@tonic-gate * Don't grab the locks for these file pointers 573*7c478bd9Sstevel@tonic-gate * since they are supposed to be flushed anyway 574*7c478bd9Sstevel@tonic-gate * It could also be the case in which the 2nd 575*7c478bd9Sstevel@tonic-gate * portion (base and lock) are not initialized 576*7c478bd9Sstevel@tonic-gate */ 577*7c478bd9Sstevel@tonic-gate FIRSTFP(lp, iop); 578*7c478bd9Sstevel@tonic-gate for (i = lp->niob; --i >= 0; NEXTFP(iop)) { 579*7c478bd9Sstevel@tonic-gate if (!(iop->_flag & _IONBF)) { 580*7c478bd9Sstevel@tonic-gate /* 581*7c478bd9Sstevel@tonic-gate * don't need to worry about the _IORW case 582*7c478bd9Sstevel@tonic-gate * since the iop will also marked with _IOREAD 583*7c478bd9Sstevel@tonic-gate * or _IOWRT whichever we are really doing 584*7c478bd9Sstevel@tonic-gate */ 585*7c478bd9Sstevel@tonic-gate if (iop->_flag & _IOWRT) { /* flush write buffers */ 586*7c478bd9Sstevel@tonic-gate res |= _fflush_u(iop); 587*7c478bd9Sstevel@tonic-gate } else if (iop->_flag & _IOREAD) { 588*7c478bd9Sstevel@tonic-gate /* 589*7c478bd9Sstevel@tonic-gate * flush seekable read buffers 590*7c478bd9Sstevel@tonic-gate * don't flush non-seekable read buffers 591*7c478bd9Sstevel@tonic-gate */ 592*7c478bd9Sstevel@tonic-gate if (GET_SEEKABLE(iop)) { 593*7c478bd9Sstevel@tonic-gate res |= _fflush_u(iop); 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate } while ((lp = lp->next) != NULL); 599*7c478bd9Sstevel@tonic-gate if (__threaded) 600*7c478bd9Sstevel@tonic-gate (void) __rw_unlock(&_first_link_lock); 601*7c478bd9Sstevel@tonic-gate return (res); 602*7c478bd9Sstevel@tonic-gate } 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate /* flush buffer */ 605*7c478bd9Sstevel@tonic-gate int 606*7c478bd9Sstevel@tonic-gate _fflush_u(FILE *iop) 607*7c478bd9Sstevel@tonic-gate { 608*7c478bd9Sstevel@tonic-gate int res = 0; 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate /* this portion is always assumed locked */ 611*7c478bd9Sstevel@tonic-gate if (!(iop->_flag & _IOWRT)) { 612*7c478bd9Sstevel@tonic-gate (void) lseek64(iop->_file, -iop->_cnt, SEEK_CUR); 613*7c478bd9Sstevel@tonic-gate iop->_cnt = 0; 614*7c478bd9Sstevel@tonic-gate /* needed for ungetc & multibyte pushbacks */ 615*7c478bd9Sstevel@tonic-gate iop->_ptr = iop->_base; 616*7c478bd9Sstevel@tonic-gate if (iop->_flag & _IORW) { 617*7c478bd9Sstevel@tonic-gate iop->_flag &= ~_IOREAD; 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate return (0); 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate if (iop->_base != NULL && iop->_ptr > iop->_base) { 622*7c478bd9Sstevel@tonic-gate res = _xflsbuf(iop); 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate if (iop->_flag & _IORW) { 625*7c478bd9Sstevel@tonic-gate iop->_flag &= ~_IOWRT; 626*7c478bd9Sstevel@tonic-gate iop->_cnt = 0; 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate return (res); 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate /* flush buffer and close stream */ 632*7c478bd9Sstevel@tonic-gate int 633*7c478bd9Sstevel@tonic-gate fclose(FILE *iop) 634*7c478bd9Sstevel@tonic-gate { 635*7c478bd9Sstevel@tonic-gate int res = 0; 636*7c478bd9Sstevel@tonic-gate rmutex_t *lk; 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate if (iop == NULL) { 639*7c478bd9Sstevel@tonic-gate return (EOF); /* avoid passing zero to FLOCKFILE */ 640*7c478bd9Sstevel@tonic-gate } 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate FLOCKFILE(lk, iop); 643*7c478bd9Sstevel@tonic-gate if (iop->_flag == 0) { 644*7c478bd9Sstevel@tonic-gate FUNLOCKFILE(lk); 645*7c478bd9Sstevel@tonic-gate return (EOF); 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate /* Is not unbuffered and opened for read and/or write ? */ 648*7c478bd9Sstevel@tonic-gate if (!(iop->_flag & _IONBF) && (iop->_flag & (_IOWRT | _IOREAD | _IORW))) 649*7c478bd9Sstevel@tonic-gate res = _fflush_u(iop); 650*7c478bd9Sstevel@tonic-gate if (close(iop->_file) < 0) 651*7c478bd9Sstevel@tonic-gate res = EOF; 652*7c478bd9Sstevel@tonic-gate if (iop->_flag & _IOMYBUF) { 653*7c478bd9Sstevel@tonic-gate (void) free((char *)iop->_base - PUSHBACK); 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate iop->_base = NULL; 656*7c478bd9Sstevel@tonic-gate iop->_ptr = NULL; 657*7c478bd9Sstevel@tonic-gate iop->_cnt = 0; 658*7c478bd9Sstevel@tonic-gate iop->_flag = 0; /* marks it as available */ 659*7c478bd9Sstevel@tonic-gate FUNLOCKFILE(lk); 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate if (__threaded) 662*7c478bd9Sstevel@tonic-gate (void) __rw_wrlock(&_first_link_lock); 663*7c478bd9Sstevel@tonic-gate fcloses++; 664*7c478bd9Sstevel@tonic-gate if (__threaded) 665*7c478bd9Sstevel@tonic-gate (void) __rw_unlock(&_first_link_lock); 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate return (res); 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate /* flush buffer, close fd but keep the stream used by freopen() */ 671*7c478bd9Sstevel@tonic-gate int 672*7c478bd9Sstevel@tonic-gate close_fd(FILE *iop) 673*7c478bd9Sstevel@tonic-gate { 674*7c478bd9Sstevel@tonic-gate int res = 0; 675*7c478bd9Sstevel@tonic-gate mbstate_t *mb; 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate if (iop == NULL || iop->_flag == 0) 678*7c478bd9Sstevel@tonic-gate return (EOF); 679*7c478bd9Sstevel@tonic-gate /* Is not unbuffered and opened for read and/or write ? */ 680*7c478bd9Sstevel@tonic-gate if (!(iop->_flag & _IONBF) && (iop->_flag & (_IOWRT | _IOREAD | _IORW))) 681*7c478bd9Sstevel@tonic-gate res = _fflush_u(iop); 682*7c478bd9Sstevel@tonic-gate if (close(iop->_file) < 0) 683*7c478bd9Sstevel@tonic-gate res = EOF; 684*7c478bd9Sstevel@tonic-gate if (iop->_flag & _IOMYBUF) { 685*7c478bd9Sstevel@tonic-gate (void) free((char *)iop->_base - PUSHBACK); 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate iop->_base = NULL; 688*7c478bd9Sstevel@tonic-gate iop->_ptr = NULL; 689*7c478bd9Sstevel@tonic-gate mb = _getmbstate(iop); 690*7c478bd9Sstevel@tonic-gate if (mb != NULL) 691*7c478bd9Sstevel@tonic-gate (void) memset(mb, 0, sizeof (mbstate_t)); 692*7c478bd9Sstevel@tonic-gate iop->_cnt = 0; 693*7c478bd9Sstevel@tonic-gate _setorientation(iop, _NO_MODE); 694*7c478bd9Sstevel@tonic-gate return (res); 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate static FILE * 698*7c478bd9Sstevel@tonic-gate getiop(FILE *fp, rmutex_t *lk, mbstate_t *mb) 699*7c478bd9Sstevel@tonic-gate { 700*7c478bd9Sstevel@tonic-gate if (lk != NULL && rmutex_trylock(lk)) 701*7c478bd9Sstevel@tonic-gate return (NULL); /* locked: fp in use */ 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate if (fp->_flag == 0) { /* unused */ 704*7c478bd9Sstevel@tonic-gate #ifndef _LP64 705*7c478bd9Sstevel@tonic-gate fp->__orientation = 0; 706*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 707*7c478bd9Sstevel@tonic-gate fp->_cnt = 0; 708*7c478bd9Sstevel@tonic-gate fp->_ptr = NULL; 709*7c478bd9Sstevel@tonic-gate fp->_base = NULL; 710*7c478bd9Sstevel@tonic-gate fp->_flag = 0377; /* claim the fp by setting low 8 bits */ 711*7c478bd9Sstevel@tonic-gate (void) memset(mb, 0, sizeof (mbstate_t)); 712*7c478bd9Sstevel@tonic-gate FUNLOCKFILE(lk); 713*7c478bd9Sstevel@tonic-gate return (fp); 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate FUNLOCKFILE(lk); 716*7c478bd9Sstevel@tonic-gate return (NULL); 717*7c478bd9Sstevel@tonic-gate } 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate #ifndef _LP64 720*7c478bd9Sstevel@tonic-gate /* 721*7c478bd9Sstevel@tonic-gate * DESCRIPTION: 722*7c478bd9Sstevel@tonic-gate * This function gets the pointer to the mbstate_t structure associated 723*7c478bd9Sstevel@tonic-gate * with the specified iop. 724*7c478bd9Sstevel@tonic-gate * 725*7c478bd9Sstevel@tonic-gate * RETURNS: 726*7c478bd9Sstevel@tonic-gate * If the associated mbstate_t found, the pointer to the mbstate_t is 727*7c478bd9Sstevel@tonic-gate * returned. Otherwise, NULL is returned. 728*7c478bd9Sstevel@tonic-gate */ 729*7c478bd9Sstevel@tonic-gate mbstate_t * 730*7c478bd9Sstevel@tonic-gate _getmbstate(FILE *iop) 731*7c478bd9Sstevel@tonic-gate { 732*7c478bd9Sstevel@tonic-gate struct xFILEdata *dat = getxfdat(iop); 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate if (dat != NULL) 735*7c478bd9Sstevel@tonic-gate return (&dat->_state); 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate return (NULL); 738*7c478bd9Sstevel@tonic-gate } 739*7c478bd9Sstevel@tonic-gate #endif 740