aboutsummaryrefslogtreecommitdiff
path: root/format.c
diff options
context:
space:
mode:
Diffstat (limited to 'format.c')
-rw-r--r--format.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/format.c b/format.c
new file mode 100644
index 0000000..cbd7265
--- /dev/null
+++ b/format.c
@@ -0,0 +1,188 @@
+#include "format.h"
+#include "gzip.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+struct segment empty_segment = {
+ .start = -1,
+ .end = -1,
+ .description = "No segment selected",
+};
+
+struct segment get_segment(void *mem, size_t len, ssize_t addr) {
+
+ if (addr < 0 || addr >= len) {
+ return empty_segment;
+ }
+
+
+ static char *buf = NULL;
+ if (buf != NULL) {
+ free(buf);
+ buf = NULL;
+ }
+ struct member *header = (struct member*) mem;
+
+ if (addr == 0) {
+ return (struct segment) {
+ .start = 0,
+ .end = 1,
+ .description = "ID1 = 31"
+ };
+ }
+ if (addr == 1) {
+ return (struct segment) {
+ .start = 1,
+ .end = 2,
+ .description = "ID2 = 139",
+ };
+ }
+ if (addr == 2) {
+ return (struct segment) {
+ .start = 2,
+ .end = 3,
+ .description = "CM (Compression Method)\n"
+ "CM = 8 is defalte",
+ };
+ }
+ if (addr == 3) {
+ buf = malloc(1000);
+ buf[0] = '\0';
+ for (int i = 0; i < 5; i++) {
+ if (header->flg & (1 << i)) {
+ strcat(buf, "- ");
+ strcat(buf, flag_str(1<<i));
+ strcat(buf, "\n");
+ }
+ }
+ return (struct segment) {
+ .start = 3,
+ .end = 4,
+ .description = buf,
+ };
+ }
+ if (addr >= 4 && addr < 8) {
+ buf = malloc(1000);
+ sprintf(buf, "Mtime=%i", header->mtime);
+ return (struct segment) {
+ .start = 4,
+ .end = 8,
+ .description = buf,
+ };
+ }
+ if (addr == 8) {
+ return (struct segment) {
+ .start = 8,
+ .end = 9,
+ .description = "XFL",
+ };
+ }
+ if (addr == 9) {
+ buf = malloc(1000);
+ sprintf(buf, "OS: %s\n", os_str(header->os));
+ return (struct segment) {
+ .start = 9,
+ .end = 10,
+ .description = buf,
+ };
+ }
+
+ void *ptr = ((struct member*) mem) + 1;
+
+ if (header->flg & FEXTRA) {
+ uint16_t xlen = *((uint16_t*) ptr);
+ if (mem + addr == ptr || mem + addr == ptr + 1) {
+ return (struct segment) {
+ .start = ptr - mem,
+ .end = ptr - mem + 1,
+ .description = "XLEN",
+ };
+ }
+ ptr = ((uint16_t*) ptr) + 1;
+ // if (mem + addr >= ptr && mem + addr < xlen) {
+ if (ptr - mem + addr < 2) {
+ return (struct segment) {
+ .start = ptr - mem,
+ .end = ptr - mem + xlen,
+ .description = "XLEN bytes of extra data",
+ };
+ }
+ ptr = ((uint8_t*) ptr) + 1 + xlen;
+ }
+
+ if (header->flg & FNAME) {
+ void *c = memchr(ptr, '\0', (ptr - mem) + len);
+ size_t start = ptr - mem;
+ size_t end = c - mem;
+ ptr = ((uint8_t*) c) + 1;
+ if (addr < c - mem + 1) {
+ return (struct segment) {
+ .start = start,
+ .end = end + 1,
+ .description = "Original filename",
+ };
+ }
+ }
+
+ if (header->flg & FCOMMENT) {
+ void *c = memchr(ptr, '\0', (ptr - mem) + len);
+ ptr = ((uint8_t*) c) + 1;
+ if (addr < c - mem + 1) {
+ size_t start = ptr - mem;
+ size_t end = c - mem;
+ return (struct segment) {
+ .start = start,
+ .end = end + 1,
+ .description = "File comment",
+ };
+ }
+ }
+
+ if (header->flg & FHCRC) {
+ if (addr < ptr - mem + 2) {
+ buf = malloc(1000);
+ fprintf(buf, "CRC16=" PRIu16, *((uint16_t*) ptr));
+ return (struct segment) {
+ .start = ptr - mem,
+ .end = ptr - mem + 2,
+ .description = buf,
+ };
+ }
+ ptr = (uint16_t*) ptr + 1;
+ }
+
+ if (len - addr < 4) {
+ buf = malloc(1000);
+ fprintf(buf, "ISIZE" PRIu32, *(((uint32_t*) ((uint8_t*) (mem + len))) - 1));
+ return (struct segment) {
+ .start = len - 4,
+ .end = len,
+ .description = buf,
+ };
+ }
+
+ if (len - addr - 4 < 4) {
+ buf = malloc(1000);
+ fprintf(buf, "CRC32" PRIu32, *(((uint32_t*) ((uint8_t*) (mem + len))) - 2));
+ return (struct segment) {
+ .start = len - 8,
+ .end = len - 4,
+ .description = buf,
+ };
+ }
+
+ if (ptr - mem <= addr && addr < ptr - mem + len - 8) {
+ return (struct segment) {
+ .start = ptr - mem,
+ .end = len - 8,
+ .description = "ZLIB compressed payload",
+ };
+ }
+
+
+ return empty_segment;
+
+}