1 /*
2  * blob.c
3  *
4  * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
5  *
6  * $Id$
7  */
8 
9 #include "config.h"
10 
11 #include <ctype.h>
12 #include <stdarg.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include "dnet.h"
18 
19 static void	*(*bl_malloc)(size_t) = malloc;
20 static void	*(*bl_realloc)(void *, size_t) = realloc;
21 static void	 (*bl_free)(void *) = free;
22 static int	   bl_size = BUFSIZ;
23 
24 static int	   fmt_D(int, int, blob_t *, va_list *);
25 static int	   fmt_H(int, int, blob_t *, va_list *);
26 static int	   fmt_b(int, int, blob_t *, va_list *);
27 static int	   fmt_c(int, int, blob_t *, va_list *);
28 static int	   fmt_d(int, int, blob_t *, va_list *);
29 static int	   fmt_h(int, int, blob_t *, va_list *);
30 static int	   fmt_s(int, int, blob_t *, va_list *);
31 
32 static void	   print_hexl(blob_t *);
33 
34 static blob_fmt_cb blob_ascii_fmt[] = {
35 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
36 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
37 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
38 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
39 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
40 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
41 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
42 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
43 	NULL,	NULL,	NULL,	NULL,	fmt_D,	NULL,	NULL,	NULL,
44 	fmt_H,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
45 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
46 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
47 	NULL,	NULL,	fmt_b,	fmt_c,	fmt_d,	NULL,	NULL,	NULL,
48 	fmt_h,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
49 	NULL,	NULL,	NULL,	fmt_s,	NULL,	NULL,	NULL,	NULL,
50 	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL
51 };
52 
53 struct blob_printer {
54 	char	  *name;
55 	void	 (*print)(blob_t *);
56 } blob_printers[] = {
57 	{ "hexl",	print_hexl },
58 	{ NULL,		NULL },
59 };
60 
61 blob_t *
blob_new(void)62 blob_new(void)
63 {
64 	blob_t *b;
65 
66 	if ((b = bl_malloc(sizeof(*b))) != NULL) {
67 		b->off = b->end = 0;
68 		b->size = bl_size;
69 		if ((b->base = bl_malloc(b->size)) == NULL) {
70 			bl_free(b);
71 			b = NULL;
72 		}
73 	}
74 	return (b);
75 }
76 
77 static int
blob_reserve(blob_t * b,int len)78 blob_reserve(blob_t *b, int len)
79 {
80 	void *p;
81 	int nsize;
82 
83 	if (b->size < b->end + len) {
84 		if (b->size == 0)
85 			return (-1);
86 
87 		if ((nsize = b->end + len) > bl_size)
88 			nsize = ((nsize / bl_size) + 1) * bl_size;
89 
90 		if ((p = bl_realloc(b->base, nsize)) == NULL)
91 			return (-1);
92 
93 		b->base = p;
94 		b->size = nsize;
95 	}
96 	b->end += len;
97 
98 	return (0);
99 }
100 
101 int
blob_read(blob_t * b,void * buf,int len)102 blob_read(blob_t *b, void *buf, int len)
103 {
104 	if (b->end - b->off < len)
105 		len = b->end - b->off;
106 
107 	memcpy(buf, b->base + b->off, len);
108 	b->off += len;
109 
110 	return (len);
111 }
112 
113 int
blob_write(blob_t * b,const void * buf,int len)114 blob_write(blob_t *b, const void *buf, int len)
115 {
116 	if (b->off + len <= b->end ||
117 	    blob_reserve(b, b->off + len - b->end) == 0) {
118 		memcpy(b->base + b->off, (u_char *)buf, len);
119 		b->off += len;
120 		return (len);
121 	}
122 	return (-1);
123 }
124 
125 int
blob_insert(blob_t * b,const void * buf,int len)126 blob_insert(blob_t *b, const void *buf, int len)
127 {
128 	if (blob_reserve(b, len) == 0 && b->size) {
129 		if (b->end - b->off > 0)
130 			memmove( b->base + b->off + len, b->base + b->off, b->end - b->off);
131 		memcpy(b->base + b->off, buf, len);
132 		b->off += len;
133 		return (len);
134 	}
135 	return (-1);
136 }
137 
138 int
blob_delete(blob_t * b,void * buf,int len)139 blob_delete(blob_t *b, void *buf, int len)
140 {
141 	if (b->off + len <= b->end && b->size) {
142 		if (buf != NULL)
143 			memcpy(buf, b->base + b->off, len);
144 		memmove(b->base + b->off, b->base + b->off + len, b->end - (b->off + len));
145 		b->end -= len;
146 		return (len);
147 	}
148 	return (-1);
149 }
150 
151 static int
blob_fmt(blob_t * b,int pack,const char * fmt,va_list * ap)152 blob_fmt(blob_t *b, int pack, const char *fmt, va_list *ap)
153 {
154 	blob_fmt_cb fmt_cb;
155 	char *p;
156 	int len;
157 
158 	for (p = (char *)fmt; *p != '\0'; p++) {
159 		if (*p == '%') {
160 			p++;
161 			if (isdigit((int) (unsigned char) *p)) {
162 				len = strtol(p, &p, 10);
163 			} else if (*p == '*') {
164 				len = va_arg(*ap, int);
165 				p++;
166 			} else
167 				len = 0;
168 
169 			if ((fmt_cb = blob_ascii_fmt[(int)*p]) == NULL)
170 				return (-1);
171 
172 			if ((*fmt_cb)(pack, len, b, ap) < 0)
173 				return (-1);
174 		} else {
175 			if (pack) {
176 				if (b->off + 1 < b->end ||
177 				    blob_reserve(b, b->off + 1 - b->end) == 0)
178 					b->base[b->off++] = *p;
179 				else
180 					return (-1);
181 			} else {
182 				if (b->base[b->off++] != *p)
183 					return (-1);
184 			}
185 		}
186 	}
187 	return (0);
188 }
189 
190 int
blob_pack(blob_t * b,const char * fmt,...)191 blob_pack(blob_t *b, const char *fmt, ...)
192 {
193 	va_list ap;
194 	va_start(ap, fmt);
195 	return (blob_fmt(b, 1, fmt, &ap));
196 }
197 
198 int
blob_unpack(blob_t * b,const char * fmt,...)199 blob_unpack(blob_t *b, const char *fmt, ...)
200 {
201 	va_list ap;
202 	va_start(ap, fmt);
203 	return (blob_fmt(b, 0, fmt, &ap));
204 }
205 
206 int
blob_seek(blob_t * b,int off,int whence)207 blob_seek(blob_t *b, int off, int whence)
208 {
209 	if (whence == SEEK_CUR)
210 		off += b->off;
211 	else if (whence == SEEK_END)
212 		off += b->end;
213 
214 	if (off < 0 || off > b->end)
215 		return (-1);
216 
217 	return ((b->off = off));
218 }
219 
220 int
blob_index(blob_t * b,const void * buf,int len)221 blob_index(blob_t *b, const void *buf, int len)
222 {
223 	int i;
224 
225 	for (i = b->off; i <= b->end - len; i++) {
226 		if (memcmp(b->base + i, buf, len) == 0)
227 			return (i);
228 	}
229 	return (-1);
230 }
231 
232 int
blob_rindex(blob_t * b,const void * buf,int len)233 blob_rindex(blob_t *b, const void *buf, int len)
234 {
235 	int i;
236 
237 	for (i = b->end - len; i >= 0; i--) {
238 		if (memcmp(b->base + i, buf, len) == 0)
239 			return (i);
240 	}
241 	return (-1);
242 }
243 
244 int
blob_print(blob_t * b,char * style,int len)245 blob_print(blob_t *b, char *style, int len)
246 {
247 	struct blob_printer *bp;
248 
249 	for (bp = blob_printers; bp->name != NULL; bp++) {
250 		if (strcmp(bp->name, style) == 0)
251 			bp->print(b);
252 	}
253 	return (0);
254 }
255 
256 int
blob_sprint(blob_t * b,char * style,int len,char * dst,int size)257 blob_sprint(blob_t *b, char *style, int len, char *dst, int size)
258 {
259 	return (0);
260 }
261 
262 blob_t *
blob_free(blob_t * b)263 blob_free(blob_t *b)
264 {
265 	if (b->size)
266 		bl_free(b->base);
267 	bl_free(b);
268 	return (NULL);
269 }
270 
271 int
blob_register_alloc(size_t size,void * (bmalloc)(size_t),void (* bfree)(void *),void * (* brealloc)(void *,size_t))272 blob_register_alloc(size_t size, void *(bmalloc)(size_t),
273     void (*bfree)(void *), void *(*brealloc)(void *, size_t))
274 {
275 	bl_size = size;
276 	if (bmalloc != NULL)
277 		bl_malloc = bmalloc;
278 	if (bfree != NULL)
279 		bl_free = bfree;
280 	if (brealloc != NULL)
281 		bl_realloc = brealloc;
282 	return (0);
283 }
284 
285 int
blob_register_pack(char c,blob_fmt_cb fmt_cb)286 blob_register_pack(char c, blob_fmt_cb fmt_cb)
287 {
288 	if (blob_ascii_fmt[(int)c] == NULL) {
289 		blob_ascii_fmt[(int)c] = fmt_cb;
290 		return (0);
291 	}
292 	return (-1);
293 }
294 
295 static int
fmt_D(int pack,int len,blob_t * b,va_list * ap)296 fmt_D(int pack, int len, blob_t *b, va_list *ap)
297 {
298 	if (len) return (-1);
299 
300 	if (pack) {
301 		uint32_t n = va_arg(*ap, uint32_t);
302 		n = htonl(n);
303 		if (blob_write(b, &n, sizeof(n)) < 0)
304 			return (-1);
305 	} else {
306 		uint32_t *n = va_arg(*ap, uint32_t *);
307 		if (blob_read(b, n, sizeof(*n)) != sizeof(*n))
308 			return (-1);
309 		*n = ntohl(*n);
310 	}
311 	return (0);
312 }
313 
314 static int
fmt_H(int pack,int len,blob_t * b,va_list * ap)315 fmt_H(int pack, int len, blob_t *b, va_list *ap)
316 {
317 	if (len) return (-1);
318 
319 	if (pack) {
320 		uint16_t n = va_arg(*ap, int);
321 		n = htons(n);
322 		if (blob_write(b, &n, sizeof(n)) < 0)
323 			return (-1);
324 	} else {
325 		uint16_t *n = va_arg(*ap, uint16_t *);
326 		if (blob_read(b, n, sizeof(*n)) != sizeof(*n))
327 			return (-1);
328 		*n = ntohs(*n);
329 	}
330 	return (0);
331 }
332 
333 static int
fmt_b(int pack,int len,blob_t * b,va_list * ap)334 fmt_b(int pack, int len, blob_t *b, va_list *ap)
335 {
336 	void *p = va_arg(*ap, void *);
337 
338 	if (len <= 0) return (-1);
339 
340 	if (pack)
341 		return (blob_write(b, p, len));
342 	else
343 		return (blob_read(b, p, len));
344 }
345 
346 static int
fmt_c(int pack,int len,blob_t * b,va_list * ap)347 fmt_c(int pack, int len, blob_t *b, va_list *ap)
348 {
349 	if (len) return (-1);
350 
351 	if (pack) {
352 		uint8_t n = va_arg(*ap, int);
353 		return (blob_write(b, &n, sizeof(n)));
354 	} else {
355 		uint8_t *n = va_arg(*ap, uint8_t *);
356 		return (blob_read(b, n, sizeof(*n)));
357 	}
358 }
359 
360 static int
fmt_d(int pack,int len,blob_t * b,va_list * ap)361 fmt_d(int pack, int len, blob_t *b, va_list *ap)
362 {
363 	if (len) return (-1);
364 
365 	if (pack) {
366 		uint32_t n = va_arg(*ap, uint32_t);
367 		return (blob_write(b, &n, sizeof(n)));
368 	} else {
369 		uint32_t *n = va_arg(*ap, uint32_t *);
370 		return (blob_read(b, n, sizeof(*n)));
371 	}
372 }
373 
374 static int
fmt_h(int pack,int len,blob_t * b,va_list * ap)375 fmt_h(int pack, int len, blob_t *b, va_list *ap)
376 {
377 	if (len) return (-1);
378 
379 	if (pack) {
380 		uint16_t n = va_arg(*ap, int);
381 		return (blob_write(b, &n, sizeof(n)));
382 	} else {
383 		uint16_t *n = va_arg(*ap, uint16_t *);
384 		return (blob_read(b, n, sizeof(*n)));
385 	}
386 }
387 
388 static int
fmt_s(int pack,int len,blob_t * b,va_list * ap)389 fmt_s(int pack, int len, blob_t *b, va_list *ap)
390 {
391 	char *p = va_arg(*ap, char *);
392 	char c = '\0';
393 	int i, end;
394 
395 	if (pack) {
396 		if (len > 0) {
397 			if ((c = p[len - 1]) != '\0')
398 				p[len - 1] = '\0';
399 		} else
400 			len = strlen(p) + 1;
401 
402 		if (blob_write(b, p, len) > 0) {
403 			if (c != '\0')
404 				p[len - 1] = c;
405 			return (len);
406 		}
407 	} else {
408 		if (len <= 0) return (-1);
409 
410 		if ((end = b->end - b->off) < len)
411 			end = len;
412 
413 		for (i = 0; i < end; i++) {
414 			if ((p[i] = b->base[b->off + i]) == '\0') {
415 				b->off += i + 1;
416 				return (i);
417 			}
418 		}
419 	}
420 	return (-1);
421 }
422 
423 static void
print_hexl(blob_t * b)424 print_hexl(blob_t *b)
425 {
426 	u_int i, j, jm, len;
427 	u_char *p;
428 	int c;
429 
430 	p = b->base + b->off;
431 	len = b->end - b->off;
432 
433 	printf("\n");
434 
435 	for (i = 0; i < len; i += 0x10) {
436 		printf("  %04x: ", (u_int)(i + b->off));
437 		jm = len - i;
438 		jm = jm > 16 ? 16 : jm;
439 
440 		for (j = 0; j < jm; j++) {
441 			printf((j % 2) ? "%02x " : "%02x", (u_int)p[i + j]);
442 		}
443 		for (; j < 16; j++) {
444 			printf((j % 2) ? "   " : "  ");
445 		}
446 		printf(" ");
447 
448 		for (j = 0; j < jm; j++) {
449 			c = p[i + j];
450 			printf("%c", isprint(c) ? c : '.');
451 		}
452 		printf("\n");
453 	}
454 }
455