Add function for reading a whole file. Enable printf format checking for some functions.master
@@ -31,6 +31,49 @@ has_bit(const uint8_t *bits, unsigned long index) | |||
return bits[index / 8] & (1 << (7 - index % 8)); | |||
} | |||
uint8_t | |||
hex2i(char c) | |||
{ | |||
if (c >= '0' && c <= '9') | |||
return c - '0'; | |||
else if (c >= 'a' && c <= 'f') | |||
return 10 + c - 'a'; | |||
else | |||
abort(); | |||
} | |||
int | |||
ishex(char *str) | |||
{ | |||
while (*str != '\0') { | |||
if (!((*str >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f'))) | |||
return 0; | |||
str++; | |||
} | |||
return 1; | |||
} | |||
uint8_t * | |||
hex2bin(const char *hex, uint8_t *bin, size_t bsize) | |||
{ | |||
for (size_t i = 0; i < bsize; i++) | |||
bin[i] = hex2i(hex[i * 2]) << 4 | hex2i(hex[i * 2 + 1]); | |||
return bin; | |||
} | |||
char * | |||
bin2hex(const uint8_t *bin, char *hex, size_t bsize) | |||
{ | |||
size_t i; | |||
const char *hexc = "0123456789abcdef"; | |||
for (i = 0; i < bsize; i++) { | |||
hex[i * 2] = hexc[(bin[i] >> 4) & 0xf]; | |||
hex[i * 2 + 1] = hexc[bin[i] &0xf]; | |||
} | |||
hex[i * 2] = '\0'; | |||
return hex; | |||
} | |||
int | |||
set_nonblocking(int fd) | |||
{ | |||
@@ -174,7 +217,7 @@ read_fully(int fd, void *buf, size_t len) | |||
while (off < len) { | |||
nread = read(fd, buf + off, len - off); | |||
if (nread == 0) | |||
return ECONNRESET; | |||
return EIO; | |||
else if (nread == -1) | |||
return errno; | |||
off += nread; | |||
@@ -182,6 +225,48 @@ read_fully(int fd, void *buf, size_t len) | |||
return 0; | |||
} | |||
int | |||
read_whole_file(void **out, size_t *size, const char *fmt, ...) | |||
{ | |||
int err, fd; | |||
int didmalloc = 0; | |||
struct stat sb; | |||
va_list ap; | |||
va_start(ap, fmt); | |||
err = vaopen(&fd, O_RDONLY, fmt, ap); | |||
va_end(ap); | |||
if (err != 0) | |||
return err; | |||
if (fstat(fd, &sb) != 0) { | |||
err = errno; | |||
goto error; | |||
} | |||
if (*size != 0 && *size < sb.st_size) { | |||
err = EFBIG; | |||
goto error; | |||
} | |||
*size = sb.st_size; | |||
if (*out == NULL) { | |||
if ((*out = malloc(*size)) == NULL) { | |||
err = errno; | |||
goto error; | |||
} | |||
didmalloc = 1; | |||
} | |||
if ((err = read_fully(fd, *out, *size)) != 0) | |||
goto error; | |||
close(fd); | |||
return 0; | |||
error: | |||
if (didmalloc) | |||
free(*out); | |||
close(fd); | |||
return err; | |||
} | |||
char * | |||
find_btpd_dir(void) | |||
{ | |||
@@ -5,14 +5,18 @@ | |||
#include <stdarg.h> | |||
#define min(x, y) ((x) <= (y) ? (x) : (y)) | |||
#define SHAHEXSIZE 41 | |||
int set_nonblocking(int fd); | |||
int set_blocking(int fd); | |||
int mkdirs(char *path); | |||
__attribute__((format (printf, 3, 0))) | |||
int vaopen(int *resfd, int flags, const char *fmt, va_list ap); | |||
__attribute__((format (printf, 3, 4))) | |||
int vopen(int *resfd, int flags, const char *fmt, ...); | |||
__attribute__((format (printf, 3, 4))) | |||
int vfopen(FILE **ret, const char *mode, const char *fmt, ...); | |||
int vfsync(const char *fmt, ...); | |||
@@ -20,10 +24,17 @@ void set_bit(uint8_t *bits, unsigned long index); | |||
int has_bit(const uint8_t *bits, unsigned long index); | |||
void clear_bit(uint8_t *bits, unsigned long index); | |||
char *bin2hex(const uint8_t *bin, char *hex, size_t bsize); | |||
uint8_t *hex2bin(const char *hex, uint8_t *bin, size_t bsize); | |||
uint8_t hex2i(char c); | |||
int ishex(char *str); | |||
long rand_between(long min, long max); | |||
int read_fully(int fd, void *buf, size_t len); | |||
int write_fully(int fd, const void *buf, size_t len); | |||
__attribute__((format (printf, 3, 4))) | |||
int read_whole_file(void **out, size_t *size, const char *fmt, ...); | |||
char *find_btpd_dir(void); | |||