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)); | 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 | int | ||||
set_nonblocking(int fd) | set_nonblocking(int fd) | ||||
{ | { | ||||
@@ -174,7 +217,7 @@ read_fully(int fd, void *buf, size_t len) | |||||
while (off < len) { | while (off < len) { | ||||
nread = read(fd, buf + off, len - off); | nread = read(fd, buf + off, len - off); | ||||
if (nread == 0) | if (nread == 0) | ||||
return ECONNRESET; | |||||
return EIO; | |||||
else if (nread == -1) | else if (nread == -1) | ||||
return errno; | return errno; | ||||
off += nread; | off += nread; | ||||
@@ -182,6 +225,48 @@ read_fully(int fd, void *buf, size_t len) | |||||
return 0; | 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 * | char * | ||||
find_btpd_dir(void) | find_btpd_dir(void) | ||||
{ | { | ||||
@@ -5,14 +5,18 @@ | |||||
#include <stdarg.h> | #include <stdarg.h> | ||||
#define min(x, y) ((x) <= (y) ? (x) : (y)) | #define min(x, y) ((x) <= (y) ? (x) : (y)) | ||||
#define SHAHEXSIZE 41 | |||||
int set_nonblocking(int fd); | int set_nonblocking(int fd); | ||||
int set_blocking(int fd); | int set_blocking(int fd); | ||||
int mkdirs(char *path); | int mkdirs(char *path); | ||||
__attribute__((format (printf, 3, 0))) | |||||
int vaopen(int *resfd, int flags, const char *fmt, va_list ap); | 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, ...); | 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 vfopen(FILE **ret, const char *mode, const char *fmt, ...); | ||||
int vfsync(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); | int has_bit(const uint8_t *bits, unsigned long index); | ||||
void clear_bit(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); | long rand_between(long min, long max); | ||||
int read_fully(int fd, void *buf, size_t len); | int read_fully(int fd, void *buf, size_t len); | ||||
int write_fully(int fd, const 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); | char *find_btpd_dir(void); | ||||