14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1985-2009 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #include "sfhdr.h" 234887Schin 244887Schin /* Reserve a segment of data or buffer. 254887Schin ** 264887Schin ** Written by Kiem-Phong Vo. 274887Schin */ 284887Schin 294887Schin #if __STD_C 308462SApril.Chin@Sun.COM Void_t* sfreserve(Sfio_t* f, ssize_t size, int type) 314887Schin #else 324887Schin Void_t* sfreserve(f,size,type) 338462SApril.Chin@Sun.COM Sfio_t* f; /* file to peek */ 344887Schin ssize_t size; /* size of peek */ 354887Schin int type; /* LOCKR: lock stream, LASTR: last record */ 364887Schin #endif 374887Schin { 384887Schin reg ssize_t n, now, sz, iosz; 394887Schin reg Sfrsrv_t* rsrv; 404887Schin reg Void_t* data; 414887Schin reg int mode, local; 428462SApril.Chin@Sun.COM SFMTXDECL(f); 434887Schin 448462SApril.Chin@Sun.COM SFMTXENTER(f,NIL(Void_t*)); 454887Schin 464887Schin sz = size < 0 ? -size : size; 474887Schin 484887Schin /* see if we need to bias toward SF_WRITE instead of the default SF_READ */ 494887Schin if(type < 0) 504887Schin mode = 0; 514887Schin else if((mode = type&SF_WRITE) ) 524887Schin type &= ~SF_WRITE; 534887Schin 544887Schin /* return the last record */ 554887Schin if(type == SF_LASTR ) 564887Schin { if((n = f->endb - f->next) > 0 && n == f->val ) 574887Schin { data = (Void_t*)f->next; 584887Schin f->next += n; 594887Schin } 604887Schin else if((rsrv = f->rsrv) && (n = -rsrv->slen) > 0) 614887Schin { rsrv->slen = 0; 624887Schin _Sfi = f->val = n; 634887Schin data = (Void_t*)rsrv->data; 644887Schin } 654887Schin else 664887Schin { _Sfi = f->val = -1; 674887Schin data = NIL(Void_t*); 684887Schin } 694887Schin 704887Schin SFMTXRETURN(f, data); 714887Schin } 724887Schin 734887Schin if(type > 0) 744887Schin { if(type == 1 ) /* upward compatibility mode */ 754887Schin type = SF_LOCKR; 764887Schin else if(type != SF_LOCKR) 774887Schin SFMTXRETURN(f, NIL(Void_t*)); 784887Schin } 794887Schin 804887Schin if(size == 0 && (type < 0 || type == SF_LOCKR) ) 814887Schin { if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) 824887Schin SFMTXRETURN(f, NIL(Void_t*)); 834887Schin 844887Schin SFLOCK(f,0); 854887Schin if((n = f->endb - f->next) < 0) 864887Schin n = 0; 874887Schin 884887Schin goto done; 894887Schin } 904887Schin 914887Schin /* iterate until get to a stream that has data or buffer space */ 924887Schin for(local = 0;; local = SF_LOCAL) 934887Schin { _Sfi = f->val = -1; 944887Schin 954887Schin if(!mode && !(mode = f->flags&SF_READ) ) 964887Schin mode = SF_WRITE; 974887Schin if((int)f->mode != mode && _sfmode(f,mode,local) < 0) 984887Schin { SFOPEN(f,0); 994887Schin SFMTXRETURN(f, NIL(Void_t*)); 1004887Schin } 1014887Schin 1024887Schin SFLOCK(f,local); 1034887Schin 1044887Schin if((n = now = f->endb - f->next) < 0) 1054887Schin n = 0; 1064887Schin if(n > 0 && n >= sz) /* all done */ 1074887Schin break; 1084887Schin 1098462SApril.Chin@Sun.COM /* set amount to perform IO */ 1108462SApril.Chin@Sun.COM if(size == 0 || (f->mode&SF_WRITE)) 1114887Schin iosz = -1; 1128462SApril.Chin@Sun.COM else if(size < 0 && n == 0 && f->push) /* maybe stack-pop */ 113*10898Sroland.mainz@nrubsig.org { if((iosz = f->push->endb - f->push->next) == 0) 114*10898Sroland.mainz@nrubsig.org iosz = f->push->size; 115*10898Sroland.mainz@nrubsig.org if(iosz < sz) 116*10898Sroland.mainz@nrubsig.org iosz = sz; /* so only get what is asked for */ 117*10898Sroland.mainz@nrubsig.org } 1184887Schin else 1198462SApril.Chin@Sun.COM { iosz = sz - n; /* get enough to fulfill requirement */ 1208462SApril.Chin@Sun.COM if(size < 0 && iosz < (f->size - n) ) 1218462SApril.Chin@Sun.COM iosz = f->size - n; /* get as much as possible */ 1228462SApril.Chin@Sun.COM if(iosz <= 0) /* nothing to do */ 1234887Schin break; 1244887Schin } 1254887Schin 1264887Schin /* do a buffer refill or flush */ 1274887Schin now = n; 1284887Schin if(f->mode&SF_WRITE) 1294887Schin (void)SFFLSBUF(f, iosz); 1304887Schin else if(type == SF_LOCKR && f->extent < 0 && (f->flags&SF_SHARE) ) 1314887Schin { if(n == 0) /* peek-read only if there is no buffered data */ 1324887Schin { f->mode |= SF_RV; 1334887Schin (void)SFFILBUF(f, iosz ); 1344887Schin } 1354887Schin if((n = f->endb - f->next) < sz) 1364887Schin { if(f->mode&SF_PKRD) 1374887Schin { f->endb = f->endr = f->next; 1384887Schin f->mode &= ~SF_PKRD; 1394887Schin } 1404887Schin break; 1414887Schin } 1424887Schin } 1438462SApril.Chin@Sun.COM else 1448462SApril.Chin@Sun.COM { /* sfreserve(f,0,0) == sfread(f, sfreserve(f,-1,SF_LOCKR), 0) */ 1458462SApril.Chin@Sun.COM if(size == 0 && type == 0) 1468462SApril.Chin@Sun.COM f->mode |= SF_RV; 1478462SApril.Chin@Sun.COM 1488462SApril.Chin@Sun.COM (void)SFFILBUF(f, iosz ); 1498462SApril.Chin@Sun.COM } 1504887Schin 1514887Schin if((n = f->endb - f->next) <= 0) 1524887Schin n = 0; 1534887Schin 1544887Schin if(n >= sz) /* got it */ 1554887Schin break; 1564887Schin 1574887Schin if(n == now || sferror(f) || sfeof(f)) /* no progress */ 1584887Schin break; 1594887Schin 1604887Schin /* request was only to assess data availability */ 1614887Schin if(type == SF_LOCKR && size > 0 && n > 0 ) 1624887Schin break; 1634887Schin } 1644887Schin 1654887Schin done: /* compute the buffer to be returned */ 1664887Schin data = NIL(Void_t*); 1674887Schin if(size == 0 || n == 0) 1684887Schin { if(n > 0) /* got data */ 1694887Schin data = (Void_t*)f->next; 1704887Schin else if(type == SF_LOCKR && size == 0 && (rsrv = _sfrsrv(f,0)) ) 1714887Schin data = (Void_t*)rsrv->data; 1724887Schin } 1734887Schin else if(n >= sz) /* got data */ 1744887Schin data = (Void_t*)f->next; 1754887Schin else if(f->flags&SF_STRING) /* try extending string buffer */ 1764887Schin { if((f->mode&SF_WRITE) && (f->flags&SF_MALLOC) ) 1774887Schin { (void)SFWR(f,f->next,sz,f->disc); 1784887Schin if((n = f->endb - f->next) >= sz ) 1794887Schin data = (Void_t*)f->next; 1804887Schin } 1814887Schin } 1824887Schin else if(f->mode&SF_WRITE) /* allocate side buffer */ 1834887Schin { if(type == SF_LOCKR && (rsrv = _sfrsrv(f, sz)) ) 1844887Schin data = (Void_t*)rsrv->data; 1854887Schin } 1864887Schin else if(type != SF_LOCKR && sz > f->size && (rsrv = _sfrsrv(f,sz)) ) 1874887Schin { if((n = SFREAD(f,(Void_t*)rsrv->data,sz)) >= sz) /* read side buffer */ 1884887Schin data = (Void_t*)rsrv->data; 1894887Schin else rsrv->slen = -n; 1904887Schin } 1914887Schin 1924887Schin SFOPEN(f,0); 1934887Schin 1944887Schin if(data) 1954887Schin { if(type == SF_LOCKR) 1964887Schin { f->mode |= SF_PEEK; 1974887Schin if((f->mode & SF_READ) && size == 0 && data != f->next) 1984887Schin f->mode |= SF_GETR; /* so sfread() will unlock */ 1994887Schin f->endr = f->endw = f->data; 2004887Schin } 2014887Schin else 2024887Schin { if(data == (Void_t*)f->next) 2034887Schin f->next += (size >= 0 ? size : n); 2044887Schin } 2054887Schin } 2064887Schin 2074887Schin _Sfi = f->val = n; /* return true buffer size */ 2084887Schin 2094887Schin SFMTXRETURN(f, data); 2104887Schin } 211