+++ /dev/null
-#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;
-}