Added jigdump, a simple utility to dump the contents of a template file.
authorSteve McIntyre <steve@einval.com>
Sun, 13 Mar 2005 22:18:28 +0000 (22:18 +0000)
committerSteve McIntyre <steve@einval.com>
Sun, 13 Mar 2005 22:18:28 +0000 (22:18 +0000)
jigdump.1 [new file with mode: 0644]
jigdump.c [new file with mode: 0644]

diff --git a/jigdump.1 b/jigdump.1
new file mode 100644 (file)
index 0000000..3e7353a
--- /dev/null
+++ b/jigdump.1
@@ -0,0 +1,20 @@
+.TH JIGDUMP 1 "September 2004" "Jigit jigdo tools"
+.SH NAME
+jigdump \- Dump the contents of a template file
+.SH SYNOPSIS
+.B jigdump
+<template file>
+.SH DESCRIPTION
+.PP
+jigdump will parse a template file and list its contents. Mainly
+useful just for debugging jigdo and friends...
+.SH "SEE ALSO"
+\fBjigdo-file\fP(1), \fBjigit\fP(1), \fBjigsum\fP(1) and \fBmkimage\fP(1).
+.SH "COPYRIGHT"
+Copyright 2004 Steve McIntyre (steve@einval.com)
+.PP
+jigdump may be copied under the terms and conditions of version 2
+of the GNU General Public License, as published by the Free
+Software Foundation (Cambridge, MA, USA).
+.SH "AUTHOR"
+Written by Steve McIntyre (steve@einval.com)
diff --git a/jigdump.c b/jigdump.c
new file mode 100644 (file)
index 0000000..7d7b610
--- /dev/null
+++ b/jigdump.c
@@ -0,0 +1,281 @@
+#include <errno.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <zlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+typedef unsigned long long UINT64;
+typedef unsigned long      UINT32;
+
+#define BUF_SIZE 65536
+
+typedef enum state_
+{
+    STARTING,
+    IN_DATA,
+    IN_DESC,
+    DUMP_DESC,
+    DONE,
+    ERROR
+} e_state;
+
+off_t find_string(unsigned char *buf, size_t buf_size, char *search)
+{
+    size_t length = strlen(search);
+    off_t result;
+    
+    for (result = 0; result < (buf_size - length); result++)
+    {
+        if (!memcmp(&buf[result], search, length))
+            return result;
+    }
+    return -1;
+}
+
+off_t parse_data_block(off_t offset, unsigned char *buf, size_t buf_size)
+{
+    /* Parse the contents of this data block... */
+    UINT64 dataLen = 0;
+    UINT64 dataUnc = 0;
+    
+    printf("\nDATA block found at offset %lld\n", offset);
+    dataLen = (UINT64)buf[4];
+    dataLen |= (UINT64)buf[5] << 8;
+    dataLen |= (UINT64)buf[6] << 16;
+    dataLen |= (UINT64)buf[7] << 24;
+    dataLen |= (UINT64)buf[8] << 32;
+    dataLen |= (UINT64)buf[9] << 40;
+    printf("  compressed block size %llu bytes\n", dataLen);
+
+    dataUnc = (UINT64)buf[10];
+    dataUnc |= (UINT64)buf[11] << 8;
+    dataUnc |= (UINT64)buf[12] << 16;
+    dataUnc |= (UINT64)buf[13] << 24;
+    dataUnc |= (UINT64)buf[14] << 32;
+    dataUnc |= (UINT64)buf[15] << 40;
+    printf("  uncompressed block size %llu bytes\n", dataUnc);
+
+    return dataLen;
+}
+
+void base64_dump(unsigned char *buf, size_t buf_size)
+{
+    const char *b64_enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+    int value = 0;
+    unsigned int i;
+    int bits = 0;
+
+    for (i = 0; i < buf_size ; i++)
+    {
+        value = (value << 8) | buf[i];
+        bits += 2;
+        printf("%c", b64_enc[(value >> bits) & 63U]);
+        if (bits >= 8) {
+            bits -= 6;
+            printf("%c", b64_enc[(value >> bits) & 63U]);
+        }
+    }
+    if (bits > 0)
+    {
+        value <<= 8 - bits;
+        printf("%c", b64_enc[(value >> bits) & 63U]);
+    }
+}
+
+off_t parse_desc_block(off_t offset, unsigned char *buf, size_t buf_size)
+{
+    /* Parse the contents of this data block... */
+    UINT64 descLen = 0;
+    
+    printf("\nDESC block found at offset %lld\n", offset);
+    descLen = (UINT64)buf[4];
+    descLen |= (UINT64)buf[5] << 8;
+    descLen |= (UINT64)buf[6] << 16;
+    descLen |= (UINT64)buf[7] << 24;
+    descLen |= (UINT64)buf[8] << 32;
+    descLen |= (UINT64)buf[9] << 40;
+    printf("  DESC block size is %llu bytes\n", descLen);
+    
+    return 10;
+}
+
+off_t parse_desc_data(off_t offset, unsigned char *buf, size_t buf_size)
+{
+    int type = buf[0];
+    printf("  DESC entry: block type %d\n", type);
+    
+    switch (type)
+    {
+        case 2:
+        {
+            UINT64 skipLen = 0;
+            skipLen = (UINT64)buf[1];
+            skipLen |= (UINT64)buf[2] << 8;
+            skipLen |= (UINT64)buf[3] << 16;
+            skipLen |= (UINT64)buf[4] << 24;
+            skipLen |= (UINT64)buf[5] << 32;
+            skipLen |= (UINT64)buf[6] << 40;
+            printf("    Unmatched data, %llu bytes\n", skipLen);
+            return 7;
+        }
+        case 5:
+        {
+            UINT64 imglen = 0;
+            UINT32 blocklen = 0;
+            int i = 0;
+
+            imglen = (UINT64)buf[1];
+            imglen |= (UINT64)buf[2] << 8;
+            imglen |= (UINT64)buf[3] << 16;
+            imglen |= (UINT64)buf[4] << 24;
+            imglen |= (UINT64)buf[5] << 32;
+            imglen |= (UINT64)buf[6] << 40;
+
+            blocklen = (UINT32)buf[23];
+            blocklen |= (UINT32)buf[24] << 8;
+            blocklen |= (UINT32)buf[25] << 16;
+            blocklen |= (UINT32)buf[26] << 24;
+
+            printf("    Original image length %llu bytes\n", imglen);
+            printf("    Image MD5: ");
+            for (i = 7; i < 23; i++)
+                printf("%2.2x", buf[i]);
+            printf(" (");
+            base64_dump(&buf[7], 16);
+            printf(")");
+            printf("\n    MD5 block length %lu bytes\n", blocklen);
+            return 0; /* i.e. we're finished! */
+        }
+        case 6:
+        {
+            UINT64 fileLen = 0;
+            int i = 0;
+
+            fileLen = (UINT64)buf[1];
+            fileLen |= (UINT64)buf[2] << 8;
+            fileLen |= (UINT64)buf[3] << 16;
+            fileLen |= (UINT64)buf[4] << 24;
+            fileLen |= (UINT64)buf[5] << 32;
+            fileLen |= (UINT64)buf[6] << 40;
+            
+            printf("    File, length %llu bytes\n", fileLen);
+            printf("    file rsyncsum: ");
+            for (i = 7; i < 15; i++)
+                printf("%2.2x", buf[i]);
+            printf("\n    file md5: ");
+            for (i = 15; i < 31; i++)
+                printf("%2.2x", buf[i]);
+            printf(" (");
+            base64_dump(&buf[15], 16);
+            printf(")");
+            printf("\n");
+            return 31;
+        }
+        default:
+            break;
+    }
+
+    return 0;
+}
+
+int main(int argc, char **argv)
+{
+    char *filename = NULL;
+    int fd = -1;
+    unsigned char *buf = NULL;
+    off_t offset = 0;
+    off_t bytes = 0;
+    e_state state = STARTING;
+    
+    if (argc != 2)
+    {
+        printf("No filename specified! Try again...\n");
+        return EINVAL;
+    }
+    
+    filename = argv[1];
+    
+    fd = open(filename, O_RDONLY);
+    if (-1 == fd)
+    {
+        printf("Failed to open file %s, error %d!. Try again...\n", filename, errno);
+        return errno;
+    }
+
+    buf = malloc(BUF_SIZE);
+    if (!buf)
+    {
+        printf("Failed to malloc %d bytes. Abort!\n", BUF_SIZE);
+        return ENOMEM;
+    }
+
+    /* Find the beginning of the data - read the first chunk, including the header */
+    while (STARTING == state)
+    {
+        off_t start_offset = -1;
+
+        bytes = read(fd, buf, BUF_SIZE);
+        if (0 >= bytes)
+        {
+            state = DONE;
+            break;
+        }
+        start_offset = find_string(buf, bytes, "DATA");
+        if (start_offset >= 0)
+        {
+            offset += start_offset;
+            state = IN_DATA;
+            break;
+        }
+        offset += bytes;
+    }
+
+    while (DONE != state && ERROR != state)
+    {
+        off_t start_offset = -1;
+        lseek(fd, offset, SEEK_SET);
+        bytes = read(fd, buf, BUF_SIZE);
+        if (0 >= bytes)
+        {
+            state = ERROR;
+            break;
+        }
+        if (IN_DATA == state)
+        {
+            if (!find_string(buf, bytes, "DATA"))
+                state = IN_DATA;
+            if (!find_string(buf, bytes, "DESC"))
+                state = IN_DESC;
+        }
+        switch (state)
+        {
+            case IN_DATA:
+                start_offset = parse_data_block(offset, buf, bytes);
+                offset += start_offset;
+                break;
+            case IN_DESC:
+                start_offset = parse_desc_block(offset, buf, bytes);
+                offset += start_offset;
+                state = DUMP_DESC;
+                break;
+            case DUMP_DESC:
+                start_offset = parse_desc_data(offset, buf, bytes);
+                offset += start_offset;
+                if (0 == start_offset)
+                    state = DONE;
+                break;
+            default:
+                break;
+        }
+    }        
+    
+    close(fd);
+
+    return 0;
+}