1 /***********************************************************************
2 * *
3 * This software is part of the zlib package *
4 * Copyright (c) 1996-2003 Jean-loup Gailly and Mark Adler *
5 * *
6 * This software is provided 'as-is', without any express or implied *
7 * warranty. In no event will the authors be held liable for any *
8 * damages arising from the use of this software. *
9 * *
10 * Permission is granted to anyone to use this software for any *
11 * purpose, including commercial applications, and to alter it and *
12 * redistribute it freely, subject to the following restrictions: *
13 * *
14 * 1. The origin of this software must not be misrepresented; *
15 * you must not claim that you wrote the original software. If *
16 * you use this software in a product, an acknowledgment in the *
17 * product documentation would be appreciated but is not *
18 * required. *
19 * *
20 * 2. Altered source versions must be plainly marked as such, *
21 * and must not be misrepresented as being the original *
22 * software. *
23 * *
24 * 3. This notice may not be removed or altered from any source *
25 * distribution. *
26 * *
27 * This software is provided "as-is", without any express or implied *
28 * warranty. In no event will the authors be held liable for any damages*
29 * arising from the use of this software. *
30 * *
31 * Permission is granted to anyone to use this software for any purpose,*
32 * including commercial applications, and to alter it and redistribute i*
33 * freely, subject to the following restrictions: *
34 * *
35 * 1. The origin of this software must not be misrepresented; you must n*
36 * claim that you wrote the original software. If you use this softwa*
37 * in a product, an acknowledgment in the product documentation would*
38 * be appreciated but is not required. *
39 * *
40 * 2. Altered source versions must be plainly marked as such, and must n*
41 * be misrepresented as being the original software. *
42 * *
43 * 3. This notice may not be removed or altered from any source *
44 * distribution. *
45 * *
46 * Julian R Seward *
47 * *
48 ***********************************************************************/
49 #pragma prototyped
50
51 /*
52 * sfio bzip discipline
53 */
54
55 #include <sfio_t.h>
56 #include <ast.h>
57 #include <bzlib.h>
58 #include <sfdcbzip.h>
59
60 #define bzsync(p,o) (-1)
61
62 typedef struct
63 {
64 Sfdisc_t disc; /* sfio discipline */
65 Bz_t* bz; /* bz handle */
66 } Sfbzip_t;
67
68 /*
69 * bzip exception handler
70 * free on close
71 */
72
73 static int
sfbzexcept(Sfio_t * sp,int op,void * val,Sfdisc_t * dp)74 sfbzexcept(Sfio_t* sp, int op, void* val, Sfdisc_t* dp)
75 {
76 register Sfbzip_t* bz = (Sfbzip_t*)dp;
77 int r;
78
79 NoP(sp);
80 #if 1
81 {
82 static char aha[] = "AHA sfdcbzip event 0\n";
83 static int init;
84
85 if (!init)
86 init = getenv("SFBZ_DEBUG") ? 1 : -1;
87 if (init > 0)
88 {
89 aha[sizeof(aha) - 3] = '0' + op;
90 write(2, aha, sizeof(aha) - 1);
91 }
92 }
93 #endif
94 switch (op)
95 {
96 case SF_ATEXIT:
97 sfdisc(sp, SF_POPDISC);
98 return 0;
99 case SF_CLOSING:
100 case SF_DPOP:
101 case SF_FINAL:
102 if (bz->bz)
103 {
104 r = bzclose(bz->bz) ? -1 : 0;
105 bz->bz = 0;
106 }
107 else
108 r = 0;
109 if (op != SF_CLOSING)
110 free(dp);
111 return r;
112 case SF_DBUFFER:
113 return 1;
114 case SF_READ:
115 case SF_WRITE:
116 return *((ssize_t*)val) < 0 ? -1 : 0;
117 case SF_SYNC:
118 return val ? 0 : bzflush(bz->bz);
119 case SFBZ_HANDLE:
120 return (*((Bz_t**)val) = bz->bz) ? 1 : -1;
121 case SFBZ_GETPOS:
122 return (*((Sfoff_t*)val) = bzsync(bz->bz, (z_off_t)(-1))) == -1 ? -1 : 0;
123 case SFBZ_SETPOS:
124 return bzsync(bz->bz, (z_off_t)(*((Sfoff_t*)val))) == -1 ? -1 : 0;
125 }
126 return 0;
127 }
128
129 /*
130 * sfio bzip discipline read
131 */
132
133 static ssize_t
sfbzread(Sfio_t * fp,Void_t * buf,size_t size,Sfdisc_t * dp)134 sfbzread(Sfio_t* fp, Void_t* buf, size_t size, Sfdisc_t* dp)
135 {
136 register Sfbzip_t* bz = (Sfbzip_t*)dp;
137
138 return bzread(bz->bz, buf, size);
139 }
140
141 /*
142 * sfio bzip discipline write
143 */
144
145 static ssize_t
sfbzwrite(Sfio_t * fp,const Void_t * buf,size_t size,Sfdisc_t * dp)146 sfbzwrite(Sfio_t* fp, const Void_t* buf, size_t size, Sfdisc_t* dp)
147 {
148 register Sfbzip_t* bz = (Sfbzip_t*)dp;
149
150 return (bzwrite(bz->bz, (void*)buf, size) < 0) ? -1 : size;
151 }
152
153 /*
154 * create and push the sfio bzip discipline
155 *
156 * (flags&SFBZ_VERIFY) return
157 * >0 is a bzip file
158 * 0 not a bzip file
159 * <0 error
160 * otherwise return
161 * >0 discipline pushed
162 * 0 discipline not needed
163 * <0 error
164 */
165
166 int
sfdcbzip(Sfio_t * sp,int flags)167 sfdcbzip(Sfio_t* sp, int flags)
168 {
169 char* m;
170 Sfbzip_t* bz;
171 char mode[10];
172
173 if (sfset(sp, 0, 0) & SF_READ)
174 {
175 register unsigned char* s;
176 register int n;
177
178 /*
179 * peek the first 4 bytes to verify the magic
180 *
181 * BZh[0-9] sfdcbzip bzip
182 */
183
184 if (!(n = sfset(sp, 0, 0) & SF_SHARE))
185 sfset(sp, SF_SHARE, 1);
186 s = (unsigned char*)sfreserve(sp, 4, 1);
187 if (!n)
188 sfset(sp, SF_SHARE, 0);
189 if (!s)
190 return -1;
191 n = s[0] == 'B' && s[1] == 'Z' && s[2] == 'h' && (s[3] >= '0' && s[3] <= '9');
192 sfread(sp, s, 0);
193 if (!n || (flags & SFBZ_VERIFY))
194 return n;
195 }
196 else if (flags & SFBZ_VERIFY)
197 return -1;
198 if (!(bz = newof(0, Sfbzip_t, 1, 0)))
199 return -1;
200 bz->disc.exceptf = sfbzexcept;
201 if (sfset(sp, 0, 0) & SF_READ)
202 bz->disc.readf = sfbzread;
203 else
204 bz->disc.writef = sfbzwrite;
205 m = mode;
206 *m++ = (sfset(sp, 0, 0) & SF_READ) ? 'r' : 'w';
207 *m++ = 'o';
208 if ((flags &= 0xf) > 0 && flags <= 9)
209 *m++ = '0' + flags;
210 *m = 0;
211 if (sfdisc(sp, &bz->disc) != &bz->disc || !(bz->bz = bzdopen(sffileno(sp), mode)))
212 {
213 free(bz);
214 return -1;
215 }
216 sfsetbuf(sp, NiL, SF_BUFSIZE);
217 if (!(sfset(sp, 0, 0) & SF_READ))
218 sfset(sp, SF_IOCHECK, 1);
219 return 1;
220 }
221