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