⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gunzip65.c

📁 cc65 的编译器文档
💻 C
字号:
/* * gunzip65 - a gunzip utility for 6502-based machines. * * Piotr Fusik <fox@scene.pl> * * This should be considered as a test of my zlib-compatible library * rather than a real application. * It's not user-friendly, fault-tolerant, whatever. * However, it really works for real GZIP files, provided they are small * enough to fit in buffer[] (after decompression!). */#include <stdio.h>#include <string.h>#include <zlib.h>#ifndef __CC65__/* * Emulate inflatemem() if using original zlib. * As you can see, this program is quite portable. */unsigned inflatemem(char* dest, const char* source){	z_stream stream;	stream.next_in = (Bytef*) source;	stream.avail_in = 65535;	stream.next_out = dest;	stream.avail_out = 65535;	stream.zalloc = (alloc_func) 0;	stream.zfree = (free_func) 0;	inflateInit2(&stream, -MAX_WBITS);	inflate(&stream, Z_FINISH);	inflateEnd(&stream);	return stream.total_out;}#endif /* __CC65__ *//* * Structure of a GZIP file: * * 1. GZIP header: *    Offset 0: Signature (2 bytes: 0x1f, 0x8b) *    Offset 2: Compression method (1 byte: 8 == "deflate") *    Offset 3: Flags (1 byte: see below) *    Offset 4: File date and time (4 bytes) *    Offset 8: Extra flags (1 byte) *    Offset 9: Target OS (1 byte: DOS, Amiga, Unix, etc.) *    if (flags & FEXTRA) { 2 bytes of length, then length bytes } *    if (flags & FNAME) { ASCIIZ filename } *    if (flags & FCOMMENT) { ASCIIZ comment } *    if (flags & FHCRC) { 2 bytes of CRC } * * 2. Deflate compressed data. * * 3. GZIP trailer: *    Offset 0: CRC-32 (4 bytes) *    Offset 4: uncompressed file length (4 bytes) *//* Flags in the GZIP header. */#define FTEXT     1	/* Extra text */#define FHCRC     2	/* Header CRC */#define FEXTRA    4	/* Extra field */#define FNAME     8	/* File name */#define FCOMMENT 16	/* File comment *//* * We read whole GZIP file into this buffer. * Then we use this buffer for the decompressed data. */static unsigned char buffer[26000];/* * Get a 16-bit little-endian unsigned number, using unsigned char* p. * On many machines this could be (*(unsigned short*) p), * but I really like portability. :-) */#define GET_WORD(p) (*(p) + ((unsigned) (p)[1] << 8))/* Likewise, for a 32-bit number. */#define GET_LONG(p) (GET_WORD(p) + ((unsigned long) GET_WORD(p + 2) << 16))/* * Uncompress a GZIP file. * On entry, buffer[] should contain the whole GZIP file contents, * and the argument complen should be equal to the length of the GZIP file. * On return, buffer[] contains the uncompressed data, and the returned * value is the length of the uncompressed data. */unsigned uncompress_buffer(unsigned complen){	unsigned char* ptr;	unsigned long crc;	unsigned long unclen;	void* ptr2;	unsigned unclen2;	/* check GZIP signature */	if (buffer[0] != 0x1f || buffer[1] != 0x8b) {		puts("Not GZIP format");		return 0;	}	/* check compression method (it is always (?) "deflate") */	if (buffer[2] != 8) {		puts("Unsupported compression method");		return 0;	}	/* get CRC from GZIP trailer */	crc = GET_LONG(buffer + complen - 8);	/* get uncompressed length from GZIP trailer */	unclen = GET_LONG(buffer + complen - 4);	if (unclen > sizeof(buffer)) {		puts("Uncompressed size too big");		return 0;	}	/* skip extra field, file name, comment and crc */	ptr = buffer + 10;	if (buffer[3] & FEXTRA)		ptr = buffer + 12 + GET_WORD(buffer + 10);	if (buffer[3] & FNAME)		while (*ptr++ != 0);	if (buffer[3] & FCOMMENT)		while (*ptr++ != 0);	if (buffer[3] & FHCRC)		ptr += 2;	/*	 * calculate length of raw "deflate" data	 * (without the GZIP header and 8-byte trailer)	 */	complen -= (ptr - buffer) + 8;	/*	 * We will move the compressed data to the end of buffer[].	 * Thus the compressed data and the decompressed data (written from	 * the beginning of buffer[]) may overlap, as long as the decompressed	 * data doesn't go further than unread compressed data.	 * ptr2 points to the beginning of compressed data at the end	 * of buffer[].	 */	ptr2 = buffer + sizeof(buffer) - complen;	/* move the compressed data to end of buffer[] */	memmove(ptr2, ptr, complen);	/* uncompress */	puts("Inflating...");	unclen2 = inflatemem(buffer, ptr2);	/* verify uncompressed length */	if (unclen2 != (unsigned) unclen) {		puts("Uncompressed size does not match");		return 0;	}	/* verify CRC */	puts("Calculating CRC...");	if (crc32(crc32(0L, Z_NULL, 0), buffer, unclen2) != crc) {		puts("CRC mismatch");		return 0;	}	/* return number of uncompressed bytes */	return unclen2;}/* * Get a filename from standard input. */char* get_fname(void){	static char filename[100];	unsigned len;	fgets(filename, sizeof(filename), stdin);	len = strlen(filename);	if (len >= 1 && filename[len - 1] == '\n')		filename[len - 1] = '\0';	return filename;}int main(void){	FILE* fp;	unsigned length;	/* read GZIP file */	puts("GZIP file name:");	fp = fopen(get_fname(), "rb");	if (!fp) {		puts("Can't open GZIP file");		return 1;	}	length = fread(buffer, 1, sizeof(buffer), fp);	fclose(fp);	if (length == sizeof(buffer)) {		puts("File is too long");		return 1;	}	/* decompress */	length = uncompress_buffer(length);	if (length == 0)		return 1;	/* write uncompressed file */	puts("Uncompressed file name:");	fp = fopen(get_fname(), "wb");	if (!fp) {		puts("Can't create output file");		return 1;	}	if (fwrite(buffer, 1, length, fp) != length) {		puts("Error while writing output file");		return 1;	}	fclose(fp);	puts("Ok.");	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -