4 * @brief Pointer/lenght abstraction and its functions.
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
30 #include <printf_hook.h>
31 #include <utils/randomizer.h>
36 chunk_t chunk_empty
= { NULL
, 0 };
39 * Described in header.
41 chunk_t
chunk_create(u_char
*ptr
, size_t len
)
43 chunk_t chunk
= {ptr
, len
};
48 * Described in header.
50 chunk_t
chunk_create_clone(u_char
*ptr
, chunk_t chunk
)
52 chunk_t clone
= chunk_empty
;
54 if (chunk
.ptr
&& chunk
.len
> 0)
57 clone
.len
= chunk
.len
;
58 memcpy(clone
.ptr
, chunk
.ptr
, chunk
.len
);
67 size_t chunk_length(const char* mode
, ...)
72 va_start(chunks
, mode
);
80 chunk_t ch
= va_arg(chunks
, chunk_t
);
96 chunk_t
chunk_create_cat(u_char
*ptr
, const char* mode
, ...)
99 chunk_t construct
= chunk_create(ptr
, 0);
101 va_start(chunks
, mode
);
104 bool free_chunk
= FALSE
;
113 chunk_t ch
= va_arg(chunks
, chunk_t
);
114 memcpy(ptr
, ch
.ptr
, ch
.len
);
116 construct
.len
+= ch
.len
;
134 * Decribed in header.
136 void chunk_split(chunk_t chunk
, const char *mode
, ...)
142 va_start(chunks
, mode
);
149 len
= va_arg(chunks
, size_t);
150 ch
= va_arg(chunks
, chunk_t
*);
151 /* a null chunk means skip len bytes */
154 chunk
= chunk_skip(chunk
, len
);
161 ch
->len
= min(chunk
.len
, len
);
170 chunk
= chunk_skip(chunk
, ch
->len
);
175 ch
->len
= min(chunk
.len
, len
);
178 ch
->ptr
= malloc(ch
->len
);
179 memcpy(ch
->ptr
, chunk
.ptr
, ch
->len
);
185 chunk
= chunk_skip(chunk
, ch
->len
);
190 ch
->len
= min(ch
->len
, chunk
.len
);
191 ch
->len
= min(ch
->len
, len
);
194 memcpy(ch
->ptr
, chunk
.ptr
, ch
->len
);
200 chunk
= chunk_skip(chunk
, ch
->len
);
212 * Described in header.
214 bool chunk_write(chunk_t chunk
, const char *path
, const char *label
, mode_t mask
, bool force
)
221 fd
= fopen(path
, "r");
225 DBG1(" %s file '%s' already exists", label
, path
);
231 oldmask
= umask(mask
);
233 fd
= fopen(path
, "w");
237 fwrite(chunk
.ptr
, sizeof(u_char
), chunk
.len
, fd
);
239 DBG1(" written %s file '%s' (%u bytes)", label
, path
, chunk
.len
);
245 DBG1(" could not open %s file '%s' for writing", label
, path
);
251 /** hex conversion digits */
252 static char hexdig_upper
[] = "0123456789ABCDEF";
253 static char hexdig_lower
[] = "0123456789abcdef";
256 * Described in header.
258 char *chunk_to_hex(chunk_t chunk
, bool uppercase
)
262 char *hexdig
= hexdig_lower
;
266 hexdig
= hexdig_upper
;
269 str
= malloc(chunk
.len
* 2 + 1);
270 str
[chunk
.len
* 2] = '\0';
272 for (i
= 0; i
< chunk
.len
; i
++)
274 str
[i
*2] = hexdig
[(chunk
.ptr
[i
] >> 4) & 0xF];
275 str
[i
*2+1] = hexdig
[(chunk
.ptr
[i
] ) & 0xF];
281 * Described in header.
283 void chunk_free(chunk_t
*chunk
)
291 * Described in header.
293 void chunk_free_randomized(chunk_t
*chunk
)
299 randomizer_t
*randomizer
= randomizer_create();
301 randomizer
->get_pseudo_random_bytes(randomizer
,
302 chunk
->len
, chunk
->ptr
);
303 randomizer
->destroy(randomizer
);
312 * Described in header.
314 chunk_t
chunk_skip(chunk_t chunk
, size_t bytes
)
316 if (chunk
.len
> bytes
)
326 * Described in header.
328 int chunk_compare(chunk_t a
, chunk_t b
)
330 int compare_len
= a
.len
- b
.len
;
331 int len
= (compare_len
< 0)? a
.len
: b
.len
;
333 if (compare_len
!= 0 || len
== 0)
337 return memcmp(a
.ptr
, b
.ptr
, len
);
341 * Described in header.
343 bool chunk_equals(chunk_t a
, chunk_t b
)
345 return a
.ptr
!= NULL
&& b
.ptr
!= NULL
&&
346 a
.len
== b
.len
&& memeq(a
.ptr
, b
.ptr
, a
.len
);
350 * Described in header.
352 bool chunk_equals_or_null(chunk_t a
, chunk_t b
)
354 if (a
.ptr
== NULL
|| b
.ptr
== NULL
)
356 return a
.len
== b
.len
&& memeq(a
.ptr
, b
.ptr
, a
.len
);
360 * Number of bytes per line to dump raw data
362 #define BYTES_PER_LINE 16
365 * output handler in printf() for byte ranges
367 static int print_bytes(FILE *stream
, const struct printf_info
*info
,
368 const void *const *args
)
370 char *bytes
= *((void**)(args
[0]));
371 int len
= *((size_t*)(args
[1]));
373 char buffer
[BYTES_PER_LINE
* 3];
374 char ascii_buffer
[BYTES_PER_LINE
+ 1];
375 char *buffer_pos
= buffer
;
376 char *bytes_pos
= bytes
;
377 char *bytes_roof
= bytes
+ len
;
382 written
+= fprintf(stream
, "=> %d bytes @ %p", len
, bytes
);
384 while (bytes_pos
< bytes_roof
)
386 *buffer_pos
++ = hexdig_upper
[(*bytes_pos
>> 4) & 0xF];
387 *buffer_pos
++ = hexdig_upper
[ *bytes_pos
& 0xF];
390 (*bytes_pos
> 31 && *bytes_pos
< 127) ?
*bytes_pos
: '.';
392 if (++bytes_pos
== bytes_roof
|| i
== BYTES_PER_LINE
)
394 int padding
= 3 * (BYTES_PER_LINE
- i
);
401 *buffer_pos
++ = '\0';
402 ascii_buffer
[i
] = '\0';
404 written
+= fprintf(stream
, "\n%4d: %s %s",
405 line_start
, buffer
, ascii_buffer
);
409 line_start
+= BYTES_PER_LINE
;
421 * output handler in printf() for chunks
423 static int print_chunk(FILE *stream
, const struct printf_info
*info
,
424 const void *const *args
)
426 chunk_t
*chunk
= *((chunk_t
**)(args
[0]));
428 chunk_t copy
= *chunk
;
433 const void *new_args
[] = {&chunk
->ptr
, &chunk
->len
};
434 return print_bytes(stream
, info
, new_args
);
445 written
+= fprintf(stream
, ":");
447 written
+= fprintf(stream
, "%02x", *copy
.ptr
++);
454 * register printf() handlers
456 static void __attribute__ ((constructor
))print_register()
458 register_printf_function(PRINTF_CHUNK
, print_chunk
, arginfo_ptr
);
459 register_printf_function(PRINTF_BYTES
, print_bytes
, arginfo_ptr_int
);