|  | /* Copyright (c) 2015 Google Inc | 
|  | * Davide Libenzi <dlibenzi@google.com> | 
|  | * See LICENSE for details. | 
|  | */ | 
|  |  | 
|  | #include <sys/types.h> | 
|  | #include <sys/stat.h> | 
|  | #include <stdint.h> | 
|  | #include <stdio.h> | 
|  | #include <string.h> | 
|  | #include <stdlib.h> | 
|  | #include <unistd.h> | 
|  | #include <fcntl.h> | 
|  | #include <errno.h> | 
|  | #include "xlib.h" | 
|  |  | 
|  | int xopen(const char *path, int flags, mode_t mode) | 
|  | { | 
|  | int fd = open(path, flags, mode); | 
|  |  | 
|  | if (fd < 0) { | 
|  | perror(path); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | return fd; | 
|  | } | 
|  |  | 
|  | void xwrite(int fd, const void *data, size_t size) | 
|  | { | 
|  | ssize_t wcount = write(fd, data, size); | 
|  |  | 
|  | if (size != (size_t) wcount) { | 
|  | perror("Writing file"); | 
|  | exit(1); | 
|  | } | 
|  | } | 
|  |  | 
|  | void xread(int fd, void *data, size_t size) | 
|  | { | 
|  | ssize_t rcount = read(fd, data, size); | 
|  |  | 
|  | if (size != (size_t) rcount) { | 
|  | perror("Reading file"); | 
|  | exit(1); | 
|  | } | 
|  | } | 
|  |  | 
|  | void xpwrite(int fd, const void *data, size_t size, off_t off) | 
|  | { | 
|  | ssize_t wcount = pwrite(fd, data, size, off); | 
|  |  | 
|  | if (size != (size_t) wcount) { | 
|  | perror("Writing file"); | 
|  | exit(1); | 
|  | } | 
|  | } | 
|  |  | 
|  | void xpread(int fd, void *data, size_t size, off_t off) | 
|  | { | 
|  | ssize_t rcount = pread(fd, data, size, off); | 
|  |  | 
|  | if (size != (size_t) rcount) { | 
|  | perror("Reading file"); | 
|  | exit(1); | 
|  | } | 
|  | } | 
|  |  | 
|  | FILE *xfopen(const char *path, const char *mode) | 
|  | { | 
|  | FILE *file = fopen(path, mode); | 
|  |  | 
|  | if (!file) { | 
|  | fprintf(stderr, "Unable to open file '%s' for mode '%s': %s\n", | 
|  | path, mode, strerror(errno)); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | return file; | 
|  | } | 
|  |  | 
|  | FILE *xfdopen(int fd, const char *mode) | 
|  | { | 
|  | FILE *file = fdopen(fd, mode); | 
|  |  | 
|  | if (!file) { | 
|  | fprintf(stderr, | 
|  | "Unable to reopen fd '%d' for mode '%s': %s\n", fd, | 
|  | mode, strerror(errno)); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | return file; | 
|  | } | 
|  |  | 
|  | off_t xfsize(FILE *file) | 
|  | { | 
|  | struct stat stat_buf; | 
|  | int fd = fileno(file); | 
|  |  | 
|  | if (fd < 0) { | 
|  | perror("xfsize fileno"); | 
|  | exit(1); | 
|  | } | 
|  | if (fstat(fd, &stat_buf)) { | 
|  | perror("xfsize fstat"); | 
|  | exit(1); | 
|  | } | 
|  | return stat_buf.st_size; | 
|  | } | 
|  |  | 
|  | void xfwrite(const void *data, size_t size, FILE *file) | 
|  | { | 
|  | if (fwrite(data, 1, size, file) != size) { | 
|  | fprintf(stderr, "Unable to write %lu bytes: %s\n", size, | 
|  | strerror(errno)); | 
|  | exit(1); | 
|  | } | 
|  | } | 
|  |  | 
|  | void xfseek(FILE *file, off_t offset, int whence) | 
|  | { | 
|  | if (fseeko(file, offset, whence)) { | 
|  | int error = errno; | 
|  |  | 
|  | fprintf(stderr, | 
|  | "Unable to seek at offset %ld from %s (fpos=%ld): %s\n", | 
|  | offset, whence == SEEK_SET ? "beginning of file" : | 
|  | (whence == SEEK_END ? "end of file" : | 
|  | "current position"), | 
|  | ftell(file), strerror(error)); | 
|  | exit(1); | 
|  | } | 
|  | } | 
|  |  | 
|  | void *xmalloc(size_t size) | 
|  | { | 
|  | void *data = malloc(size); | 
|  |  | 
|  | if (!data) { | 
|  | perror("Allocating memory block"); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | return data; | 
|  | } | 
|  |  | 
|  | void *xzmalloc(size_t size) | 
|  | { | 
|  | void *data = xmalloc(size); | 
|  |  | 
|  | memset(data, 0, size); | 
|  |  | 
|  | return data; | 
|  | } | 
|  |  | 
|  | char *xstrdup(const char *str) | 
|  | { | 
|  | char *dstr = strdup(str); | 
|  |  | 
|  | if (dstr == NULL) { | 
|  | perror("Duplicating a string"); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | return dstr; | 
|  | } | 
|  |  | 
|  | const char *vb_decode_uint64(const char *data, uint64_t *pval) | 
|  | { | 
|  | unsigned int i; | 
|  | uint64_t val = 0; | 
|  |  | 
|  | for (i = 0; (*data & 0x80) != 0; i += 7, data++) | 
|  | val |= (((uint64_t) *data) & 0x7f) << i; | 
|  | *pval = val | ((uint64_t) *data) << i; | 
|  |  | 
|  | return data + 1; | 
|  | } | 
|  |  | 
|  | int vb_fdecode_uint64(FILE *file, uint64_t *pval) | 
|  | { | 
|  | unsigned int i = 0; | 
|  | uint64_t val = 0; | 
|  |  | 
|  | for (;;) { | 
|  | int c = fgetc(file); | 
|  |  | 
|  | if (c == EOF) | 
|  | return EOF; | 
|  | val |= (((uint64_t) c) & 0x7f) << i; | 
|  | i += 7; | 
|  | if ((c & 0x80) == 0) | 
|  | break; | 
|  | } | 
|  | *pval = val; | 
|  |  | 
|  | return i / 7; | 
|  | } | 
|  |  | 
|  | uint8_t nibble_to_num(char c) | 
|  | { | 
|  | switch (c) { | 
|  | case '0': | 
|  | return 0; | 
|  | case '1': | 
|  | return 1; | 
|  | case '2': | 
|  | return 2; | 
|  | case '3': | 
|  | return 3; | 
|  | case '4': | 
|  | return 4; | 
|  | case '5': | 
|  | return 5; | 
|  | case '6': | 
|  | return 6; | 
|  | case '7': | 
|  | return 7; | 
|  | case '8': | 
|  | return 8; | 
|  | case '9': | 
|  | return 9; | 
|  | case 'a': | 
|  | case 'A': | 
|  | return 0xa; | 
|  | case 'b': | 
|  | case 'B': | 
|  | return 0xb; | 
|  | case 'c': | 
|  | case 'C': | 
|  | return 0xc; | 
|  | case 'd': | 
|  | case 'D': | 
|  | return 0xd; | 
|  | case 'e': | 
|  | case 'E': | 
|  | return 0xe; | 
|  | case 'f': | 
|  | case 'F': | 
|  | return 0xf; | 
|  | }; | 
|  | return -1; | 
|  | } |