3
/* Discipline to make an unseekable read stream seekable
5
** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
8
typedef struct _skable_s
9
{ Sfdisc_t disc; /* sfio discipline */
10
Sfio_t* shadow; /* to shadow data */
11
int eof; /* if eof has been reached */
15
static ssize_t skwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
17
static ssize_t skwrite(f, buf, n, disc)
18
Sfio_t* f; /* stream involved */
19
Void_t* buf; /* buffer to read into */
20
size_t n; /* number of bytes to read */
21
Sfdisc_t* disc; /* discipline */
28
static ssize_t skread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
30
static ssize_t skread(f, buf, n, disc)
31
Sfio_t* f; /* stream involved */
32
Void_t* buf; /* buffer to read into */
33
size_t n; /* number of bytes to read */
34
Sfdisc_t* disc; /* discipline */
45
return sfread(sf,buf,n);
47
addr = sfseek(sf,(Sfoff_t)0,1);
51
return sfread(sf,buf,n);
53
if((r = (ssize_t)(extent-addr)) > 0)
54
{ if((w = sfread(sf,buf,r)) != r)
61
if((w = sfrd(f,buf,n,disc)) <= 0)
65
else if(sfwrite(sf,buf,w) != w)
72
static Sfoff_t skseek(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc)
74
static Sfoff_t skseek(f, addr, type, disc)
87
if(type < 0 || type > 2)
93
extent = sfseek(sf,(Sfoff_t)0,2);
100
return (Sfoff_t)(-1);
101
else if(addr > extent)
103
return (Sfoff_t)(-1);
105
/* read enough to reach the seek point */
107
{ if(addr > extent+sizeof(buf) )
109
else w = (int)(addr-extent);
110
if((r = sfrd(f,buf,w,disc)) <= 0)
112
else if((w = sfwrite(sf,buf,r)) > 0)
121
return (Sfoff_t)(-1);
124
return sfseek(sf,addr,0);
127
/* on close, remove the discipline */
129
static skexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
131
static skexcept(f,type,data,disc)
138
if(type == SF_FINAL || type == SF_DPOP)
139
{ sfclose(((Seek_t*)disc)->shadow);
146
int sfdcseekable(Sfio_t* f)
154
/* see if already seekable */
155
if(sfseek(f,(Sfoff_t)0,1) >= 0)
158
if(!(sk = (Seek_t*)malloc(sizeof(Seek_t))) )
161
sk->disc.readf = skread;
162
sk->disc.writef = skwrite;
163
sk->disc.seekf = skseek;
164
sk->disc.exceptf = skexcept;
165
sk->shadow = sftmp(SF_BUFSIZE);
168
if(sfdisc(f, (Sfdisc_t*)sk) != (Sfdisc_t*)sk)
169
{ sfclose(sk->shadow);