TWLbf/utils.c
2017-10-01 17:34:51 +08:00

170 lines
4.0 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <assert.h>
#include "utils.h"
int htoi(char a){
if(a >= '0' && a <= '9'){
return a - '0';
}else if(a >= 'a' && a <= 'f'){
return a - ('a' - 0xa);
}else if(a >= 'A' && a <= 'F'){
return a - ('A' - 0xa);
}else{
return -1;
}
}
int hex2bytes(u8 *out, unsigned byte_len, const char *in, int critical){
if (strlen(in) != byte_len << 1){
fprintf(stderr, "%s: invalid input length, expecting %u, got %u.\n",
__FUNCTION__, (unsigned)byte_len << 1, (unsigned)strlen(in));
assert(!critical);
return -1;
}
for(unsigned i = 0; i < byte_len; ++i){
int h = htoi(*in++), l = htoi(*in++);
if(h == -1 || l == -1){
fprintf(stderr, "%s: invalid input \"%c%c\"\n",
__FUNCTION__, *(in - 2), *(in - 1));
assert(!critical);
return -2;
}
*out++ = (h << 4) + l;
}
return 0;
}
static char hexdump_buf[HEXDUMP_BUF_SIZE];
// CAUTION, this always assume the buffer is big enough
// it uses a static buffer so the value is only valid until next call
// and of course this is not thread safe
const char *hexdump(const void *b, unsigned l, int space){
const u8 *p = (u8*)b;
char *out = hexdump_buf;
for(unsigned i = 0; i < l; ++i){
out += sprintf(out, "%02x", *p);
++p;
if(space && i < l - 1){
*out++ = ' ';
}
}
return hexdump_buf;
}
void print_hex(const void *b, unsigned len) {
const u8 *p = (u8*)b;
const unsigned cols = 16;
int rows = (len + cols - 1) / cols;
// first print on t1 until it exeeds 19 lines
for (unsigned i = 0; i < rows; ++i) {
printf("%04x:", i * cols);
for (unsigned j = 0; j < cols; ++j) {
if (j % 4 == 0) {
printf(" ");
}
int offset = i * cols + j;
if (offset < len) {
printf("%02x ", p[offset]);
} else {
printf(" ");
}
}
for (unsigned j = 0; j < cols; ++j) {
if (j % 4 == 0) {
printf(" ");
}
int offset = i * cols + j;
if (offset < len) {
char c = p[offset];
printf("%c", c >= 0x20 && c <= 0x7e ? c : '.');
} else {
printf(" ");
}
}
printf("\n");
}
}
void read_block_from_file(void *out, const char *file_name, size_t offset, size_t size) {
FILE * f = fopen(file_name, "rb");
if (f == NULL) {
fprintf(stderr, "can't read file: %s\n", file_name);
exit(-1);
}
fseek(f, offset, SEEK_SET);
size_t read = fread(out, 1, size, f);
if (read != size) {
fprintf(stderr, "failed to read %u bytes at offset %u from file: %s",
(unsigned)size, (unsigned)offset, file_name);
exit(-1);
}
fclose(f);
}
// read entire file to memory, don't use it on large files
// the caller is resposible to free the memory
void* read_file(const char *file_name, unsigned *psize) {
FILE *f = fopen(file_name, "rb");
if (f == NULL) {
fprintf(stderr, "can't read file: %s\n", file_name);
exit(-1);
}
fseek(f, 0, SEEK_END);
*psize = ftell(f);
if (*psize == 0) {
fprintf(stderr, "file length is zero: %s\n", file_name);
exit(-1);
}
// printf("size: %u\n", (unsigned)*psize);
void *p = malloc(*psize);
if (p == NULL) {
fprintf(stderr, "failed to alloc buffer to read %s\n", file_name);
exit(-2);
}
fseek(f, 0, SEEK_SET);
size_t read = fread(p, 1, *psize, f);
if (read != *psize) {
fprintf(stderr, "failed to read entire file %s\n", file_name);
free(p);
exit(-1);
}
fclose(f);
return p;
}
void dump_to_file(const char *file_name, const void *buf, size_t len) {
FILE *f = fopen(file_name, "r");
if (f != NULL) {
fclose(f);
fprintf(stderr, "%s exists, won't overwrite\n", file_name);
return;
}
f = fopen(file_name, "wb");
if (f == NULL) {
fprintf(stderr, "can't open file to write: %s\n", file_name);
return;
}
size_t written = fwrite(buf, 1, len, f);
if (written != len) {
fprintf(stderr, "failed to write %u bytes to %s\n",
(unsigned)len, file_name);
}
fclose(f);
}
// this stupid thing shares the hexdump_buf with hexdump
const char *to_Mebi(size_t size) {
if (size % (1024 * 1024)) {
sprintf(hexdump_buf, "%.2f", (float)(((double)size) / 1024 / 1024));
} else {
sprintf(hexdump_buf, "%u", (unsigned)(size >> 20));
}
return hexdump_buf;
}