14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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 "sfdchdr.h" 234887Schin 244887Schin /* Discipline to make an unseekable read stream seekable 254887Schin ** 264887Schin ** sfraise(f,SFSK_DISCARD,0) discards previous seek data 274887Schin ** but seeks from current offset on still allowed 284887Schin ** 294887Schin ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998. 304887Schin */ 314887Schin 324887Schin typedef struct _skable_s 334887Schin { Sfdisc_t disc; /* sfio discipline */ 344887Schin Sfio_t* shadow; /* to shadow data */ 354887Schin Sfoff_t discard;/* sfseek(f,-1,SEEK_SET) discarded data */ 364887Schin Sfoff_t extent; /* shadow extent */ 374887Schin int eof; /* if eof has been reached */ 384887Schin } Seek_t; 394887Schin 404887Schin #if __STD_C 414887Schin static ssize_t skwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) 424887Schin #else 434887Schin static ssize_t skwrite(f, buf, n, disc) 444887Schin Sfio_t* f; /* stream involved */ 454887Schin Void_t* buf; /* buffer to read into */ 464887Schin size_t n; /* number of bytes to read */ 474887Schin Sfdisc_t* disc; /* discipline */ 484887Schin #endif 494887Schin { 504887Schin return (ssize_t)(-1); 514887Schin } 524887Schin 534887Schin #if __STD_C 544887Schin static ssize_t skread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) 554887Schin #else 564887Schin static ssize_t skread(f, buf, n, disc) 574887Schin Sfio_t* f; /* stream involved */ 584887Schin Void_t* buf; /* buffer to read into */ 594887Schin size_t n; /* number of bytes to read */ 604887Schin Sfdisc_t* disc; /* discipline */ 614887Schin #endif 624887Schin { 634887Schin Seek_t* sk; 644887Schin Sfio_t* sf; 654887Schin Sfoff_t addr; 664887Schin ssize_t r, w, p; 674887Schin 684887Schin sk = (Seek_t*)disc; 694887Schin sf = sk->shadow; 704887Schin if(sk->eof) 714887Schin return sfread(sf,buf,n); 724887Schin 734887Schin addr = sfseek(sf,(Sfoff_t)0,SEEK_CUR); 744887Schin 754887Schin if(addr+n <= sk->extent) 764887Schin return sfread(sf,buf,n); 774887Schin 784887Schin if((r = (ssize_t)(sk->extent-addr)) > 0) 794887Schin { if((w = sfread(sf,buf,r)) != r) 804887Schin return w; 814887Schin buf = (char*)buf + r; 824887Schin n -= r; 834887Schin } 844887Schin 854887Schin /* do a raw read */ 864887Schin if((w = sfrd(f,buf,n,disc)) <= 0) 874887Schin { sk->eof = 1; 884887Schin w = 0; 894887Schin } 904887Schin else 914887Schin { 924887Schin if((p = sfwrite(sf,buf,w)) != w) 934887Schin sk->eof = 1; 944887Schin if(p > 0) 954887Schin sk->extent += p; 964887Schin } 974887Schin 984887Schin return r+w; 994887Schin } 1004887Schin 1014887Schin #if __STD_C 1024887Schin static Sfoff_t skseek(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc) 1034887Schin #else 1044887Schin static Sfoff_t skseek(f, addr, type, disc) 1054887Schin Sfio_t* f; 1064887Schin Sfoff_t addr; 1074887Schin int type; 1084887Schin Sfdisc_t* disc; 1094887Schin #endif 1104887Schin { 1114887Schin Seek_t* sk; 1124887Schin Sfio_t* sf; 1134887Schin char buf[SF_BUFSIZE]; 1144887Schin ssize_t r, w; 1154887Schin 1164887Schin sk = (Seek_t*)disc; 1174887Schin sf = sk->shadow; 1184887Schin 1194887Schin switch (type) 1204887Schin { 1214887Schin case SEEK_SET: 1224887Schin addr -= sk->discard; 1234887Schin break; 1244887Schin case SEEK_CUR: 1254887Schin addr += sftell(sf); 1264887Schin break; 1274887Schin case SEEK_END: 1284887Schin addr += sk->extent; 1294887Schin break; 1304887Schin default: 1314887Schin return -1; 1324887Schin } 1334887Schin 1344887Schin if(addr < 0) 1354887Schin return (Sfoff_t)(-1); 1364887Schin else if(addr > sk->extent) 1374887Schin { if(sk->eof) 1384887Schin return (Sfoff_t)(-1); 1394887Schin 1404887Schin /* read enough to reach the seek point */ 1414887Schin while(addr > sk->extent) 1424887Schin { if(addr > sk->extent+sizeof(buf) ) 1434887Schin w = sizeof(buf); 1444887Schin else w = (int)(addr-sk->extent); 1454887Schin if((r = sfrd(f,buf,w,disc)) <= 0) 1464887Schin w = r-1; 1474887Schin else if((w = sfwrite(sf,buf,r)) > 0) 1484887Schin sk->extent += w; 1494887Schin if(w != r) 1504887Schin { sk->eof = 1; 1514887Schin break; 1524887Schin } 1534887Schin } 1544887Schin 1554887Schin if(addr > sk->extent) 1564887Schin return (Sfoff_t)(-1); 1574887Schin } 1584887Schin 1594887Schin return sfseek(sf,addr,SEEK_SET) + sk->discard; 1604887Schin } 1614887Schin 1624887Schin /* on close, remove the discipline */ 1634887Schin #if __STD_C 1644887Schin static int skexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) 1654887Schin #else 1664887Schin static int skexcept(f,type,data,disc) 1674887Schin Sfio_t* f; 1684887Schin int type; 1694887Schin Void_t* data; 1704887Schin Sfdisc_t* disc; 1714887Schin #endif 1724887Schin { 1734887Schin Seek_t* sk; 1744887Schin 1754887Schin sk = (Seek_t*)disc; 1764887Schin 1774887Schin switch (type) 1784887Schin { 1794887Schin case SF_FINAL: 1804887Schin case SF_DPOP: 1814887Schin sfclose(sk->shadow); 1824887Schin free(disc); 1834887Schin break; 1844887Schin case SFSK_DISCARD: 1854887Schin sk->eof = 0; 1864887Schin sk->discard += sk->extent; 1874887Schin sk->extent = 0; 1884887Schin sfseek(sk->shadow,(Sfoff_t)0,SEEK_SET); 1894887Schin break; 1904887Schin } 1914887Schin return 0; 1924887Schin } 1934887Schin 1944887Schin #if __STD_C 1954887Schin int sfdcseekable(Sfio_t* f) 1964887Schin #else 1974887Schin int sfdcseekable(f) 1984887Schin Sfio_t* f; 1994887Schin #endif 2004887Schin { 2014887Schin reg Seek_t* sk; 2024887Schin 2034887Schin /* see if already seekable */ 2044887Schin if(sfseek(f,(Sfoff_t)0,SEEK_CUR) >= 0) 2054887Schin return 0; 2064887Schin 2074887Schin if(!(sk = (Seek_t*)malloc(sizeof(Seek_t))) ) 2084887Schin return -1; 2094887Schin memset(sk, 0, sizeof(*sk)); 2104887Schin 2114887Schin sk->disc.readf = skread; 2124887Schin sk->disc.writef = skwrite; 2134887Schin sk->disc.seekf = skseek; 2144887Schin sk->disc.exceptf = skexcept; 2154887Schin sk->shadow = sftmp(SF_BUFSIZE); 2164887Schin sk->discard = 0; 2174887Schin sk->extent = 0; 2184887Schin sk->eof = 0; 2194887Schin 2204887Schin if(sfdisc(f, (Sfdisc_t*)sk) != (Sfdisc_t*)sk) 2214887Schin { sfclose(sk->shadow); 2224887Schin free(sk); 2234887Schin return -1; 2244887Schin } 2254887Schin 2264887Schin return 0; 2274887Schin } 228