#include #include uint verbose_level; void __attribute__((noreturn)) error(const char* fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); exit(EXIT_FAILURE); } int verbose(uint level, const char* fmt, ...) { int ret = 0; va_list ap; if (verbose_level >= level) { va_start(ap, fmt); vprintf(fmt, ap); } return ret; } bool ask_user_bool(tristate_t auto_response, const char* fmt, ...) { va_list ap; char prompt[256]; char* line; size_t len; int ret; bool answer; va_start(ap, fmt); vsnprintf(prompt, sizeof(prompt), fmt, ap); va_end(ap); again: printf("%s [y/n]? ", prompt); if (auto_response != t_none) { answer = (auto_response == t_true); printf("%s\n", (answer ? "y" : "n")); return answer; } line = NULL; len = 0; getline(&line, &len, stdin); if (ret > 0) { switch (line[0]) { case 'y': case 'Y': answer = true; break; case 'n': case 'N': answer = false; break; default: ret = -1; } } free(line); if (ret <= 0) { goto again; } return answer; } void pblk_read(int fd, u64 pblk, u32 count, u8* data) { off_t pos; size_t remain; ssize_t ret; pos = lseek(fd, pblk * PBLK_SIZE, SEEK_SET); if (pos == (off_t)-1) { error("Failed to seek\n"); } remain = count * PBLK_SIZE; while (remain) { ret = read(fd, data, remain); if (ret <= 0) { error("Failed to read\n"); } remain -= ret; data += ret; } } void pblk_write(int fd, u64 pblk, u32 count, const u8* data) { off_t pos; size_t remain; ssize_t ret; pos = lseek(fd, pblk * PBLK_SIZE, SEEK_SET); if (pos == (off_t)-1) { error("Failed to seek\n"); } remain = count * PBLK_SIZE; while (remain) { ret = write(fd, data, remain); if (ret <= 0) { error("Failed to write\n"); } remain -= ret; data += ret; } } void cbd_check_header(const struct cbd_header* header) { enum cbd_alg alg = cbd_compression_alg_get(&header->params); u8 level = cbd_compression_level_get(&header->params); if (memcmp(header->magic, CBD_MAGIC, sizeof(header->magic))) { error("Bad magic\n"); } if (header->version_major != CBD_VERSION_MAJOR) { error("Bad major version\n"); } if (header->version_minor != CBD_VERSION_MINOR) { error("Bad major version\n"); } if (alg == CBD_ALG_NONE || alg >= CBD_ALG_MAX) { error("Bad algorithm\n"); } if (level < 1 || level > 9) { error("Bad compression\n"); } if (header->params.lblk_shift < LBLK_SHIFT_MIN || header->params.lblk_shift >= LBLK_SHIFT_MAX) { error("Bad logical block shift\n"); } }