Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/disc/sfdcseekable.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#include "sfdchdr.h"
23
24
/* Discipline to make an unseekable read stream seekable
25
**
26
** sfraise(f,SFSK_DISCARD,0) discards previous seek data
27
** but seeks from current offset on still allowed
28
**
29
** Written by Kiem-Phong Vo, [email protected], 03/18/1998.
30
*/
31
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 */
38
} Seek_t;
39
40
#if __STD_C
41
static ssize_t skwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
42
#else
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 */
48
#endif
49
{
50
return (ssize_t)(-1);
51
}
52
53
#if __STD_C
54
static ssize_t skread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
55
#else
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 */
61
#endif
62
{
63
Seek_t* sk;
64
Sfio_t* sf;
65
Sfoff_t addr;
66
ssize_t r, w, p;
67
68
sk = (Seek_t*)disc;
69
sf = sk->shadow;
70
if(sk->eof)
71
return sfread(sf,buf,n);
72
73
addr = sfseek(sf,(Sfoff_t)0,SEEK_CUR);
74
75
if(addr+n <= sk->extent)
76
return sfread(sf,buf,n);
77
78
if((r = (ssize_t)(sk->extent-addr)) > 0)
79
{ if((w = sfread(sf,buf,r)) != r)
80
return w;
81
buf = (char*)buf + r;
82
n -= r;
83
}
84
85
/* do a raw read */
86
if((w = sfrd(f,buf,n,disc)) <= 0)
87
{ sk->eof = 1;
88
w = 0;
89
}
90
else
91
{
92
if((p = sfwrite(sf,buf,w)) != w)
93
sk->eof = 1;
94
if(p > 0)
95
sk->extent += p;
96
}
97
98
return r+w;
99
}
100
101
#if __STD_C
102
static Sfoff_t skseek(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc)
103
#else
104
static Sfoff_t skseek(f, addr, type, disc)
105
Sfio_t* f;
106
Sfoff_t addr;
107
int type;
108
Sfdisc_t* disc;
109
#endif
110
{
111
Seek_t* sk;
112
Sfio_t* sf;
113
char buf[SF_BUFSIZE];
114
ssize_t r, w;
115
116
sk = (Seek_t*)disc;
117
sf = sk->shadow;
118
119
switch (type)
120
{
121
case SEEK_SET:
122
addr -= sk->discard;
123
break;
124
case SEEK_CUR:
125
addr += sftell(sf);
126
break;
127
case SEEK_END:
128
addr += sk->extent;
129
break;
130
default:
131
return -1;
132
}
133
134
if(addr < 0)
135
return (Sfoff_t)(-1);
136
else if(addr > sk->extent)
137
{ if(sk->eof)
138
return (Sfoff_t)(-1);
139
140
/* read enough to reach the seek point */
141
while(addr > sk->extent)
142
{ if(addr > sk->extent+sizeof(buf) )
143
w = sizeof(buf);
144
else w = (int)(addr-sk->extent);
145
if((r = sfrd(f,buf,w,disc)) <= 0)
146
w = r-1;
147
else if((w = sfwrite(sf,buf,r)) > 0)
148
sk->extent += w;
149
if(w != r)
150
{ sk->eof = 1;
151
break;
152
}
153
}
154
155
if(addr > sk->extent)
156
return (Sfoff_t)(-1);
157
}
158
159
return sfseek(sf,addr,SEEK_SET) + sk->discard;
160
}
161
162
/* on close, remove the discipline */
163
#if __STD_C
164
static int skexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
165
#else
166
static int skexcept(f,type,data,disc)
167
Sfio_t* f;
168
int type;
169
Void_t* data;
170
Sfdisc_t* disc;
171
#endif
172
{
173
Seek_t* sk;
174
175
sk = (Seek_t*)disc;
176
177
switch (type)
178
{
179
case SF_FINAL:
180
case SF_DPOP:
181
sfclose(sk->shadow);
182
free(disc);
183
break;
184
case SFSK_DISCARD:
185
sk->eof = 0;
186
sk->discard += sk->extent;
187
sk->extent = 0;
188
sfseek(sk->shadow,(Sfoff_t)0,SEEK_SET);
189
break;
190
}
191
return 0;
192
}
193
194
#if __STD_C
195
int sfdcseekable(Sfio_t* f)
196
#else
197
int sfdcseekable(f)
198
Sfio_t* f;
199
#endif
200
{
201
reg Seek_t* sk;
202
203
/* see if already seekable */
204
if(sfseek(f,(Sfoff_t)0,SEEK_CUR) >= 0)
205
return 0;
206
207
if(!(sk = (Seek_t*)malloc(sizeof(Seek_t))) )
208
return -1;
209
memset(sk, 0, sizeof(*sk));
210
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);
216
sk->discard = 0;
217
sk->extent = 0;
218
sk->eof = 0;
219
220
if(sfdisc(f, (Sfdisc_t*)sk) != (Sfdisc_t*)sk)
221
{ sfclose(sk->shadow);
222
free(sk);
223
return -1;
224
}
225
226
return 0;
227
}
228
229