1 /* ------------------------------------------------------------------------ */
2 /* LHa for UNIX    															*/
3 /*				crcio.c -- crc input / output								*/
4 /*																			*/
5 /*		Modified          		Nobutaka Watazaki							*/
6 /*																			*/
7 /*	Ver. 1.14 	Source All chagned				1995.01.14	N.Watazaki		*/
8 /* ------------------------------------------------------------------------ */
9 #include "lha.h"
10 
11 /* ------------------------------------------------------------------------ */
12 static unsigned short crctable[UCHAR_MAX + 1];
13 static unsigned char subbitbuf, bitcount;
14 #ifdef EUC
15 static int      putc_euc_cache;
16 #endif
17 static int      getc_euc_cache;
18 
19 /* ------------------------------------------------------------------------ */
20 void
make_crctable()21 make_crctable( /* void */ )
22 {
23 	unsigned int    i, j, r;
24 
25 	for (i = 0; i <= UCHAR_MAX; i++) {
26 		r = i;
27 		for (j = 0; j < CHAR_BIT; j++)
28 			if (r & 1)
29 				r = (r >> 1) ^ CRCPOLY;
30 			else
31 				r >>= 1;
32 		crctable[i] = r;
33 	}
34 }
35 
36 /* ------------------------------------------------------------------------ */
37 #ifdef NEED_INCREMENTAL_INDICATOR
38 static void
put_indicator(count)39 put_indicator(count)
40 	long int        count;
41 {
42 	if (!quiet && indicator_threshold) {
43 		while (count > indicator_count) {
44 			putchar('o');
45 			fflush(stdout);
46 			indicator_count += indicator_threshold;
47 		}
48 	}
49 }
50 #endif
51 
52 /* ------------------------------------------------------------------------ */
53 unsigned short
calccrc(p,n)54 calccrc(p, n)
55 	unsigned char  *p;
56 	unsigned int    n;
57 {
58 	reading_size += n;
59 #ifdef NEED_INCREMENTAL_INDICATOR
60 	put_indicator(reading_size);
61 #endif
62 	while (n-- > 0)
63 		UPDATE_CRC(*p++);
64 	return crc;
65 }
66 
67 /* ------------------------------------------------------------------------ */
68 void
fillbuf(unsigned char n)69 fillbuf(unsigned char n) /* Shift bitbuf n bits left, read n bits */
70 {
71 	while (n > bitcount) {
72 		n -= bitcount;
73 		bitbuf = (bitbuf << bitcount) + (subbitbuf >> (CHAR_BIT - bitcount));
74 		if (compsize != 0) {
75 			compsize--;
76 			subbitbuf = (unsigned char) getc(infile);
77 		}
78 		else
79 			subbitbuf = 0;
80 		bitcount = CHAR_BIT;
81 	}
82 	bitcount -= n;
83 	bitbuf = (bitbuf << n) + (subbitbuf >> (CHAR_BIT - n));
84 	subbitbuf <<= n;
85 }
86 
87 /* ------------------------------------------------------------------------ */
88 unsigned short
getbits(unsigned char n)89 getbits(unsigned char n)
90 {
91 	unsigned short  x;
92 
93 	x = bitbuf >> (2 * CHAR_BIT - n);
94 	fillbuf(n);
95 	return x;
96 }
97 
98 /* ------------------------------------------------------------------------ */
99 void
putcode(unsigned char n,unsigned short x)100 putcode(unsigned char n, unsigned short x) /* Write rightmost n bits of x */
101 {
102 	while (n >= bitcount) {
103 		n -= bitcount;
104 		subbitbuf += x >> (USHRT_BIT - bitcount);
105 		x <<= bitcount;
106 		if (compsize < origsize) {
107 			if (fwrite(&subbitbuf, 1, 1, outfile) == 0) {
108 				/* fileerror(WTERR, outfile); */
109 			    fatal_error("Write error in crcio.c(putcode)\n");
110 				/* exit(errno); */
111 			}
112 			compsize++;
113 		}
114 		else
115 			unpackable = 1;
116 		subbitbuf = 0;
117 		bitcount = CHAR_BIT;
118 	}
119 	subbitbuf += x >> (USHRT_BIT - bitcount);
120 	bitcount -= n;
121 }
122 
123 /* ------------------------------------------------------------------------ */
124 void
putbits(unsigned char n,unsigned short x)125 putbits(unsigned char n, unsigned short x) /* Write rightmost n bits of x */
126 {
127 	x <<= USHRT_BIT - n;
128 	while (n >= bitcount) {
129 		n -= bitcount;
130 		subbitbuf += x >> (USHRT_BIT - bitcount);
131 		x <<= bitcount;
132 		if (compsize < origsize) {
133 			if (fwrite(&subbitbuf, 1, 1, outfile) == 0) {
134 				/* fileerror(WTERR, outfile); */
135 			    fatal_error("Write error in crcio.c(putbits)\n");
136 				/* exit(errno); */
137 			}
138 			compsize++;
139 		}
140 		else
141 			unpackable = 1;
142 		subbitbuf = 0;
143 		bitcount = CHAR_BIT;
144 	}
145 	subbitbuf += x >> (USHRT_BIT - bitcount);
146 	bitcount -= n;
147 }
148 
149 /* ------------------------------------------------------------------------ */
150 int
fread_crc(p,n,fp)151 fread_crc(p, n, fp)
152 	unsigned char  *p;
153 	int             n;
154 	FILE           *fp;
155 {
156 	if (text_mode)
157 		n = fread_txt(p, n, fp);
158 	else
159 		n = fread(p, 1, n, fp);
160 
161 	calccrc(p, n);
162 	return n;
163 }
164 
165 /* ------------------------------------------------------------------------ */
166 void
fwrite_crc(p,n,fp)167 fwrite_crc(p, n, fp)
168 	unsigned char  *p;
169 	int             n;
170 	FILE           *fp;
171 {
172 	calccrc(p, n);
173 	if (verify_mode)
174 		return;
175 
176 	if (fp) {
177 		if (text_mode) {
178 			if (fwrite_txt(p, n, fp))
179 				fatal_error("File write error\n");
180 		}
181 		else {
182 			if (fwrite(p, 1, n, fp) < n)
183 				fatal_error("File write error\n");
184 		}
185 	}
186 }
187 
188 /* ------------------------------------------------------------------------ */
189 void
init_code_cache()190 init_code_cache( /* void */ )
191 {				/* called from copyfile() in util.c */
192 #ifdef EUC
193 	putc_euc_cache = EOF;
194 #endif
195 	getc_euc_cache = EOF;
196 }
197 
198 void
init_getbits()199 init_getbits( /* void */ )
200 {
201 	bitbuf = 0;
202 	subbitbuf = 0;
203 	bitcount = 0;
204 	fillbuf(2 * CHAR_BIT);
205 #ifdef EUC
206 	putc_euc_cache = EOF;
207 #endif
208 }
209 
210 /* ------------------------------------------------------------------------ */
211 void
init_putbits()212 init_putbits( /* void */ )
213 {
214 	bitcount = CHAR_BIT;
215 	subbitbuf = 0;
216 	getc_euc_cache = EOF;
217 }
218 
219 /* ------------------------------------------------------------------------ */
220 #ifdef EUC
221 void
putc_euc(c,fd)222 putc_euc(c, fd)
223 	int             c;
224 	FILE           *fd;
225 {
226 	int             d;
227 
228 	if (putc_euc_cache == EOF) {
229 		if (!euc_mode || c < 0x81 || c > 0xFC) {
230 			putc(c, fd);
231 			return;
232 		}
233 		if (c >= 0xA0 && c < 0xE0) {
234 			putc(0x8E, fd);	/* single shift */
235 			putc(c, fd);
236 			return;
237 		}
238 		putc_euc_cache = c;	/* save first byte */
239 		return;
240 	}
241 	d = putc_euc_cache;
242 	putc_euc_cache = EOF;
243 	if (d >= 0xA0)
244 		d -= 0xE0 - 0xA0;
245 	if (c > 0x9E) {
246 		c = c - 0x9F + 0x21;
247 		d = (d - 0x81) * 2 + 0x22;
248 	}
249 	else {
250 		if (c > 0x7E)
251 			c--;
252 		c -= 0x1F;
253 		d = (d - 0x81) * 2 + 0x21;
254 	}
255 	putc(0x80 | d, fd);
256 	putc(0x80 | c, fd);
257 }
258 #endif
259 
260 /* ------------------------------------------------------------------------ */
261 int
fwrite_txt(p,n,fp)262 fwrite_txt(p, n, fp)
263 	unsigned char  *p;
264 	int             n;
265 	FILE           *fp;
266 {
267 	while (--n >= 0) {
268 		if (*p != '\015' && *p != '\032') {
269 #ifdef EUC
270 			putc_euc(*p, fp);
271 #else
272 			putc(*p, fp);
273 #endif
274 		}
275 
276 		prev_char = *p++;
277 	}
278 	return (ferror(fp));
279 }
280 
281 /* ------------------------------------------------------------------------ */
282 int
fread_txt(p,n,fp)283 fread_txt(p, n, fp)
284 	unsigned char  *p;
285 	int             n;
286 	FILE           *fp;
287 {
288 	int             c;
289 	int             cnt = 0;
290 
291 	while (cnt < n) {
292 		if (getc_euc_cache != EOF) {
293 			c = getc_euc_cache;
294 			getc_euc_cache = EOF;
295 		}
296 		else {
297 			if ((c = fgetc(fp)) == EOF)
298 				break;
299 			if (c == '\n') {
300 				getc_euc_cache = c;
301 				++origsize;
302 				c = '\r';
303 			}
304 #ifdef EUC
305 			else if (euc_mode && (c == 0x8E || (0xA0 < c && c < 0xFF))) {
306 				int             d = fgetc(fp);
307 				if (d == EOF) {
308 					*p++ = c;
309 					cnt++;
310 					break;
311 				}
312 				if (c == 0x8E) {	/* single shift (KANA) */
313 					if ((0x20 < d && d < 0x7F) || (0xA0 < d && d < 0xFF))
314 						c = d | 0x80;
315 					else
316 						getc_euc_cache = d;
317 				}
318 				else {
319 					if (0xA0 < d && d < 0xFF) {	/* if GR */
320 						c &= 0x7F;	/* convert to MS-kanji */
321 						d &= 0x7F;
322 						if (!(c & 1)) {
323 							c--;
324 							d += 0x7F - 0x21;
325 						}
326 						if ((d += 0x40 - 0x21) > 0x7E)
327 							d++;
328 						if ((c = (c >> 1) + 0x71) >= 0xA0)
329 							c += 0xE0 - 0xA0;
330 					}
331 					getc_euc_cache = d;
332 				}
333 			}
334 #endif
335 		}
336 		*p++ = c;
337 		cnt++;
338 	}
339 	return cnt;
340 }
341 
342 /* ------------------------------------------------------------------------ */
343 unsigned short
calc_header_crc(p,n)344 calc_header_crc(p, n)		/* Thanks T.Okamoto */
345 	unsigned char  *p;
346 	unsigned int    n;
347 {
348 	crc = 0;
349 	while (n-- > 0)
350 		UPDATE_CRC(*p++);
351 	return crc;
352 }
353