diff options
Diffstat (limited to 'analyze-gz.c')
-rw-r--r-- | analyze-gz.c | 280 |
1 files changed, 0 insertions, 280 deletions
diff --git a/analyze-gz.c b/analyze-gz.c deleted file mode 100644 index a0c6d40..0000000 --- a/analyze-gz.c +++ /dev/null @@ -1,280 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <stdbool.h> -#include <assert.h> -#include <ctype.h> - -#define ID1 31 -#define ID2 139 - -enum compression_method { - DEFLATE = 8, -}; - -enum flag { - FTEXT = 1 << 0, - FHCRC = 1 << 1, - FEXTRA = 1 << 2, - FNAME = 1 << 3, - FCOMMENT = 1 << 4, -}; - -enum operating_system { - FAT = 0, - AMIGA, - VMS, - UNIX, - CMS, - ATARI_TOS, - HPFS, - MACINTOSH, - Z_SYSTEM, - CP_M, - TOPS20, - NTFS, - QDOS, - ACORN_RISCOS, -}; - -const char *os_str(enum operating_system os) { - switch (os) { - case FAT: return "FAT filesystem (MS-DOS, OS/2, NT/Win32)"; - case AMIGA: return "Amiga"; - case VMS: return "VMS (or OpenVMS)"; - case UNIX: return "Unix"; - case CMS: return "VM/CMS"; - case ATARI_TOS: return "Atari TOS"; - case HPFS: return "HPFS filesystem (OS/2, NT)"; - case MACINTOSH: return "Macintosh"; - case Z_SYSTEM: return "Z-System"; - case CP_M: return "CP/M"; - case TOPS20: return "TOPS-20"; - case NTFS: return "NTFS filesystem (NT)"; - case QDOS: return "QDOS"; - case ACORN_RISCOS: return "Acorn RISCOS"; - default: return "unknown"; - } -} - -struct member { - uint8_t id1, id2, cm, flg; - uint32_t mtime; - uint8_t xfl, os; -} __attribute__((packed)); - - -enum color { - BLACK = 0, - RED, - GREEN, - YELLOW, - BLUE, - PURPLE, - CYAN, - WHITE, -}; - - -struct segment { - enum color c; - size_t len; - uint8_t *data; -}; - -enum color next_color(void) { - static uint8_t cc = 0; - cc += 1; - cc %= 6; - return cc + 1; -} - -void color_put(enum color c) { - printf("\x1b[0;3%im", c); -} - -void color_reset(void) { - printf("\x1b[m"); -} - -#define LINELEN 0x8 -struct segment line_segments[LINELEN]; -size_t file_idx = 0; -size_t line_idx = 0; -size_t current_segment = 0; - -void cleanup_line(void) { - for (int i = 0; i < current_segment; i++) { - free(line_segments[i].data); - } -} - -void put_byte(uint8_t byte) { - static bool flip = 0; - printf("%02x", byte); - flip = !flip; - if (! flip) { - printf(" "); - } -} - -void flush_line() { - printf("%06lx: ", file_idx); - file_idx += LINELEN; - for (int i = 0; i < current_segment; i++) { - color_put(line_segments[i].c); - for (int b = 0; b < line_segments[i].len; b++) { - put_byte(line_segments[i].data[b]); - } - color_reset(); - } - for (int i = 0; i < current_segment; i++) { - color_put(line_segments[i].c); - for (int b = 0; b < line_segments[i].len; b++) { - uint8_t ch = line_segments[i].data[b]; - if (isprint(ch)) { - printf("%c", ch); - } else { - printf("."); - } - } - color_reset(); - } - printf("\n"); -} - -void add_segment(struct segment segment) { - line_segments[current_segment++] = segment; - line_idx += segment.len; - if (line_idx == LINELEN) { - flush_line(); - cleanup_line(); - current_segment = 0; - line_idx = 0; - } -} - -/* - * Buf MUST be a malloc:ed buffer, which is invalidated on this call. - */ -void write_chunk(uint8_t *buf, size_t len) { - if (line_idx + len >= LINELEN) { - enum color c = next_color(); - size_t len1 = LINELEN - line_idx, - len2 = len - len1; - uint8_t *buf1 = malloc(len1), - *buf2 = malloc(len2); - memcpy(buf1, buf, len1); - memcpy(buf2, buf + len1, len2); - free(buf); - struct segment - seg1 = { - .c = c, - .len = len1, - .data = buf1, - }, - seg2 = { - .c = c, - .len = len2, - .data = buf2, - }; - add_segment(seg1); - add_segment(seg2); - } else { - struct segment seg = { - .c = next_color(), - .len = len, - .data = buf, - }; - add_segment(seg); - } -} - -void write_chunk_s(uint8_t *buf, size_t len) { - assert (len >= 0); - uint8_t *true_buf = malloc(len); - memcpy(true_buf, buf, len); - write_chunk(true_buf, len); -} - -int main(int argc, char *argv[]) { - if (argc == 1) { - fprintf(stderr, "Usage: %s <filename.gz>\n", argv[0]); - return 1; - } - - FILE *f = fopen(argv[1], "rb"); - size_t len; - - struct member header; - uint8_t *extra_fields = NULL; - uint16_t crc16 = 0; - char *filename = NULL; - char *file_comment = NULL; - - len = fread(&header, sizeof(header), 1, f); - - if (len != 1) { - fprintf(stderr, "Unexpected end of header\n"); - return 1; - } - - write_chunk_s((uint8_t[2]) {header.id1, header.id2}, 2); - write_chunk_s(&header.cm, 1); - write_chunk_s(&header.flg, 1); - { - size_t s = sizeof(header.mtime); - uint8_t *buf = malloc(s); - memcpy(buf, &header.mtime, s); - write_chunk(buf, s); - } - write_chunk_s(&header.xfl, 1); - write_chunk_s(&header.os, 1); - - if (header.flg & FEXTRA) { - uint16_t xlen; - len = fread(&xlen, sizeof(xlen), 1, f); - { - uint8_t *buf = malloc(len); - memcpy(buf, &xlen, len); - write_chunk(buf, len); - } - extra_fields = malloc(xlen); - len = fread(extra_fields, 1, xlen, f); - write_chunk(extra_fields, xlen); - } - - if (header.flg & FNAME) { - size_t n; - len = getdelim(&filename, &n, '\0', f); - write_chunk((uint8_t*) filename, n); - } - - if (header.flg & FCOMMENT) { - size_t n; - len = getdelim(&file_comment, &n, '\0', f); - write_chunk((uint8_t*) file_comment, n); - } - - if (header.flg & FHCRC) { - len = fread(&crc16, sizeof(crc16), 1, f); - { - uint8_t *buf = malloc(len); - memcpy(buf, &crc16, len); - write_chunk(buf, len); - } - } - -// cleanup: - if (extra_fields) free(extra_fields); - if (filename) free(filename); - if (file_comment) free(file_comment); - flush_line(); - cleanup_line(); - - printf("\n"); - - -} |