|
|
1.1 ! root 1: /*ident "@(#)ctrans:lib/stream/filebuf.c 1.1.2.2" */ ! 2: /************************************************************************** ! 3: Copyright (c) 1984 AT&T ! 4: All Rights Reserved ! 5: ! 6: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T ! 7: ! 8: The copyright notice above does not evidence any ! 9: actual or intended publication of such source code. ! 10: ! 11: filebuf.c: ! 12: ! 13: *****************************************************************************/ ! 14: ! 15: #include <iostream.h> ! 16: #include <fstream.h> ! 17: #include <osfcn.h> ! 18: #include "streamdefs.h" ! 19: ! 20: #ifndef O_RDONLY ! 21: # include <fcntl.h> ! 22: #endif ! 23: ! 24: #ifndef O_CREAT ! 25: # define O_CREAT 00400 ! 26: #endif ! 27: ! 28: #ifndef O_TRUNC ! 29: # define O_TRUNC 01000 ! 30: #endif ! 31: ! 32: #ifndef O_EXCL ! 33: # define O_EXCL 02000 ! 34: #endif ! 35: ! 36: ! 37: #ifndef O_APPEND ! 38: # define O_APPEND 0 ! 39: #endif ! 40: ! 41: #include <errno.h> ! 42: extern int errno ; ! 43: ! 44: const int filebuf::openprot = 0644 ; ! 45: ! 46: static const int input=ios::in ; ! 47: static const int output=ios::out ; ! 48: static const int append=ios::app ; ! 49: static const int atend=ios::ate ; ! 50: static const int tcate=ios::trunc ; ! 51: static const int nocr=ios::nocreate ; ! 52: static const int norep=ios::noreplace ; ! 53: ! 54: static const int seek_beg=ios::beg ; ! 55: static const int seek_end=ios::end ; ! 56: static const int seek_cur=ios::cur ; ! 57: ! 58: int filebuf::last_op() ! 59: { ! 60: return (pptr()?output:(gptr()?input:0)) ; ! 61: } ! 62: ! 63: inline void save_errno(int& orig) ! 64: { ! 65: orig = ::errno ; ! 66: ::errno = 0 ; ! 67: } ! 68: ! 69: inline int restore_errno(int& orig) ! 70: { ! 71: if ( ::errno == 0 ) ::errno = orig ; ! 72: return EOF ; ! 73: } ! 74: ! 75: /* ! 76: * Open a file with the given mode. ! 77: * Return: NULL if failure ! 78: * this if success ! 79: */ ! 80: filebuf* filebuf::open (const char *name, int om, int prot) ! 81: { ! 82: int errno_orig ; ! 83: save_errno(errno_orig) ; ! 84: if ( om&append ) om |= output ; ! 85: ! 86: if ( opened ) { ! 87: restore_errno(errno_orig) ; ! 88: return 0 ; ! 89: } ! 90: ! 91: int flags = 0 ; ! 92: if ( om&append ) flags |= O_APPEND ; ! 93: ! 94: switch (om&(input|output)) { ! 95: case input : ! 96: flags |= O_RDONLY ; ! 97: xfd = ::open(name,flags) ; ! 98: break ; ! 99: ! 100: case output : ! 101: flags |= O_WRONLY|O_CREAT|O_TRUNC ; ! 102: if ( om&nocr ) flags &= ~O_CREAT ; ! 103: if ( om&norep ) flags |= O_CREAT|O_EXCL ; ! 104: if ( om&append ) flags |= O_APPEND ; ! 105: if ( flags == (O_WRONLY|O_CREAT|O_TRUNC) ) { ! 106: xfd = ::creat(name,prot) ; ! 107: } ! 108: else { ! 109: xfd = ::open(name,flags,prot) ; ! 110: } ! 111: ! 112: if ( xfd >= 0 && (om&(atend|append))) lseek(xfd,0,2) ; ! 113: break ; ! 114: ! 115: case input|output: ! 116: flags |= O_RDWR|O_CREAT ; ! 117: if ( om&tcate ) flags |= O_TRUNC ; ! 118: if ( om&append ) flags |= O_APPEND ; ! 119: if ( om&nocr ) flags &= ~O_CREAT ; ! 120: xfd = ::open(name,flags,prot) ; ! 121: if ( xfd >= 0 && (om&(atend|append))) lseek(xfd,0,2) ; ! 122: break; ! 123: } ! 124: ! 125: if (xfd < 0) return 0; ! 126: ! 127: opened = 1; ! 128: setp(0,0) ; ! 129: setg(0,0,0) ; ! 130: mode = om ; ! 131: last_seek = EOF ; ! 132: restore_errno(errno_orig) ; ! 133: return this; ! 134: } ! 135: ! 136: filebuf* filebuf::attach (int f) ! 137: { ! 138: if ( opened ) return 0 ; ! 139: xfd = f; ! 140: opened = 1; ! 141: setp(0,0) ; ! 142: setg(0,0,0) ; ! 143: mode=0 ; ! 144: last_seek= EOF; ! 145: return this; ! 146: } ! 147: ! 148: /* ! 149: * Empty an output buffer. ! 150: * Returns: EOF on error ! 151: * 0 on success ! 152: */ ! 153: int filebuf::overflow(int c) ! 154: { ! 155: int errno_orig ; ! 156: save_errno(errno_orig) ; ! 157: if ( !opened ) return restore_errno(errno_orig) ; ! 158: if ( allocate() == EOF ) return restore_errno(errno_orig) ; ! 159: if ( last_op() == input ) { ! 160: if ( sync()==EOF ) return restore_errno(errno_orig) ; ! 161: } ! 162: ! 163: register char* p = base() ; ! 164: // pptr()==NULL does not imply p < pptr(), so we need separate ! 165: // test. ! 166: while ( pptr() && p < pptr() ) { ! 167: if ( O_APPEND==0 && (mode&append) ) { ! 168: // System doesn't have an append mode, so approximate ! 169: // as best we can. ! 170: lseek(xfd,0,2) ; ! 171: } ! 172: /* Partial writes are sometimes possible in peculiar ! 173: * circumstances */ ! 174: register int count = write(xfd,p,pptr()-p) ; ! 175: if ( count < 0 ) { ! 176: last_seek = EOF ; ! 177: return restore_errno(errno_orig) ; ! 178: } ! 179: p += count ; ! 180: ! 181: if ( SEEK_ARITH_OK ! 182: && last_seek != EOF ! 183: && mode && !(mode&append) ! 184: && count >= 0 ) { ! 185: last_seek += count ; ! 186: } else { ! 187: last_seek = EOF ; ! 188: } ! 189: ! 190: if ( count < 0 ) return restore_errno(errno_orig) ; ! 191: } ! 192: ! 193: setp(base(),ebuf()) ; ! 194: setg(0,0,0); ! 195: ! 196: if ( c == EOF ) /* don't do anything */ ; ! 197: else if ( unbuffered() ) { ! 198: char ch = c; ! 199: last_seek = EOF ; ! 200: while ( write(xfd,&ch,1)!=1 && ::errno==0 ) ; ! 201: if ( ::errno != 0 ) return restore_errno(errno_orig) ; ! 202: } ! 203: else { ! 204: sputc(c) ; ! 205: } ! 206: ! 207: restore_errno(errno_orig) ; ! 208: return zapeof(c) ; ! 209: } ! 210: ! 211: ! 212: /* ! 213: * Fill an input buffer. ! 214: * Returns: EOF on error or end of input ! 215: * next character on success ! 216: */ ! 217: int filebuf::underflow() ! 218: { ! 219: int count; ! 220: ! 221: if ( !opened ) return EOF ; ! 222: if ( allocate() == EOF ) return EOF ; ! 223: if ( last_op() == output ) { ! 224: if ( sync()==EOF ) return EOF ; ! 225: } ! 226: int orig_errno ; ! 227: save_errno(orig_errno) ; ! 228: setp(0,0) ; ! 229: if ( unbuffered() ) { ! 230: last_seek=EOF ; ! 231: count = read(xfd,&lahead[0],1) ; ! 232: setg(&lahead[0],&lahead[0],&lahead[count]) ; ! 233: if ( count <= 0 ) return EOF ; ! 234: } ! 235: else { ! 236: register int rdsize ; ! 237: if ( blen() > 2*sizeof(long) ) { ! 238: /* gptr must be set greater than base to ! 239: * guarantee at least 1 char of pushback. ! 240: * putting it farther will tend in many common ! 241: * cases to keep things aligned. ! 242: */ ! 243: in_start = base()+sizeof(long) ; ! 244: rdsize = blen()-sizeof(long) ; ! 245: } else { ! 246: in_start = base()+1 ; ! 247: rdsize = blen()-1 ; ! 248: } ! 249: count = read(xfd,in_start,rdsize) ; ! 250: while ( count<=0 && ::errno==EINTR ) { ! 251: /* ! 252: * Signal caught and returned before any data ! 253: * transfered. ! 254: */ ! 255: ::errno = 0 ; ! 256: count = read(xfd,in_start,rdsize) ; ! 257: } ! 258: ! 259: if ( SEEK_ARITH_OK ! 260: && last_seek != EOF ! 261: && mode && !(mode&append) ! 262: && count >= 0 ) { ! 263: last_seek += count ; ! 264: } else { ! 265: last_seek = EOF ; ! 266: } ! 267: ! 268: if ( count <= 0 ) { ! 269: setg(0,0,0) ; ! 270: return restore_errno(orig_errno) ; ! 271: } ! 272: setg(base(),in_start,in_start+count) ; ! 273: } ! 274: ! 275: restore_errno(orig_errno) ; ! 276: return zapeof(*gptr()); ! 277: } ! 278: ! 279: filebuf* filebuf::close() ! 280: { ! 281: int f = xfd ; ! 282: if ( !opened ) { ! 283: return 0 ; ! 284: } ! 285: if (last_op()==output) overflow(); ! 286: setg(0,0,0) ; ! 287: setp(0,0) ; ! 288: opened = 0 ; ! 289: xfd = -1 ; ! 290: last_seek = EOF ; ! 291: if ( mode != 0 ) { ! 292: mode = 0 ; ! 293: int orig_errno ; ! 294: save_errno(orig_errno) ; ! 295: int ok = ::close(f); ! 296: restore_errno(orig_errno) ; ! 297: return ( ok==EOF ? 0 : this ) ; ! 298: } else { ! 299: return this ; ! 300: } ! 301: } ! 302: ! 303: int filebuf::sync() ! 304: { ! 305: int ok = 0 ; ! 306: int orig_errno ; ! 307: save_errno(orig_errno) ; ! 308: switch(last_op()) { ! 309: case input: ! 310: last_seek = lseek(xfd,gptr()-egptr(),seek_cur) ; ! 311: if ( last_seek < 0 ) { ! 312: ok = EOF ; ! 313: last_seek = EOF ; ! 314: } ! 315: break ; ! 316: case output: ! 317: ok = overflow() ; ! 318: /* This does not result in infinite recursion even though ! 319: * under some circumstances overflow might call sync. ! 320: * it explicitly does not when last_op==output ! 321: */ ! 322: break; ! 323: } ! 324: setp(0,0) ; ! 325: setg(0,0,0) ; ! 326: restore_errno(orig_errno) ; ! 327: return (ok==EOF ? EOF : 0 ) ; ! 328: } ! 329: ! 330: streampos filebuf::seekoff(streamoff p, seek_dir d, int m) ! 331: { ! 332: int orig_errno ; ! 333: save_errno(orig_errno) ; ! 334: ! 335: if ( last_seek == EOF ) { ! 336: last_seek = lseek(xfd,0,seek_cur) ; ! 337: } ! 338: if ( last_seek == EOF ) return EOF ; ! 339: if( SEEK_ARITH_OK && !unbuffered() ) { ! 340: char* refptr = 0 ; ! 341: streampos sneed ; ! 342: streampos sref, minavail, maxavail ; ! 343: ! 344: switch ( last_op() ) { ! 345: case input : { ! 346: refptr = gptr() ; ! 347: sref = last_seek-(egptr()-gptr()) ; ! 348: minavail = last_seek-(egptr()-in_start) ; ! 349: maxavail = last_seek-1 ; ! 350: } break ; ! 351: case output : { ! 352: // only allowable seek during output is ! 353: // to present position. ! 354: refptr = pptr() ; ! 355: sref = last_seek+pptr()-pbase() ; ! 356: minavail = maxavail = sref ; ! 357: } break ; ! 358: } ! 359: switch( d ) { ! 360: case seek_beg : sneed = p ; break ; ! 361: case seek_cur : sneed = sref+p ;break ; ! 362: case seek_end : refptr = 0 ; break ; ! 363: /* Can't do seek_end */ ! 364: } ! 365: if ( refptr && sneed >= minavail && sneed <= maxavail ) { ! 366: switch( last_op() ) { ! 367: case input : { ! 368: setg(eback(),refptr+(sneed-sref),egptr()); ! 369: } break ; ! 370: case output : { ! 371: // Seeking to current position. Nothing to ! 372: // do. ! 373: } break ; ! 374: default : { ! 375: // shouldn't get here. Try to recover somehow ! 376: sync() ; ! 377: seekoff(p,d,m); ! 378: } break ; ! 379: } ! 380: return sneed ; ! 381: } ! 382: if ( refptr && sneed < sref && sneed+blen()/2 > sref ! 383: && last_op() == input ) { ! 384: // looks like we are stepping backward through ! 385: // a file. Performance may be improved by ! 386: // backing up a little extra. ! 387: ! 388: streampos toofar = sneed-blen()/2 ; ! 389: if ( toofar < 0 ) toofar = 0 ; ! 390: sync() ; ! 391: last_seek=lseek(xfd,toofar,seek_beg) ; ! 392: overflow(); ! 393: seekoff(p,d,m); ! 394: } ! 395: } ! 396: ! 397: restore_errno(orig_errno) ; ! 398: if ( sync()==EOF ) return EOF ; ! 399: else { ! 400: last_seek=lseek(xfd,p,d) ; ! 401: return last_seek ; ! 402: } ! 403: } ! 404: ! 405: filebuf::filebuf() ! 406: : xfd(-1), opened(0), mode(0), last_seek(EOF) ! 407: { ! 408: ! 409: } ! 410: ! 411: filebuf::filebuf(int f) ! 412: : xfd(f), opened(1), mode(0), last_seek(EOF) ! 413: { ! 414: ! 415: } ! 416: ! 417: filebuf::filebuf(int f, char* p, int l) ! 418: : streambuf(p,l), xfd(f), opened(1), mode(0), last_seek(EOF) ! 419: { ! 420: ! 421: } ! 422: ! 423: filebuf::~filebuf() { ! 424: close() ; ! 425: } ! 426: ! 427: streambuf* filebuf::setbuf(char* p , int len) ! 428: { ! 429: ! 430: if ( is_open() ) return 0 ; ! 431: setb(0,0) ; ! 432: return streambuf::setbuf(p,len) ; ! 433: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.