#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <endian.h>
#include <errno.h>
#include <time.h>
#include "util.h"
#include "valgrind_internal.h"
unsigned long long Pagesize;
unsigned long long Mmap_align;
Malloc_func Malloc = malloc;
Free_func Free = free;
Realloc_func Realloc = realloc;
Strdup_func Strdup = strdup;
void *
Zalloc(size_t sz)
{
void *ret = Malloc(sz);
if (!ret)
return NULL;
return memset(ret, 0, sz);
}
#ifdef ANY_VG_TOOL_ENABLED
unsigned _On_valgrind;
#endif
int
util_is_zeroed(const void *addr, size_t len)
{
const char *a = addr;
while (len-- > 0)
if (*a++)
return 0;
return 1;
}
int
util_checksum(void *addr, size_t len, uint64_t *csump, int insert)
{
if (len % 4 != 0)
abort();
uint32_t *p32 = addr;
uint32_t *p32end = (uint32_t *)((char *)addr + len);
uint32_t lo32 = 0;
uint32_t hi32 = 0;
uint64_t csum;
while (p32 < p32end)
if (p32 == (uint32_t *)csump) {
p32++;
hi32 += lo32;
p32++;
hi32 += lo32;
} else {
lo32 += le32toh(*p32);
++p32;
hi32 += lo32;
}
csum = (uint64_t)hi32 << 32 | lo32;
if (insert) {
*csump = htole64(csum);
return 1;
}
return *csump == htole64(csum);
}
void
util_set_alloc_funcs(void *(*malloc_func)(size_t size),
void (*free_func)(void *ptr),
void *(*realloc_func)(void *ptr, size_t size),
char *(*strdup_func)(const char *s))
{
Malloc = (malloc_func == NULL) ? malloc : malloc_func;
Free = (free_func == NULL) ? free : free_func;
Realloc = (realloc_func == NULL) ? realloc : realloc_func;
Strdup = (strdup_func == NULL) ? strdup : strdup_func;
}
char *
util_fgets(char *buffer, int max, FILE *stream)
{
char *str = fgets(buffer, max, stream);
if (str == NULL)
goto end;
int len = (int)strlen(str);
if (len < 2)
goto end;
if (str[len - 2] == '\r' && str[len - 1] == '\n') {
str[len - 2] = '\n';
str[len - 1] = '\0';
}
end:
return str;
}
struct suff {
const char *suff;
uint64_t mag;
};
int
util_parse_size(const char *str, size_t *sizep)
{
const struct suff suffixes[] = {
{ "B", 1ULL },
{ "K", 1ULL << 10 },
{ "M", 1ULL << 20 },
{ "G", 1ULL << 30 },
{ "T", 1ULL << 40 },
{ "P", 1ULL << 50 },
{ "KiB", 1ULL << 10 },
{ "MiB", 1ULL << 20 },
{ "GiB", 1ULL << 30 },
{ "TiB", 1ULL << 40 },
{ "PiB", 1ULL << 50 },
{ "kB", 1000ULL },
{ "MB", 1000ULL * 1000 },
{ "GB", 1000ULL * 1000 * 1000 },
{ "TB", 1000ULL * 1000 * 1000 * 1000 },
{ "PB", 1000ULL * 1000 * 1000 * 1000 * 1000 }
};
int res = -1;
unsigned i;
size_t size = 0;
char unit[9] = {0};
int ret = sscanf(str, "%zu%8s", &size, unit);
if (ret == 1) {
res = 0;
} else if (ret == 2) {
for (i = 0; i < ARRAY_SIZE(suffixes); ++i) {
if (strcmp(suffixes[i].suff, unit) == 0) {
size = size * suffixes[i].mag;
res = 0;
break;
}
}
} else {
return -1;
}
if (sizep && res == 0)
*sizep = size;
return res;
}
void
util_init(void)
{
if (Pagesize == 0)
Pagesize = (unsigned long) sysconf(_SC_PAGESIZE);
#ifndef _WIN32
Mmap_align = Pagesize;
#else
if (Mmap_align == 0) {
SYSTEM_INFO si;
GetSystemInfo(&si);
Mmap_align = si.dwAllocationGranularity;
}
#endif
#ifdef ANY_VG_TOOL_ENABLED
_On_valgrind = RUNNING_ON_VALGRIND;
#endif
}
char *
util_concat_str(const char *s1, const char *s2)
{
char *result = malloc(strlen(s1) + strlen(s2) + 1);
if (!result)
return NULL;
strcpy(result, s1);
strcat(result, s2);
return result;
}
struct tm *
util_localtime(const time_t *timep)
{
int oerrno = errno;
struct tm *tm = localtime(timep);
if (tm != NULL)
errno = oerrno;
return tm;
}