8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / lib / libast / common / disc / sfdcseekable.c
blob9c9c6489c686dbb222f3eae9d255014e182aaa20
1 /***********************************************************************
2 * *
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 *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #include "sfdchdr.h"
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 */
38 } Seek_t;
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
50 return (ssize_t)(-1);
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
63 Seek_t* sk;
64 Sfio_t* sf;
65 Sfoff_t addr;
66 ssize_t r, w, p;
68 sk = (Seek_t*)disc;
69 sf = sk->shadow;
70 if(sk->eof)
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)
80 return w;
81 buf = (char*)buf + r;
82 n -= r;
85 /* do a raw read */
86 if((w = sfrd(f,buf,n,disc)) <= 0)
87 { sk->eof = 1;
88 w = 0;
90 else
92 if((p = sfwrite(sf,buf,w)) != w)
93 sk->eof = 1;
94 if(p > 0)
95 sk->extent += p;
98 return r+w;
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
111 Seek_t* sk;
112 Sfio_t* sf;
113 char buf[SF_BUFSIZE];
114 ssize_t r, w;
116 sk = (Seek_t*)disc;
117 sf = sk->shadow;
119 switch (type)
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;
134 if(addr < 0)
135 return (Sfoff_t)(-1);
136 else if(addr > sk->extent)
137 { if(sk->eof)
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) )
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;
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 */
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
173 Seek_t* sk;
175 sk = (Seek_t*)disc;
177 switch (type)
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;
191 return 0;
194 #if __STD_C
195 int sfdcseekable(Sfio_t* f)
196 #else
197 int sfdcseekable(f)
198 Sfio_t* f;
199 #endif
201 reg Seek_t* sk;
203 /* see if already seekable */
204 if(sfseek(f,(Sfoff_t)0,SEEK_CUR) >= 0)
205 return 0;
207 if(!(sk = (Seek_t*)malloc(sizeof(Seek_t))) )
208 return -1;
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);
216 sk->discard = 0;
217 sk->extent = 0;
218 sk->eof = 0;
220 if(sfdisc(f, (Sfdisc_t*)sk) != (Sfdisc_t*)sk)
221 { sfclose(sk->shadow);
222 free(sk);
223 return -1;
226 return 0;