xref: /onnv-gate/usr/src/lib/libast/common/disc/sfdcsubstr.c (revision 4887:feebf9260c2e)
1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
18*4887Schin *                  David Korn <dgk@research.att.com>                   *
19*4887Schin *                   Phong Vo <kpv@research.att.com>                    *
20*4887Schin *                                                                      *
21*4887Schin ***********************************************************************/
22*4887Schin #include	"sfdchdr.h"
23*4887Schin 
24*4887Schin 
25*4887Schin /*	Discipline to treat a contiguous segment of a stream as a stream
26*4887Schin **	in its own right. The hard part in all this is to allow multiple
27*4887Schin **	segments of the stream to be used as substreams at the same time.
28*4887Schin **
29*4887Schin **	Written by David G. Korn and Kiem-Phong Vo (03/18/1998)
30*4887Schin */
31*4887Schin 
32*4887Schin typedef struct _subfile_s
33*4887Schin {
34*4887Schin 	Sfdisc_t	disc;	/* sfio discipline */
35*4887Schin 	Sfio_t*		parent;	/* parent stream */
36*4887Schin 	Sfoff_t		offset;	/* starting offset */
37*4887Schin 	Sfoff_t		extent;	/* size wanted */
38*4887Schin 	Sfoff_t		here;	/* current seek location */
39*4887Schin } Subfile_t;
40*4887Schin 
41*4887Schin #if __STD_C
42*4887Schin static ssize_t streamio(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc, int type)
43*4887Schin #else
44*4887Schin static ssize_t streamio(f, buf, n, disc, type)
45*4887Schin Sfio_t*		f;
46*4887Schin Void_t*		buf;
47*4887Schin size_t		n;
48*4887Schin Sfdisc_t*	disc;
49*4887Schin int		type;
50*4887Schin #endif
51*4887Schin {
52*4887Schin 	reg Subfile_t	*su;
53*4887Schin 	reg Sfoff_t	here, parent;
54*4887Schin 	reg ssize_t	io;
55*4887Schin 
56*4887Schin 	su = (Subfile_t*)disc;
57*4887Schin 
58*4887Schin 	/* read just what we need */
59*4887Schin 	if(su->extent >= 0 && (ssize_t)n > (io = (ssize_t)(su->extent - su->here)) )
60*4887Schin 		n = io;
61*4887Schin 	if(n <= 0)
62*4887Schin 		return n;
63*4887Schin 
64*4887Schin 	/* save current location in parent stream */
65*4887Schin 	parent = sfsk(f,(Sfoff_t)0,SEEK_CUR,disc);
66*4887Schin 
67*4887Schin 	/* read data */
68*4887Schin 	here = su->here + su->offset;
69*4887Schin 	if(sfsk(f,here,SEEK_SET,disc) != here)
70*4887Schin 		io = 0;
71*4887Schin 	else
72*4887Schin 	{	if(type == SF_WRITE)
73*4887Schin 			io = sfwr(f,buf,n,disc);
74*4887Schin 		else	io = sfrd(f,buf,n,disc);
75*4887Schin 		if(io > 0)
76*4887Schin 			su->here += io;
77*4887Schin 	}
78*4887Schin 
79*4887Schin 	/* restore parent current position */
80*4887Schin 	sfsk(f,parent,SEEK_SET,disc);
81*4887Schin 
82*4887Schin 	return io;
83*4887Schin }
84*4887Schin 
85*4887Schin #if __STD_C
86*4887Schin static ssize_t streamwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
87*4887Schin #else
88*4887Schin static ssize_t streamwrite(f, buf, n, disc)
89*4887Schin Sfio_t*		f;
90*4887Schin Void_t*		buf;
91*4887Schin size_t		n;
92*4887Schin Sfdisc_t*	disc;
93*4887Schin #endif
94*4887Schin {
95*4887Schin 	return streamio(f,(Void_t*)buf,n,disc,SF_WRITE);
96*4887Schin }
97*4887Schin 
98*4887Schin #if __STD_C
99*4887Schin static ssize_t streamread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
100*4887Schin #else
101*4887Schin static ssize_t streamread(f, buf, n, disc)
102*4887Schin Sfio_t*		f;
103*4887Schin Void_t*		buf;
104*4887Schin size_t		n;
105*4887Schin Sfdisc_t*	disc;
106*4887Schin #endif
107*4887Schin {
108*4887Schin 	return streamio(f,buf,n,disc,SF_READ);
109*4887Schin }
110*4887Schin 
111*4887Schin #if __STD_C
112*4887Schin static Sfoff_t streamseek(Sfio_t* f, Sfoff_t pos, int type, Sfdisc_t* disc)
113*4887Schin #else
114*4887Schin static Sfoff_t streamseek(f, pos, type, disc)
115*4887Schin Sfio_t*		f;
116*4887Schin Sfoff_t		pos;
117*4887Schin int		type;
118*4887Schin Sfdisc_t*	disc;
119*4887Schin #endif
120*4887Schin {
121*4887Schin 	reg Subfile_t*	su;
122*4887Schin 	reg Sfoff_t	here, parent;
123*4887Schin 
124*4887Schin 	su = (Subfile_t*)disc;
125*4887Schin 
126*4887Schin 	switch(type)
127*4887Schin 	{
128*4887Schin 	case SEEK_SET:
129*4887Schin 		here = 0;
130*4887Schin 		break;
131*4887Schin 	case SEEK_CUR:
132*4887Schin 		here = su->here;
133*4887Schin 		break;
134*4887Schin 	case SEEK_END:
135*4887Schin 		if(su->extent >= 0)
136*4887Schin 			here = su->extent;
137*4887Schin 		else
138*4887Schin 		{	parent = sfsk(f,(Sfoff_t)0,SEEK_CUR,disc);
139*4887Schin 			if((here = sfsk(f,(Sfoff_t)0,SEEK_END,disc)) < 0)
140*4887Schin 				return -1;
141*4887Schin 			else	here -= su->offset;
142*4887Schin 			sfsk(f,parent,SEEK_SET,disc);
143*4887Schin 		}
144*4887Schin 		break;
145*4887Schin 	default:
146*4887Schin 		return -1;
147*4887Schin 	}
148*4887Schin 
149*4887Schin 	pos += here;
150*4887Schin 	if(pos < 0 || (su->extent >= 0 && pos >= su->extent))
151*4887Schin 		return -1;
152*4887Schin 
153*4887Schin 	return (su->here = pos);
154*4887Schin }
155*4887Schin 
156*4887Schin #if __STD_C
157*4887Schin static int streamexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
158*4887Schin #else
159*4887Schin static int streamexcept(f, type, data, disc)
160*4887Schin Sfio_t*		f;
161*4887Schin int		type;
162*4887Schin Void_t*		data;
163*4887Schin Sfdisc_t*	disc;
164*4887Schin #endif
165*4887Schin {
166*4887Schin 	if(type == SF_FINAL || type == SF_DPOP)
167*4887Schin 		free(disc);
168*4887Schin 	return 0;
169*4887Schin }
170*4887Schin 
171*4887Schin #if __STD_C
172*4887Schin Sfio_t* sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent)
173*4887Schin #else
174*4887Schin Sfio_t* sfdcsubstream(f, parent, offset, extent)
175*4887Schin Sfio_t*	f;	/* stream */
176*4887Schin Sfio_t*	parent;	/* parent stream */
177*4887Schin Sfoff_t	offset;	/* offset in f */
178*4887Schin Sfoff_t	extent;	/* desired size */
179*4887Schin #endif
180*4887Schin {
181*4887Schin 	reg Sfio_t*	sp;
182*4887Schin 	reg Subfile_t*	su;
183*4887Schin 	reg Sfoff_t	here;
184*4887Schin 
185*4887Schin 	/* establish that we can seek to offset */
186*4887Schin 	if((here = sfseek(parent,(Sfoff_t)0,SEEK_CUR)) < 0 || sfseek(parent,offset,SEEK_SET) < 0)
187*4887Schin 		return 0;
188*4887Schin 	else	sfseek(parent,here,SEEK_SET);
189*4887Schin 	sfpurge(parent);
190*4887Schin 
191*4887Schin 	if (!(sp = f) && !(sp = sfnew(NIL(Sfio_t*), NIL(Void_t*), (size_t)SF_UNBOUND, dup(sffileno(parent)), parent->flags)))
192*4887Schin 		return 0;
193*4887Schin 
194*4887Schin 	if(!(su = (Subfile_t*)malloc(sizeof(Subfile_t))))
195*4887Schin 	{	if(sp != f)
196*4887Schin 			sfclose(sp);
197*4887Schin 		return 0;
198*4887Schin 	}
199*4887Schin 	memset(su, 0, sizeof(*su));
200*4887Schin 
201*4887Schin 	su->disc.readf = streamread;
202*4887Schin 	su->disc.writef = streamwrite;
203*4887Schin 	su->disc.seekf = streamseek;
204*4887Schin 	su->disc.exceptf = streamexcept;
205*4887Schin 	su->parent = parent;
206*4887Schin 	su->offset = offset;
207*4887Schin 	su->extent = extent;
208*4887Schin 
209*4887Schin 	if(sfdisc(sp, (Sfdisc_t*)su) != (Sfdisc_t*)su)
210*4887Schin 	{	free(su);
211*4887Schin 		if(sp != f)
212*4887Schin 			sfclose(sp);
213*4887Schin 		return 0;
214*4887Schin 	}
215*4887Schin 
216*4887Schin 	return sp;
217*4887Schin }
218