xref: /onnv-gate/usr/src/lib/libast/common/disc/sfdcsubstr.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 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	"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
streamio(Sfio_t * f,Void_t * buf,size_t n,Sfdisc_t * disc,int type)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
streamwrite(Sfio_t * f,const Void_t * buf,size_t n,Sfdisc_t * disc)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
streamread(Sfio_t * f,Void_t * buf,size_t n,Sfdisc_t * disc)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
streamseek(Sfio_t * f,Sfoff_t pos,int type,Sfdisc_t * disc)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
streamexcept(Sfio_t * f,int type,Void_t * data,Sfdisc_t * disc)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
sfdcsubstream(Sfio_t * f,Sfio_t * parent,Sfoff_t offset,Sfoff_t extent)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