2 * Copyright (C) 2008-2010 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
32 ENUM(status_names
, SUCCESS
, NEED_MORE
,
48 * Described in header.
50 void *clalloc(void * pointer
, size_t size
)
55 memcpy(data
, pointer
, size
);
61 * Described in header.
63 void memxor(u_int8_t dst
[], u_int8_t src
[], size_t n
)
67 /* byte wise XOR until dst aligned */
68 for (i
= 0; (uintptr_t)&dst
[i
] % sizeof(long) && i
< n
; i
++)
72 /* try to use words if src shares an aligment with dst */
73 switch (((uintptr_t)&src
[i
] % sizeof(long)))
76 for (m
= n
- sizeof(long); i
<= m
; i
+= sizeof(long))
78 *(long*)&dst
[i
] ^= *(long*)&src
[i
];
82 for (m
= n
- sizeof(int); i
<= m
; i
+= sizeof(int))
84 *(int*)&dst
[i
] ^= *(int*)&src
[i
];
88 for (m
= n
- sizeof(short); i
<= m
; i
+= sizeof(short))
90 *(short*)&dst
[i
] ^= *(short*)&src
[i
];
96 /* byte wise XOR of the rest */
104 * Described in header.
106 void memwipe_noinline(void *ptr
, size_t n
)
108 memwipe_inline(ptr
, n
);
112 * Described in header.
114 void *memstr(const void *haystack
, const char *needle
, size_t n
)
116 unsigned const char *pos
= haystack
;
117 size_t l
= strlen(needle
);
118 for (; n
>= l
; ++pos
, --n
)
120 if (memeq(pos
, needle
, l
))
129 * Described in header.
131 char* translate(char *str
, const char *from
, const char *to
)
134 if (strlen(from
) != strlen(to
))
141 if ((match
= strchr(from
, *pos
)) != NULL
)
143 *pos
= to
[match
- from
];
151 * Described in header.
153 bool mkdir_p(const char *path
, mode_t mode
)
156 char *pos
, full
[PATH_MAX
];
158 if (!path
|| *path
== '\0')
162 len
= snprintf(full
, sizeof(full
)-1, "%s", path
);
163 if (len
< 0 || len
>= sizeof(full
)-1)
165 DBG1(DBG_LIB
, "path string %s too long", path
);
168 /* ensure that the path ends with a '/' */
169 if (full
[len
-1] != '/')
174 /* skip '/' at the beginning */
179 while ((pos
= strchr(pos
, '/')))
182 if (access(full
, F_OK
) < 0)
184 if (mkdir(full
, mode
) < 0)
186 DBG1(DBG_LIB
, "failed to create directory %s", full
);
197 * Return monotonic time
199 time_t time_monotonic(timeval_t
*tv
)
201 #if defined(HAVE_CLOCK_GETTIME) && \
202 (defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
203 defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
204 /* as we use time_monotonic() for condvar operations, we use the
205 * monotonic time source only if it is also supported by pthread. */
208 if (clock_gettime(CLOCK_MONOTONIC
, &ts
) == 0)
212 tv
->tv_sec
= ts
.tv_sec
;
213 tv
->tv_usec
= ts
.tv_nsec
/ 1000;
217 #endif /* HAVE_CLOCK_GETTIME && (...) */
218 /* Fallback to non-monotonic timestamps:
219 * On MAC OS X, creating monotonic timestamps is rather difficult. We
220 * could use mach_absolute_time() and catch sleep/wakeup notifications.
221 * We stick to the simpler (non-monotonic) gettimeofday() for now.
222 * But keep in mind: we need the same time source here as in condvar! */
227 if (gettimeofday(tv
, NULL
) != 0)
228 { /* should actually never fail if passed pointers are valid */
261 status_t
return_failed()
273 #ifndef HAVE_GCC_ATOMIC_OPERATIONS
277 * We use a single mutex for all refcount variables.
279 static pthread_mutex_t ref_mutex
= PTHREAD_MUTEX_INITIALIZER
;
284 void ref_get(refcount_t
*ref
)
286 pthread_mutex_lock(&ref_mutex
);
288 pthread_mutex_unlock(&ref_mutex
);
294 bool ref_put(refcount_t
*ref
)
298 pthread_mutex_lock(&ref_mutex
);
299 more_refs
= --(*ref
) > 0;
300 pthread_mutex_unlock(&ref_mutex
);
303 #endif /* HAVE_GCC_ATOMIC_OPERATIONS */
306 * Described in header.
308 int time_printf_hook(char *dst
, size_t len
, printf_hook_spec_t
*spec
,
309 const void *const *args
)
311 static const char* months
[] = {
312 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
313 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
315 time_t *time
= *((time_t**)(args
[0]));
316 bool utc
= *((bool*)(args
[1]));;
319 if (time
== UNDEFINED_TIME
)
321 return print_in_hook(dst
, len
, "--- -- --:--:--%s----",
322 utc ?
" UTC " : " ");
330 localtime_r(time
, &t
);
332 return print_in_hook(dst
, len
, "%s %02d %02d:%02d:%02d%s%04d",
333 months
[t
.tm_mon
], t
.tm_mday
, t
.tm_hour
, t
.tm_min
,
334 t
.tm_sec
, utc ?
" UTC " : " ", t
.tm_year
+ 1900);
338 * Described in header.
340 int time_delta_printf_hook(char *dst
, size_t len
, printf_hook_spec_t
*spec
,
341 const void *const *args
)
343 char* unit
= "second";
344 time_t *arg1
= *((time_t**)(args
[0]));
345 time_t *arg2
= *((time_t**)(args
[1]));
346 u_int64_t delta
= llabs(*arg1
- *arg2
);
348 if (delta
> 2 * 60 * 60 * 24)
350 delta
/= 60 * 60 * 24;
353 else if (delta
> 2 * 60 * 60)
358 else if (delta
> 2 * 60)
363 return print_in_hook(dst
, len
, "%" PRIu64
" %s%s", delta
, unit
,
364 (delta
== 1) ?
"" : "s");
368 * Number of bytes per line to dump raw data
370 #define BYTES_PER_LINE 16
372 static char hexdig_upper
[] = "0123456789ABCDEF";
375 * Described in header.
377 int mem_printf_hook(char *dst
, size_t dstlen
,
378 printf_hook_spec_t
*spec
, const void *const *args
)
380 char *bytes
= *((void**)(args
[0]));
381 int len
= *((size_t*)(args
[1]));
383 char buffer
[BYTES_PER_LINE
* 3];
384 char ascii_buffer
[BYTES_PER_LINE
+ 1];
385 char *buffer_pos
= buffer
;
386 char *bytes_pos
= bytes
;
387 char *bytes_roof
= bytes
+ len
;
392 written
+= print_in_hook(dst
, dstlen
, "=> %d bytes @ %p", len
, bytes
);
394 while (bytes_pos
< bytes_roof
)
396 *buffer_pos
++ = hexdig_upper
[(*bytes_pos
>> 4) & 0xF];
397 *buffer_pos
++ = hexdig_upper
[ *bytes_pos
& 0xF];
400 (*bytes_pos
> 31 && *bytes_pos
< 127) ?
*bytes_pos
: '.';
402 if (++bytes_pos
== bytes_roof
|| i
== BYTES_PER_LINE
)
404 int padding
= 3 * (BYTES_PER_LINE
- i
);
410 *buffer_pos
++ = '\0';
411 ascii_buffer
[i
] = '\0';
413 written
+= print_in_hook(dst
, dstlen
, "\n%4d: %s %s",
414 line_start
, buffer
, ascii_buffer
);
417 line_start
+= BYTES_PER_LINE
;