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 254887Schin /* Discipline to treat a contiguous segment of a stream as a stream 264887Schin ** in its own right. The hard part in all this is to allow multiple 274887Schin ** segments of the stream to be used as substreams at the same time. 284887Schin ** 294887Schin ** Written by David G. Korn and Kiem-Phong Vo (03/18/1998) 304887Schin */ 314887Schin 324887Schin typedef struct _subfile_s 334887Schin { 344887Schin Sfdisc_t disc; /* sfio discipline */ 354887Schin Sfio_t* parent; /* parent stream */ 364887Schin Sfoff_t offset; /* starting offset */ 374887Schin Sfoff_t extent; /* size wanted */ 384887Schin Sfoff_t here; /* current seek location */ 394887Schin } Subfile_t; 404887Schin 414887Schin #if __STD_C 424887Schin static ssize_t streamio(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc, int type) 434887Schin #else 444887Schin static ssize_t streamio(f, buf, n, disc, type) 454887Schin Sfio_t* f; 464887Schin Void_t* buf; 474887Schin size_t n; 484887Schin Sfdisc_t* disc; 494887Schin int type; 504887Schin #endif 514887Schin { 524887Schin reg Subfile_t *su; 534887Schin reg Sfoff_t here, parent; 544887Schin reg ssize_t io; 554887Schin 564887Schin su = (Subfile_t*)disc; 574887Schin 584887Schin /* read just what we need */ 594887Schin if(su->extent >= 0 && (ssize_t)n > (io = (ssize_t)(su->extent - su->here)) ) 604887Schin n = io; 614887Schin if(n <= 0) 624887Schin return n; 634887Schin 644887Schin /* save current location in parent stream */ 654887Schin parent = sfsk(f,(Sfoff_t)0,SEEK_CUR,disc); 664887Schin 674887Schin /* read data */ 684887Schin here = su->here + su->offset; 694887Schin if(sfsk(f,here,SEEK_SET,disc) != here) 704887Schin io = 0; 714887Schin else 724887Schin { if(type == SF_WRITE) 734887Schin io = sfwr(f,buf,n,disc); 744887Schin else io = sfrd(f,buf,n,disc); 754887Schin if(io > 0) 764887Schin su->here += io; 774887Schin } 784887Schin 794887Schin /* restore parent current position */ 804887Schin sfsk(f,parent,SEEK_SET,disc); 814887Schin 824887Schin return io; 834887Schin } 844887Schin 854887Schin #if __STD_C 864887Schin static ssize_t streamwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) 874887Schin #else 884887Schin static ssize_t streamwrite(f, buf, n, disc) 894887Schin Sfio_t* f; 904887Schin Void_t* buf; 914887Schin size_t n; 924887Schin Sfdisc_t* disc; 934887Schin #endif 944887Schin { 954887Schin return streamio(f,(Void_t*)buf,n,disc,SF_WRITE); 964887Schin } 974887Schin 984887Schin #if __STD_C 994887Schin static ssize_t streamread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) 1004887Schin #else 1014887Schin static ssize_t streamread(f, buf, n, disc) 1024887Schin Sfio_t* f; 1034887Schin Void_t* buf; 1044887Schin size_t n; 1054887Schin Sfdisc_t* disc; 1064887Schin #endif 1074887Schin { 1084887Schin return streamio(f,buf,n,disc,SF_READ); 1094887Schin } 1104887Schin 1114887Schin #if __STD_C 1124887Schin static Sfoff_t streamseek(Sfio_t* f, Sfoff_t pos, int type, Sfdisc_t* disc) 1134887Schin #else 1144887Schin static Sfoff_t streamseek(f, pos, type, disc) 1154887Schin Sfio_t* f; 1164887Schin Sfoff_t pos; 1174887Schin int type; 1184887Schin Sfdisc_t* disc; 1194887Schin #endif 1204887Schin { 1214887Schin reg Subfile_t* su; 1224887Schin reg Sfoff_t here, parent; 1234887Schin 1244887Schin su = (Subfile_t*)disc; 1254887Schin 1264887Schin switch(type) 1274887Schin { 1284887Schin case SEEK_SET: 1294887Schin here = 0; 1304887Schin break; 1314887Schin case SEEK_CUR: 1324887Schin here = su->here; 1334887Schin break; 1344887Schin case SEEK_END: 1354887Schin if(su->extent >= 0) 1364887Schin here = su->extent; 1374887Schin else 1384887Schin { parent = sfsk(f,(Sfoff_t)0,SEEK_CUR,disc); 1394887Schin if((here = sfsk(f,(Sfoff_t)0,SEEK_END,disc)) < 0) 1404887Schin return -1; 1414887Schin else here -= su->offset; 1424887Schin sfsk(f,parent,SEEK_SET,disc); 1434887Schin } 1444887Schin break; 1454887Schin default: 1464887Schin return -1; 1474887Schin } 1484887Schin 1494887Schin pos += here; 1504887Schin if(pos < 0 || (su->extent >= 0 && pos >= su->extent)) 1514887Schin return -1; 1524887Schin 1534887Schin return (su->here = pos); 1544887Schin } 1554887Schin 1564887Schin #if __STD_C 1574887Schin static int streamexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) 1584887Schin #else 1594887Schin static int streamexcept(f, type, data, disc) 1604887Schin Sfio_t* f; 1614887Schin int type; 1624887Schin Void_t* data; 1634887Schin Sfdisc_t* disc; 1644887Schin #endif 1654887Schin { 1664887Schin if(type == SF_FINAL || type == SF_DPOP) 1674887Schin free(disc); 1684887Schin return 0; 1694887Schin } 1704887Schin 1714887Schin #if __STD_C 1724887Schin Sfio_t* sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent) 1734887Schin #else 1744887Schin Sfio_t* sfdcsubstream(f, parent, offset, extent) 1754887Schin Sfio_t* f; /* stream */ 1764887Schin Sfio_t* parent; /* parent stream */ 1774887Schin Sfoff_t offset; /* offset in f */ 1784887Schin Sfoff_t extent; /* desired size */ 1794887Schin #endif 1804887Schin { 1814887Schin reg Sfio_t* sp; 1824887Schin reg Subfile_t* su; 1834887Schin reg Sfoff_t here; 1844887Schin 1854887Schin /* establish that we can seek to offset */ 1864887Schin if((here = sfseek(parent,(Sfoff_t)0,SEEK_CUR)) < 0 || sfseek(parent,offset,SEEK_SET) < 0) 1874887Schin return 0; 1884887Schin else sfseek(parent,here,SEEK_SET); 1894887Schin sfpurge(parent); 1904887Schin 1914887Schin if (!(sp = f) && !(sp = sfnew(NIL(Sfio_t*), NIL(Void_t*), (size_t)SF_UNBOUND, dup(sffileno(parent)), parent->flags))) 1924887Schin return 0; 1934887Schin 1944887Schin if(!(su = (Subfile_t*)malloc(sizeof(Subfile_t)))) 1954887Schin { if(sp != f) 1964887Schin sfclose(sp); 1974887Schin return 0; 1984887Schin } 1994887Schin memset(su, 0, sizeof(*su)); 2004887Schin 2014887Schin su->disc.readf = streamread; 2024887Schin su->disc.writef = streamwrite; 2034887Schin su->disc.seekf = streamseek; 2044887Schin su->disc.exceptf = streamexcept; 2054887Schin su->parent = parent; 2064887Schin su->offset = offset; 2074887Schin su->extent = extent; 2084887Schin 2094887Schin if(sfdisc(sp, (Sfdisc_t*)su) != (Sfdisc_t*)su) 2104887Schin { free(su); 2114887Schin if(sp != f) 2124887Schin sfclose(sp); 2134887Schin return 0; 2144887Schin } 2154887Schin 2164887Schin return sp; 2174887Schin } 218