/*
 *  extract-gzip.c
 *  
 *  Simple usage: Pass filenames as arguments to the program.
 *  It will scan through them, looking for the gzip magic. If
 *  found, it will extract the gzipped file to either the filename
 *  provided in the gzip header, or if that doesn't exist, it will
 *  save it to a file named after the offset where it was found.
 *
 *  Created by Steve White on Fri Nov 15 2002
 *  Updated by Steve White on Wed Feb 05 2003
 *
 *  Copyright (c) 2002-2003 Steve White. All rights reserved.
 *
 */

#include <stdio.h>
#include <sys/fcntl.h>

static void usage(char *progname);
void extractgzip(int input);

int main(int argc, char *argv[]) {
	int input;
	int i=0;

	if (argc < 2) {
		usage(argv[0]);
		exit(1);
	}

	for (i=1; i<argc; i++) {
		input = open(argv[i], O_RDONLY);
		if (input == -1) {
			fprintf(stderr, "Error: Unable to open %s for reading\n", argv[i]);
		} else {
			extractgzip(input);
			close(input);
		}
	}
}

static void usage(char *progname) {
	printf("Usage: %s [FILE]...\n"
		"Extract gzip files from FILE(s)\n", progname);
}


void extractgzip(int input) {
	unsigned long cmp=0, offset=-1;
	unsigned char data;
	char filename[255], buffer[32768];
	int output, read_size;

	while (read(input, &data, 1) == 1) {
		cmp = cmp << 8 | data;
		if ( (cmp & 0xffffff00) == 0x1f8b0800) {
			offset = lseek(input, 0, SEEK_CUR) - 4;
			if ( (cmp & 0xff) == 8) {
				lseek(input, offset+10, SEEK_SET);
				read(input, &filename, 252);
				sprintf(filename, "%s.gz", filename);
			} else {
				sprintf(filename, "0x%08x.gz", offset);
			}

			output = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0666);
			if (output == -1) {
				fprintf(stderr, "Error: Unable to open %s for writing\n", filename);
				return;
			}

			fprintf(stderr, "gzip magic (0x%08x) detected at 0x%08x - saving to file %s\n", cmp, offset, filename);

			lseek(input, offset, SEEK_SET);
			while ((read_size = read(input, buffer, sizeof(buffer))) != 0) {
				write(output, buffer, (unsigned int)read_size);
			}
			close(output);

			break;
		}
	}
}
