| /* 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; | 
 | } |