1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1996-2011 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*                                                                      *
19***********************************************************************/
20#pragma prototyped
21/*
22 * Glenn Fowler
23 * AT&T Research
24 *
25 * man this is sum library
26 */
27
28static const char id[] = "\n@(#)$Id: sumlib (AT&T Research) 2009-09-28 $\0\n";
29
30#define _SUM_PRIVATE_	\
31			struct Method_s*	method;	\
32			uintmax_t		total_count;	\
33			uintmax_t		total_size;	\
34			uintmax_t		size;
35
36#include <sum.h>
37#include <ctype.h>
38#include <swap.h>
39#include <hashpart.h>
40
41#define SCALE(n,m)	(((n)+(m)-1)/(m))
42
43typedef struct Method_s
44{
45	const char*	match;
46	const char*	description;
47	const char*	options;
48	Sum_t*		(*open)(const struct Method_s*, const char*);
49	int		(*init)(Sum_t*);
50	int		(*block)(Sum_t*, const void*, size_t);
51	int		(*data)(Sum_t*, Sumdata_t*);
52	int		(*print)(Sum_t*, Sfio_t*, int, size_t);
53	int		(*done)(Sum_t*);
54	int		scale;
55} Method_t;
56
57typedef struct Map_s
58{
59	const char*	match;
60	const char*	description;
61	const char*	map;
62} Map_t;
63
64/*
65 * 16 and 32 bit common code
66 */
67
68#define _INTEGRAL_PRIVATE_ \
69	uint32_t	sum; \
70	uint32_t	total_sum;
71
72typedef struct Integral_s
73{
74	_SUM_PUBLIC_
75	_SUM_PRIVATE_
76	_INTEGRAL_PRIVATE_
77} Integral_t;
78
79static Sum_t*
80long_open(const Method_t* method, const char* name)
81{
82	Integral_t*	p;
83
84	if (p = newof(0, Integral_t, 1, 0))
85	{
86		p->method = (Method_t*)method;
87		p->name = name;
88	}
89	return (Sum_t*)p;
90}
91
92static int
93long_init(Sum_t* p)
94{
95	((Integral_t*)p)->sum = 0;
96	return 0;
97}
98
99static int
100long_done(Sum_t* p)
101{
102	register Integral_t*	x = (Integral_t*)p;
103
104	x->total_sum ^= (x->sum &= 0xffffffff);
105	return 0;
106}
107
108static int
109short_done(Sum_t* p)
110{
111	register Integral_t*	x = (Integral_t*)p;
112
113	x->total_sum ^= (x->sum &= 0xffff);
114	return 0;
115}
116
117static int
118long_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
119{
120	register Integral_t*	x = (Integral_t*)p;
121	register uint32_t	c;
122	register uintmax_t	z;
123	register size_t		n;
124
125	c = (flags & SUM_TOTAL) ? x->total_sum : x->sum;
126	sfprintf(sp, "%.*I*u", (flags & SUM_LEGACY) ? 5 : 1, sizeof(c), c);
127	if (flags & SUM_SIZE)
128	{
129		z = (flags & SUM_TOTAL) ? x->total_size : x->size;
130		if ((flags & SUM_SCALE) && ((n = scale) || (n = x->method->scale)))
131			z = SCALE(z, n);
132		sfprintf(sp, " %*I*u", (flags & SUM_LEGACY) ? 6 : 0, sizeof(z), z);
133	}
134	if (flags & SUM_TOTAL)
135		sfprintf(sp, " %*I*u", (flags & SUM_LEGACY) ? 6 : 0, sizeof(x->total_count), x->total_count);
136	return 0;
137}
138
139static int
140long_data(Sum_t* p, Sumdata_t* data)
141{
142	register Integral_t*	x = (Integral_t*)p;
143
144	data->size = sizeof(data->num);
145	data->num = x->sum;
146	data->buf = 0;
147	return 0;
148}
149
150#include "FEATURE/sum"
151
152#include "sum-att.c"
153#include "sum-ast4.c"
154#include "sum-bsd.c"
155#include "sum-crc.c"
156#include "sum-prng.c"
157
158#if _LIB_md && _lib_MD5Init && _hdr_md5 && _lib_SHA2Init && _hdr_sha2
159
160#include "sum-lmd.c"
161
162#else
163
164#include "sum-md5.c"
165#include "sum-sha1.c"
166#include "sum-sha2.c"
167
168#endif
169
170/*
171 * now the library interface
172 */
173
174#undef	METHOD		/* solaris <sys/localedef.h>! */
175#define METHOD(x)	x##_match,x##_description,x##_options,x##_open,x##_init,x##_block,x##_data,x##_print,x##_done,x##_scale
176
177static const Method_t	methods[] =
178{
179	METHOD(att),
180	METHOD(ast4),
181	METHOD(bsd),
182	METHOD(crc),
183	METHOD(prng),
184#ifdef md4_description
185	METHOD(md4),
186#endif
187#ifdef md5_description
188	METHOD(md5),
189#endif
190#ifdef sha1_description
191	METHOD(sha1),
192#endif
193#ifdef sha256_description
194	METHOD(sha256),
195#endif
196#ifdef sha384_description
197	METHOD(sha384),
198#endif
199#ifdef sha512_description
200	METHOD(sha512),
201#endif
202};
203
204static const Map_t	maps[] =
205{
206	{
207		"posix|cksum|std|standard",
208		"The posix 1003.2-1992 32 bit crc checksum. This is the"
209		" default \bcksum\b(1)  method.",
210		"crc-0x04c11db7-rotate-done-size"
211	},
212	{
213		"zip",
214		"The \bzip\b(1) crc.",
215		"crc-0xedb88320-init-done"
216	},
217	{
218		"fddi",
219		"The FDDI crc.",
220		"crc-0xedb88320-size=0xcc55cc55"
221	},
222	{
223		"fnv|fnv1",
224		"The Fowler-Noll-Vo 32 bit PRNG hash with non-zero"
225		" initializer (FNV-1).",
226		"prng-0x01000193-init=0x811c9dc5"
227	},
228	{
229		"ast|strsum",
230		"The \bast\b \bstrsum\b(3) PRNG hash.",
231		"prng-0x63c63cd9-add=0x9c39c33d"
232	},
233};
234
235/*
236 * simple alternation prefix match
237 */
238
239static int
240match(register const char* s, register const char* p)
241{
242	register const char*	b = s;
243
244	for (;;)
245	{
246		do
247		{
248			if (*p == '|' || *p == 0)
249				return 1;
250		} while (*s++ == *p++);
251		for (;;)
252		{
253			switch (*p++)
254			{
255			case 0:
256				return 0;
257			case '|':
258				break;
259			default:
260				continue;
261			}
262			break;
263		}
264		s = b;
265	}
266	return 0;
267}
268
269/*
270 * open sum method name
271 */
272
273Sum_t*
274sumopen(register const char* name)
275{
276	register int	n;
277
278	if (!name || !name[0] || name[0] == '-' && !name[1])
279		name = "default";
280	for (n = 0; n < elementsof(maps); n++)
281		if (match(name, maps[n].match))
282		{
283			name = maps[n].map;
284			break;
285		}
286	for (n = 0; n < elementsof(methods); n++)
287		if (match(name, methods[n].match))
288			return (*methods[n].open)(&methods[n], name);
289	return 0;
290}
291
292/*
293 * initialize for a new run of blocks
294 */
295
296int
297suminit(Sum_t* p)
298{
299	p->size = 0;
300	return (*p->method->init)(p);
301}
302
303/*
304 * compute the running sum on buf
305 */
306
307int
308sumblock(Sum_t* p, const void* buf, size_t siz)
309{
310	p->size += siz;
311	return (*p->method->block)(p, buf, siz);
312}
313
314/*
315 * done with this run of blocks
316 */
317
318int
319sumdone(Sum_t* p)
320{
321	p->total_count++;
322	p->total_size += p->size;
323	return (*p->method->done)(p);
324}
325
326/*
327 * print the sum [size] on sp
328 */
329
330int
331sumprint(Sum_t* p, Sfio_t* sp, int flags, size_t scale)
332{
333	return (*p->method->print)(p, sp, flags, scale);
334}
335
336/*
337 * return the current sum (internal) data
338 */
339
340int
341sumdata(Sum_t* p, Sumdata_t* d)
342{
343	return (*p->method->data)(p, d);
344}
345
346/*
347 * close an open sum handle
348 */
349
350int
351sumclose(Sum_t* p)
352{
353	free(p);
354	return 0;
355}
356
357/*
358 * print the checksum method optget(3) usage on sp and return the length
359 */
360
361int
362sumusage(Sfio_t* sp)
363{
364	register int	i;
365	register int	n;
366
367	for (i = n = 0; i < elementsof(methods); i++)
368	{
369		n += sfprintf(sp, "[+%s?%s]", methods[i].match, methods[i].description);
370		if (methods[i].options)
371			n += sfprintf(sp, "{\n%s\n}", methods[i].options);
372	}
373	for (i = 0; i < elementsof(maps); i++)
374		n += sfprintf(sp, "[+%s?%s Shorthand for \b%s\b.]", maps[i].match, maps[i].description, maps[i].map);
375	return n;
376}
377