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