1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
25 /* Discipline to treat a contiguous segment of a stream as a stream
26 ** in its own right. The hard part in all this is to allow multiple
27 ** segments of the stream to be used as substreams at the same time.
29 ** Written by David G. Korn and Kiem-Phong Vo (03/18/1998)
32 typedef struct _subfile_s
34 Sfdisc_t disc
; /* sfio discipline */
35 Sfio_t
* parent
; /* parent stream */
36 Sfoff_t offset
; /* starting offset */
37 Sfoff_t extent
; /* size wanted */
38 Sfoff_t here
; /* current seek location */
42 static ssize_t
streamio(Sfio_t
* f
, Void_t
* buf
, size_t n
, Sfdisc_t
* disc
, int type
)
44 static ssize_t
streamio(f
, buf
, n
, disc
, type
)
53 reg Sfoff_t here
, parent
;
56 su
= (Subfile_t
*)disc
;
58 /* read just what we need */
59 if(su
->extent
>= 0 && (ssize_t
)n
> (io
= (ssize_t
)(su
->extent
- su
->here
)) )
64 /* save current location in parent stream */
65 parent
= sfsk(f
,(Sfoff_t
)0,SEEK_CUR
,disc
);
68 here
= su
->here
+ su
->offset
;
69 if(sfsk(f
,here
,SEEK_SET
,disc
) != here
)
72 { if(type
== SF_WRITE
)
73 io
= sfwr(f
,buf
,n
,disc
);
74 else io
= sfrd(f
,buf
,n
,disc
);
79 /* restore parent current position */
80 sfsk(f
,parent
,SEEK_SET
,disc
);
86 static ssize_t
streamwrite(Sfio_t
* f
, const Void_t
* buf
, size_t n
, Sfdisc_t
* disc
)
88 static ssize_t
streamwrite(f
, buf
, n
, disc
)
95 return streamio(f
,(Void_t
*)buf
,n
,disc
,SF_WRITE
);
99 static ssize_t
streamread(Sfio_t
* f
, Void_t
* buf
, size_t n
, Sfdisc_t
* disc
)
101 static ssize_t
streamread(f
, buf
, n
, disc
)
108 return streamio(f
,buf
,n
,disc
,SF_READ
);
112 static Sfoff_t
streamseek(Sfio_t
* f
, Sfoff_t pos
, int type
, Sfdisc_t
* disc
)
114 static Sfoff_t
streamseek(f
, pos
, type
, disc
)
122 reg Sfoff_t here
, parent
;
124 su
= (Subfile_t
*)disc
;
138 { parent
= sfsk(f
,(Sfoff_t
)0,SEEK_CUR
,disc
);
139 if((here
= sfsk(f
,(Sfoff_t
)0,SEEK_END
,disc
)) < 0)
141 else here
-= su
->offset
;
142 sfsk(f
,parent
,SEEK_SET
,disc
);
150 if(pos
< 0 || (su
->extent
>= 0 && pos
>= su
->extent
))
153 return (su
->here
= pos
);
157 static int streamexcept(Sfio_t
* f
, int type
, Void_t
* data
, Sfdisc_t
* disc
)
159 static int streamexcept(f
, type
, data
, disc
)
166 if(type
== SF_FINAL
|| type
== SF_DPOP
)
172 Sfio_t
* sfdcsubstream(Sfio_t
* f
, Sfio_t
* parent
, Sfoff_t offset
, Sfoff_t extent
)
174 Sfio_t
* sfdcsubstream(f
, parent
, offset
, extent
)
175 Sfio_t
* f
; /* stream */
176 Sfio_t
* parent
; /* parent stream */
177 Sfoff_t offset
; /* offset in f */
178 Sfoff_t extent
; /* desired size */
185 /* establish that we can seek to offset */
186 if((here
= sfseek(parent
,(Sfoff_t
)0,SEEK_CUR
)) < 0 || sfseek(parent
,offset
,SEEK_SET
) < 0)
188 else sfseek(parent
,here
,SEEK_SET
);
191 if (!(sp
= f
) && !(sp
= sfnew(NIL(Sfio_t
*), NIL(Void_t
*), (size_t)SF_UNBOUND
, dup(sffileno(parent
)), parent
->flags
)))
194 if(!(su
= (Subfile_t
*)malloc(sizeof(Subfile_t
))))
199 memset(su
, 0, sizeof(*su
));
201 su
->disc
.readf
= streamread
;
202 su
->disc
.writef
= streamwrite
;
203 su
->disc
.seekf
= streamseek
;
204 su
->disc
.exceptf
= streamexcept
;
209 if(sfdisc(sp
, (Sfdisc_t
*)su
) != (Sfdisc_t
*)su
)