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