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 ***********************************************************************/
24 /* Discipline to make an unseekable read stream seekable
26 ** sfraise(f,SFSK_DISCARD,0) discards previous seek data
27 ** but seeks from current offset on still allowed
29 ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
32 typedef struct _skable_s
33 { Sfdisc_t disc
; /* sfio discipline */
34 Sfio_t
* shadow
; /* to shadow data */
35 Sfoff_t discard
;/* sfseek(f,-1,SEEK_SET) discarded data */
36 Sfoff_t extent
; /* shadow extent */
37 int eof
; /* if eof has been reached */
41 static ssize_t
skwrite(Sfio_t
* f
, const Void_t
* buf
, size_t n
, Sfdisc_t
* disc
)
43 static ssize_t
skwrite(f
, buf
, n
, disc
)
44 Sfio_t
* f
; /* stream involved */
45 Void_t
* buf
; /* buffer to read into */
46 size_t n
; /* number of bytes to read */
47 Sfdisc_t
* disc
; /* discipline */
54 static ssize_t
skread(Sfio_t
* f
, Void_t
* buf
, size_t n
, Sfdisc_t
* disc
)
56 static ssize_t
skread(f
, buf
, n
, disc
)
57 Sfio_t
* f
; /* stream involved */
58 Void_t
* buf
; /* buffer to read into */
59 size_t n
; /* number of bytes to read */
60 Sfdisc_t
* disc
; /* discipline */
71 return sfread(sf
,buf
,n
);
73 addr
= sfseek(sf
,(Sfoff_t
)0,SEEK_CUR
);
75 if(addr
+n
<= sk
->extent
)
76 return sfread(sf
,buf
,n
);
78 if((r
= (ssize_t
)(sk
->extent
-addr
)) > 0)
79 { if((w
= sfread(sf
,buf
,r
)) != r
)
86 if((w
= sfrd(f
,buf
,n
,disc
)) <= 0)
92 if((p
= sfwrite(sf
,buf
,w
)) != w
)
102 static Sfoff_t
skseek(Sfio_t
* f
, Sfoff_t addr
, int type
, Sfdisc_t
* disc
)
104 static Sfoff_t
skseek(f
, addr
, type
, disc
)
113 char buf
[SF_BUFSIZE
];
135 return (Sfoff_t
)(-1);
136 else if(addr
> sk
->extent
)
138 return (Sfoff_t
)(-1);
140 /* read enough to reach the seek point */
141 while(addr
> sk
->extent
)
142 { if(addr
> sk
->extent
+sizeof(buf
) )
144 else w
= (int)(addr
-sk
->extent
);
145 if((r
= sfrd(f
,buf
,w
,disc
)) <= 0)
147 else if((w
= sfwrite(sf
,buf
,r
)) > 0)
155 if(addr
> sk
->extent
)
156 return (Sfoff_t
)(-1);
159 return sfseek(sf
,addr
,SEEK_SET
) + sk
->discard
;
162 /* on close, remove the discipline */
164 static int skexcept(Sfio_t
* f
, int type
, Void_t
* data
, Sfdisc_t
* disc
)
166 static int skexcept(f
,type
,data
,disc
)
186 sk
->discard
+= sk
->extent
;
188 sfseek(sk
->shadow
,(Sfoff_t
)0,SEEK_SET
);
195 int sfdcseekable(Sfio_t
* f
)
203 /* see if already seekable */
204 if(sfseek(f
,(Sfoff_t
)0,SEEK_CUR
) >= 0)
207 if(!(sk
= (Seek_t
*)malloc(sizeof(Seek_t
))) )
209 memset(sk
, 0, sizeof(*sk
));
211 sk
->disc
.readf
= skread
;
212 sk
->disc
.writef
= skwrite
;
213 sk
->disc
.seekf
= skseek
;
214 sk
->disc
.exceptf
= skexcept
;
215 sk
->shadow
= sftmp(SF_BUFSIZE
);
220 if(sfdisc(f
, (Sfdisc_t
*)sk
) != (Sfdisc_t
*)sk
)
221 { sfclose(sk
->shadow
);