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