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>
35 chunk_t chunk_empty
= { NULL
, 0 };
38 * Described in header.
40 chunk_t
chunk_create(u_char
*ptr
, size_t len
)
42 chunk_t chunk
= {ptr
, len
};
47 * Described in header.
49 chunk_t
chunk_create_clone(u_char
*ptr
, chunk_t chunk
)
51 chunk_t clone
= chunk_empty
;
53 if (chunk
.ptr
&& chunk
.len
> 0)
56 clone
.len
= chunk
.len
;
57 memcpy(clone
.ptr
, chunk
.ptr
, chunk
.len
);
66 size_t chunk_length(const char* mode
, ...)
71 va_start(chunks
, mode
);
79 chunk_t ch
= va_arg(chunks
, chunk_t
);
95 chunk_t
chunk_create_cat(u_char
*ptr
, const char* mode
, ...)
98 chunk_t construct
= chunk_create(ptr
, 0);
100 va_start(chunks
, mode
);
103 bool free_chunk
= FALSE
;
112 chunk_t ch
= va_arg(chunks
, chunk_t
);
113 memcpy(ptr
, ch
.ptr
, ch
.len
);
115 construct
.len
+= ch
.len
;
133 * Decribed in header.
135 void chunk_split(chunk_t chunk
, const char *mode
, ...)
141 va_start(chunks
, mode
);
148 len
= va_arg(chunks
, size_t);
149 ch
= va_arg(chunks
, chunk_t
*);
150 /* a null chunk means skip len bytes */
153 chunk
= chunk_skip(chunk
, len
);
160 ch
->len
= min(chunk
.len
, len
);
169 chunk
= chunk_skip(chunk
, ch
->len
);
174 ch
->len
= min(chunk
.len
, len
);
177 ch
->ptr
= malloc(ch
->len
);
178 memcpy(ch
->ptr
, chunk
.ptr
, ch
->len
);
184 chunk
= chunk_skip(chunk
, ch
->len
);
189 ch
->len
= min(ch
->len
, chunk
.len
);
190 ch
->len
= min(ch
->len
, len
);
193 memcpy(ch
->ptr
, chunk
.ptr
, ch
->len
);
199 chunk
= chunk_skip(chunk
, ch
->len
);
211 * Described in header.
213 bool chunk_write(chunk_t chunk
, const char *path
, const char *label
, mode_t mask
, bool force
)
220 fd
= fopen(path
, "r");
224 DBG1(" %s file '%s' already exists", label
, path
);
230 oldmask
= umask(mask
);
232 fd
= fopen(path
, "w");
236 fwrite(chunk
.ptr
, sizeof(u_char
), chunk
.len
, fd
);
238 DBG1(" written %s file '%s' (%u bytes)", label
, path
, chunk
.len
);
244 DBG1(" could not open %s file '%s' for writing", label
, path
);
251 * Described in header.
253 void chunk_free(chunk_t
*chunk
)
261 * Described in header.
263 chunk_t
chunk_skip(chunk_t chunk
, size_t bytes
)
265 if (chunk
.len
> bytes
)
275 * Described in header.
277 int chunk_compare(chunk_t a
, chunk_t b
)
279 int compare_len
= a
.len
- b
.len
;
280 int len
= (compare_len
< 0)? a
.len
: b
.len
;
282 if (compare_len
!= 0 || len
== 0)
286 return memcmp(a
.ptr
, b
.ptr
, len
);
290 * Described in header.
292 bool chunk_equals(chunk_t a
, chunk_t b
)
294 return a
.ptr
!= NULL
&& b
.ptr
!= NULL
&&
295 a
.len
== b
.len
&& memeq(a
.ptr
, b
.ptr
, a
.len
);
299 * Described in header.
301 bool chunk_equals_or_null(chunk_t a
, chunk_t b
)
303 if (a
.ptr
== NULL
|| b
.ptr
== NULL
)
305 return a
.len
== b
.len
&& memeq(a
.ptr
, b
.ptr
, a
.len
);
309 * Number of bytes per line to dump raw data
311 #define BYTES_PER_LINE 16
314 * output handler in printf() for byte ranges
316 static int print_bytes(FILE *stream
, const struct printf_info
*info
,
317 const void *const *args
)
319 char *bytes
= *((void**)(args
[0]));
320 int len
= *((size_t*)(args
[1]));
322 char buffer
[BYTES_PER_LINE
* 3];
323 char ascii_buffer
[BYTES_PER_LINE
+ 1];
324 char *buffer_pos
= buffer
;
325 char *bytes_pos
= bytes
;
326 char *bytes_roof
= bytes
+ len
;
331 written
+= fprintf(stream
, "=> %d bytes @ %p", len
, bytes
);
333 while (bytes_pos
< bytes_roof
)
335 static char hexdig
[] = "0123456789ABCDEF";
337 *buffer_pos
++ = hexdig
[(*bytes_pos
>> 4) & 0xF];
338 *buffer_pos
++ = hexdig
[ *bytes_pos
& 0xF];
341 (*bytes_pos
> 31 && *bytes_pos
< 127) ?
*bytes_pos
: '.';
343 if (++bytes_pos
== bytes_roof
|| i
== BYTES_PER_LINE
)
345 int padding
= 3 * (BYTES_PER_LINE
- i
);
352 *buffer_pos
++ = '\0';
353 ascii_buffer
[i
] = '\0';
355 written
+= fprintf(stream
, "\n%4d: %s %s",
356 line_start
, buffer
, ascii_buffer
);
360 line_start
+= BYTES_PER_LINE
;
372 * output handler in printf() for chunks
374 static int print_chunk(FILE *stream
, const struct printf_info
*info
,
375 const void *const *args
)
377 chunk_t
*chunk
= *((chunk_t
**)(args
[0]));
379 chunk_t copy
= *chunk
;
384 const void *new_args
[] = {&chunk
->ptr
, &chunk
->len
};
385 return print_bytes(stream
, info
, new_args
);
396 written
+= fprintf(stream
, ":");
398 written
+= fprintf(stream
, "%02x", *copy
.ptr
++);
405 * register printf() handlers
407 static void __attribute__ ((constructor
))print_register()
409 register_printf_function(PRINTF_CHUNK
, print_chunk
, arginfo_ptr
);
410 register_printf_function(PRINTF_BYTES
, print_bytes
, arginfo_ptr_int
);