diff -u --recursive --new-file linux-1.2.11/drivers/block/Makefile linux/drivers/block/Makefile
--- linux-1.2.11/drivers/block/Makefile	Sun Jul 16 20:46:04 1995
+++ linux/drivers/block/Makefile	Sun Jul 16 20:48:00 1995
@@ -21,8 +21,8 @@
 # In the future, some of these should be built conditionally.
 #
 
-OBJS := ll_rw_blk.o ramdisk.o genhd.o 
-SRCS := ll_rw_blk.c ramdisk.c genhd.c 
+OBJS := ll_rw_blk.o rd.o rd_gz_inflate.o rd_gz_unzip.o genhd.o 
+SRCS := ll_rw_blk.c rd.c rd_gz_inflate.c rd_gz_unzip.c genhd.c 
 BLOCK_MODULE_OBJS =
 
 ifdef CONFIG_BLK_DEV_FD
diff -u --recursive --new-file linux-1.2.11/drivers/block/README.ramdisk linux/drivers/block/README.ramdisk
--- linux-1.2.11/drivers/block/README.ramdisk	Wed Dec 31 17:00:00 1969
+++ linux/drivers/block/README.ramdisk	Sun Jul 16 20:48:00 1995
@@ -0,0 +1,34 @@
+New RAMDISK driver README
+-------------------------
+
+	This improved version of the ramdisk driver contains two major 
+enhancements to the older ramdisk driver :
+
+	1.  It supports gzipped ramdisk images.  This, for example, makes 
+the standard 1.44MB rootdisk shipped with Slackware 2.2 take up only 544K 
+of disk space.  This feature can be used easily by gziping a standard 
+rootdisk (or creating a larger one in a ramdisk), and copying it down to 
+the floppy.
+
+	This can be extremely useful for certain rare situations (like if 
+you only have a 720K disk to put a rootdisk on - using this ramdisk 
+driver, you can put a full rootdisk on it...)
+
+(TODO:  Make the gzip loader read at 384K and 512K into the disk, so a 
+kernel and a rootdisk can both be used.)
+
+	2.  It also supports multiple ramdisk devices (referencing 
+straight to the buffer cache).  A buffer protection scheme has been added 
+to the buffer.c system, which should keep the buffers safe.
+
+	You can create the devices by doing :
+
+	mknod /dev/ramX b 33 X
+
+	(X is the minor number - it can be up to 255.  Note that minor #0 
+can be the static ramdisk as well, so I suggest that it not be mknoded.)
+	
+	Enjoy!
+
+	- Chad Page
+	 (cpage@best.com)
diff -u --recursive --new-file linux-1.2.11/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- linux-1.2.11/drivers/block/ll_rw_blk.c	Sun Jul 16 20:46:04 1995
+++ linux/drivers/block/ll_rw_blk.c	Sun Jul 16 20:49:26 1995
@@ -21,6 +21,24 @@
 #include <asm/io.h>
 #include "blk.h"
 
+/* The following #define, when uncommented, adds a penalty to the current
+   processes priority (actually, it's dynamic count variable), which should
+   discourage excessive i/o... it only does anything when it gets to low-level
+   code, since the buffers go pretty fast anyway...
+
+   These changes do *nothing* if COUNTER_DEC is not defined.
+*/
+
+/* #define COUNTER_DEC */
+
+#ifdef COUNTER_DEC
+	#define COUNTER_DEC_BLOCK 50
+	#define COUNTER_DEC_PAGE 200
+#else
+	#define COUNTER_DEC_BLOCK 0
+	#define COUNTER_DEC_PAGE 0
+#endif
+
 /*
  * The request-struct contains all necessary data
  * to load a nr of sectors into memory
@@ -422,6 +440,11 @@
 		printk("Can't page to read-only device 0x%X\n",dev);
 		return;
 	}
+
+	current->counter -= COUNTER_DEC_PAGE;
+	if (current->counter < 0) 
+		current->counter = 0;
+
 	req = get_request_wait(NR_REQUEST, dev);
 /* fill up the request-info, and add it to the queue */
 	req->cmd = rw;
@@ -489,6 +512,13 @@
 		goto sorry;
 	}
 
+	/* At this point, let's change current->counter so the program won't go 
+      	   straight for the block device again - if things are loaded... */
+
+	current->counter -= COUNTER_DEC_BLOCK;
+	if (current->counter < 0) 	
+		current->counter = 0; 
+
 	/* If there are no pending requests for this device, then we insert
 	   a dummy request for that device.  This will prevent the request
 	   from starting until we have shoved all of the blocks into the
@@ -597,7 +627,6 @@
 #ifdef CONFIG_SBPCD
 	mem_start = sbpcd_init(mem_start, mem_end);
 #endif CONFIG_SBPCD
-	if (ramdisk_size)
-		mem_start += rd_init(mem_start, ramdisk_size*1024);
+	mem_start += rd_init(mem_start, ramdisk_size*1024);
 	return mem_start;
 }
diff -u --recursive --new-file linux-1.2.11/drivers/block/rd.c linux/drivers/block/rd.c
--- linux-1.2.11/drivers/block/rd.c	Wed Dec 31 17:00:00 1969
+++ linux/drivers/block/rd.c	Sun Jul 16 20:48:00 1995
@@ -0,0 +1,613 @@
+/*
+ *  ramdisk.c - Multiple ramdisk driver - gzip-loading version - v. 0.8 beta.
+ * 
+ *  (C) Chad Page et. al, 1995. 
+ *
+ *  This ramdisk is designed to have filesystems created on it and mounted
+ *  just like a regular floppy disk.  
+ *  
+ *  It also does something suggested by Linus : use the buffer cache as the
+ *  ramdisk data.  This makes it possible to dynamically allocate the ramdisk
+ *  buffer - with some consequences I have to deal with as I write this. 
+ *
+ *  This version is bimodal in that it supports BOTH static allocation and
+ *  dynamic allocation.  I added that because of unforseen bugs (as in, it
+ *  wouldn't boot!), and I've used a mmap call to do this.
+ *  
+ *  Based on the original ramdisk.c, written mostly by Theodore Ts'o in 1991.
+ * 
+ *  The gzip loader is self-activating, and automatically switches between
+ *  the two loading methods on whether or not get_method says it's a gzip file
+ *  or not (note : this isin't a clean printout yet!) 
+ *
+ */
+
+#include <linux/config.h>
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+
+static char kernel_version[] = UTS_RELEASE;
+#endif
+#define DEVICE_NAME "ramdisk"
+#define DEVICE_REQUEST rd_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#include <linux/sched.h>
+#include <linux/minix_fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/malloc.h>
+#include <linux/ioctl.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+
+extern void wait_for_keypress(void);
+
+#define MAJOR_NR 33 /* This is an official major number */
+
+#ifdef MODULE
+	#include "/usr/src/linux/drivers/block/blk.h"
+#else
+	#include "blk.h"
+	#define BUILD_CRAMDISK
+
+	void rd_load(void);
+	int crd_load(struct inode *finode, struct file * fflip);
+#endif
+
+/* Various static variables go here... mostly used within the ramdisk code only. */
+
+unsigned long rd_addr[256] = {0, };
+
+int rd_length[256];
+int rd_blocksizes[256] = {1024, };
+
+/* This is the size of the rootdisk-loading ramdisk.  If it is 0, don't load 
+   the rootdisk... */
+
+int rd_param; 
+
+/*
+ *  Basically, my strategy here is to set up a buffer-head which can't be
+ *  deleted, and make that my Ramdisk.  If the request is outside of the
+ *  allocated size, we must get rid of it...
+ *
+ */
+
+static void rd_request(void)
+{
+	unsigned int minor;
+	int offset, len;
+
+repeat:
+	INIT_REQUEST;
+	
+	minor = MINOR(CURRENT->dev);	
+
+	if ((rd_addr[minor] < 4096) && (minor == 0)) {
+		end_request(0);
+		goto repeat;
+	}
+
+	offset = CURRENT->sector << 9;
+	len = CURRENT->current_nr_sectors << 9;	
+	
+	if ((offset + len) > rd_length[minor]) {
+		end_request(0);
+		goto repeat;
+	}
+
+	if (rd_addr[minor] < 4096) /* This is a buffer-cache-disk */
+	{
+		if (CURRENT->cmd == READ)
+		{	
+			memset(CURRENT->buffer, 0, len); 
+		}
+		CURRENT->bh->b_prot = 1;
+	}
+	else /* Conventional ramdisk */
+	{
+		if (CURRENT->cmd == READ)
+		{
+			memcpy(CURRENT->buffer, (char *)(rd_addr[minor] + offset), len);
+		}
+		if (CURRENT->cmd == WRITE)
+		{
+			memcpy((char *)(rd_addr[minor] + offset), CURRENT->buffer, len);
+		}
+	}
+	end_request(1);
+	goto repeat;
+} 
+
+/* The implementation of BLKFLSBUF is stolen from ide.c.  Hopefully it's
+   a good hack... */
+
+static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	if (!inode || !inode->i_rdev) 	
+		return -EINVAL;
+
+	switch (cmd) {
+		case BLKFLSBUF:
+			if (!suser()) return -EACCES;
+			fsync_dev(inode->i_rdev);
+			invalidate_buffers(inode->i_rdev);
+			break;
+		default:
+			break;
+	};
+
+	return 0;
+}
+
+static struct file_operations fd_fops = {
+	NULL,		/* lseek - default */
+	block_read,	/* read - block dev write */
+	block_write,	/* write - block dev write */
+	NULL,		/* readdir - not here! */
+	NULL,		/* select */
+	rd_ioctl, 	/* ioctl */
+	NULL,		/* mmap */
+	NULL,		/* no special open code... there should be! */
+	NULL,		/* no special release code... */
+	block_fsync		/* fsync */ 
+};
+
+/* This is the registration and initialization section of the ramdisk driver */
+
+int main_rd_init(void)
+{
+	int count;
+
+	if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) {
+		printk("RAMDISK2 : Could not get major %d", MAJOR_NR);
+		return -EIO;
+	}
+
+	blk_dev[MAJOR_NR].request_fn = &rd_request;
+
+	for (count = 0; count < 256; count++) {
+		rd_length[count] = (16384 * 1024);
+		rd_blocksizes[count] = 1024;
+	}
+
+	blksize_size[MAJOR_NR] = rd_blocksizes;
+
+	return 0;
+}
+
+/* Module init */
+#ifdef MODULE
+int init_module(void)
+{
+	return main_rd_init();
+}
+
+void cleanup_module(void)
+{
+	unregister_blkdev(MAJOR_NR, "ramdisk");
+}
+#else
+/* Non-modular init... */ 
+
+long rd_init(long mem_start, int length)
+{
+	main_rd_init();
+
+	rd_param = length;	
+	rd_addr[0] = mem_start;
+	rd_length[0] = length;
+
+	return length;
+}
+#endif
+/* This is the non-modular section of the driver.  This is changed
+   from the original in that the ramdisk blindly loads from block 0 without
+   a filesystem check.  Peter Anvin told me that he and Linus agreed that it
+   was no longer necessary, and that it took up space (which I am using to
+   write all these comments :)
+
+   As usual, I am trying to maintain compatibility with the older ramdisk in
+   the function calls used by the other parts of the kernel, to prevent
+   kernel patching.
+
+   This code is diabled when this is compiled into modular form.
+*/
+
+#ifndef MODULE
+
+void rd_load()
+{
+	struct inode inode;
+	struct file flip;
+	int device;
+
+	device = ROOT_DEV;
+
+	printk(KERN_NOTICE "VFS: Insert ramdisk floppy and press ENTER\n");
+	wait_for_keypress();
+
+	if (MAJOR(device) != FLOPPY_MAJOR) return;
+
+	memset(&flip, 0, sizeof(flip));
+	memset(&inode, 0, sizeof(inode));
+	inode.i_rdev = device;
+	flip.f_mode = 1; /* read only */
+	flip.f_inode = &inode;
+
+	if (blkdev_open(&inode, &flip) != 0) return;
+
+#ifdef BUILD_CRAMDISK
+	if (crd_load(&inode, &flip) == 1) { 
+		if (flip.f_op -> release) flip.f_op -> release(&inode, &flip);
+		return;
+	}
+
+	if (flip.f_op -> lseek) flip.f_op -> lseek(&inode, &flip, 0, 0);
+#endif
+
+	/* Now, copy the data... */
+
+	flip.f_op -> read(&inode, &flip, (char *)rd_addr[0], rd_param);
+
+	if (flip.f_op -> release) flip.f_op -> release(&inode, &flip);
+
+	invalidate_buffers(ROOT_DEV);
+	ROOT_DEV = (MAJOR_NR << 8);  
+}
+
+#ifdef BUILD_CRAMDISK
+
+/*
+ *  From linux/kernel/blk_drv/cramdisk.c
+ *
+ *  Written/adapted by Richard Lyons, 1FEB94, and hacked by Chad Page Apr. 95
+ *  to work with the new ramdisk driver. 
+ *
+ *  Parts of this file are copyright Jean-loup Gailly.
+ *  Parts of this file are not copyright Mark Adler.
+ *
+ */
+
+#include <linux/rd_gz_gzip.h>
+#include <linux/rd_gz_lzw.h>
+
+#define EOF		-1 
+
+DECLARE(uch, inbuf, INBUFSIZ);
+unsigned char *outbuf;
+DECLARE(uch, window, WSIZE);
+DECLARE(ulg, crc_32_tab, 256);
+
+#define fcalloc(a,b)	malloc((a) * (b))
+#define fcfree(p)	free(p)
+#define to_stdout	0
+
+unsigned int	insize;
+unsigned int	inptr;
+
+unsigned char	*output_data;
+unsigned long	output_ptr;
+unsigned int	outcnt;
+
+int		method, exit_code, part_nb, last_member;
+int		test = 0;
+int		force = 0;
+int		verbose = 1;
+long		bytes_out;
+
+void		makecrc(void);
+void		allocbufs(void);
+void		freebufs(void);
+local int	get_method(int in);
+void		(*work)(int inf, int outf);
+
+struct inode *inode;
+struct file *flip;
+
+/*
+ *  Unlike cramdisk, I use get_method to decide whether or not the rootdisk
+ *  is gzipped, and if it is I go here...
+ */
+
+int crd_load(struct inode * finode, struct file * fflip)
+{
+    inode = finode;
+    flip = fflip; 
+
+    exit_code = OK;
+    test = 0;
+    part_nb = 0;
+    allocbufs();
+    clear_bufs();
+    makecrc();
+    method = get_method(0);
+    if (method < 0)
+    {
+    	printk("RAMDISK : gzip header not found - continuing with conventional load.\n");
+	return 0;
+    }
+    printk("RAMDISK : starting gunzip of rootdisk image... ");
+    work(0, 0);
+    printk("done.\n");
+    freebufs();
+    invalidate_buffers(ROOT_DEV);
+    if (exit_code == OK)
+	ROOT_DEV = (MAJOR_NR << 8);
+    return 1;
+}
+
+void
+allocbufs(void)
+{
+    ALLOC(uch, inbuf, INBUFSIZ); 
+    outbuf = (unsigned char *)rd_addr[0];
+    ALLOC(uch, window, WSIZE);
+    ALLOC(ulg, crc_32_tab, 256);
+}
+
+void
+freebufs(void)
+{
+    FREE(crc_32_tab);
+    FREE(window);
+    FREE(inbuf);
+}
+
+
+/* ===========================================================================
+ * Clear input and output buffers
+ */
+void clear_bufs()
+{
+    output_data = (unsigned char *)rd_addr[0];
+    outcnt = output_ptr = 0;
+    insize = inptr = 0;
+    bytes_out = 0L;
+}
+
+/*
+ * Code to compute the CRC-32 table. Borrowed from 
+ * gzip-1.0.3/makecrc.c.
+ */
+
+void
+makecrc(void)
+{
+/* Not copyrighted 1990 Mark Adler	*/
+
+  unsigned long c;      /* crc shift register */
+  unsigned long e;      /* polynomial exclusive-or pattern */
+  int i;                /* counter for all possible eight bit values */
+  int k;                /* byte being shifted into crc apparatus */
+
+  /* terms of polynomial defining this crc (except x^32): */
+  static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+  /* Make exclusive-or pattern from polynomial */
+  e = 0;
+  for (i = 0; i < sizeof(p)/sizeof(int); i++)
+    e |= 1L << (31 - p[i]);
+
+  crc_32_tab[0] = 0;
+
+  for (i = 1; i < 256; i++)
+  {
+    c = 0;
+    for (k = i | 256; k != 1; k >>= 1)
+    {
+      c = c & 1 ? (c >> 1) ^ e : c >> 1;
+      if (k & 1)
+        c ^= e;
+    }
+    crc_32_tab[i] = c;
+  }
+}
+
+/* ===========================================================================
+ * Run a set of bytes through the crc shift register.  If s is a NULL
+ * pointer, then initialize the crc shift register contents instead.
+ * Return the current crc in either case.
+ */
+ulg updcrc(s, n)
+    uch *s;                 /* pointer to bytes to pump through */
+    unsigned n;             /* number of bytes in s[] */
+{
+    register ulg c;         /* temporary variable */
+
+    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
+
+    if (s == NULL) {
+	c = 0xffffffffL;
+    } else {
+	c = crc;
+	while (n--) {
+	    c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
+	}
+    }
+    crc = c;
+    return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
+}
+
+void
+error(char *s)
+{
+    printk("%s", s);
+    exit_code = ERROR;
+}
+
+/* ========================================================================
+ * Check the magic number of the input file and update ofname if an
+ * original name was given and to_stdout is not set.
+ * Return the compression method, -1 for error, -2 for warning.
+ * Set inptr to the offset of the next byte to be processed.
+ * This function may be called repeatedly for an input file consisting
+ * of several contiguous gzip'ed members.
+ * IN assertions: there is at least one remaining compressed member.
+ *   If the member is a zip file, it must be the only one.
+ */
+local int get_method(in)
+    int in;        /* input file descriptor */
+{
+    uch flags;
+    char magic[2]; /* magic header */
+
+    magic[0] = (char)get_byte();
+    magic[1] = (char)get_byte();
+
+    method = -1;                 /* unknown yet */
+    part_nb++;                   /* number of parts in gzip file */
+    last_member = 0;
+    /* assume multiple members in gzip file except for record oriented I/O */
+
+    if (memcmp(magic, GZIP_MAGIC, 2) == 0
+        || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
+
+	work = unzip;
+	method = (int)get_byte();
+	flags  = (uch)get_byte();
+	if ((flags & ENCRYPTED) != 0) {
+	    error("Input is encrypted\n");
+	    exit_code = ERROR;
+	    return -1;
+	}
+	if ((flags & CONTINUATION) != 0) {
+	       error("Multi part input\n");
+	    exit_code = ERROR;
+	    if (force <= 1) return -1;
+	}
+	if ((flags & RESERVED) != 0) {
+	    error("Input has invalid flags\n");
+	    exit_code = ERROR;
+	    if (force <= 1) return -1;
+	}
+	inptr += 6;
+
+	if ((flags & CONTINUATION) != 0) {
+	    unsigned part = (unsigned)get_byte();
+	    part |= ((unsigned)get_byte())<<8;
+	    if (verbose) {
+		error("Input is not part number 1\n");
+	    }
+	}
+	if ((flags & EXTRA_FIELD) != 0) {
+	    unsigned len = (unsigned)get_byte();
+	    len |= ((unsigned)get_byte())<<8;
+	    while (len--) (void)get_byte();
+	}
+
+	/* Get original file name if it was truncated */
+	if ((flags & ORIG_NAME) != 0) {
+	    if (to_stdout || part_nb > 1) {
+		/* Discard the old name */
+		while (get_byte() != 0) /* null */ ;
+	    } else {
+
+/* You won't believe how long not having this line in messed me up...
+   in the gzip loader used by the kernel and cramdisk, it does not take
+   into account the original file name, causing me literally hours of grief
+   until I reverse-engineered gzip-1.0.3 from my Linux CD set to figure out
+   how my gzip adaption was broken... then I put this line in, and presto!
+ */
+		 while (get_byte() != 0);
+	    } /* to_stdout */
+	} /* orig_name */
+
+	/* Discard file comment if any */
+	if ((flags & COMMENT) != 0) {
+	    while (get_byte() != 0) /* null */ ;
+	}
+
+    } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
+	    && memcmp(inbuf, PKZIP_MAGIC, 4) == 0) {
+	/* To simplify the code, we support a zip file when alone only.
+         * We are thus guaranteed that the entire local header fits in inbuf.
+         */
+        inptr = 0;
+	work = unzip;
+	if (check_zipfile(in) == -1) return -1;
+	/* check_zipfile may get ofname from the local header */
+	last_member = 1;
+
+    } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
+    	error("packed input");
+    } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
+	error("compressed input");
+	last_member = 1;
+    }
+    if (method == -1) {
+	error("Corrupted input\n");
+	if (exit_code != ERROR) exit_code = part_nb == 1 ? ERROR : WARNING;
+	return part_nb == 1 ? -1 : -2;
+    }
+
+    return method;
+}
+
+/* I made this a real function while trying to debug this.  It isin't needed,
+and will go away in alpha 4/beta-test 1. */
+
+int get_byte(void)
+{
+	if (inptr < insize) {
+		return inbuf[inptr++];
+	}
+	else
+		return fill_inbuf();
+}
+
+int
+fill_inbuf(void)
+{
+	if (exit_code != OK) return EOF;
+
+	insize = flip -> f_op -> read(inode, flip, inbuf, INBUFSIZ);
+	if (insize == 0) return EOF;
+
+	inptr = 1;
+
+	return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+void flush_window()
+{
+    if (outcnt == 0)
+	return;
+    if ((output_ptr + outcnt) > rd_length[0])
+	error("CRAMDISK: compressed image too long\n");
+    else {
+	updcrc(window, outcnt);
+
+	memcpy(output_data + output_ptr, (char *)window, outcnt);
+
+	bytes_out += (ulg)outcnt;
+	output_ptr += (ulg)outcnt;
+    }
+    outcnt = 0;
+}
+
+
+typedef struct {
+	unsigned long	start;
+	unsigned long	pages;
+} chain;
+
+#define	MAX_MISSES (PAGE_SIZE/sizeof(chain))
+
+#endif
+
+#endif /* Non-modular portions */
+
diff -u --recursive --new-file linux-1.2.11/drivers/block/rd_gz_inflate.c linux/drivers/block/rd_gz_inflate.c
--- linux-1.2.11/drivers/block/rd_gz_inflate.c	Wed Dec 31 17:00:00 1969
+++ linux/drivers/block/rd_gz_inflate.c	Sun Jul 16 20:48:01 1995
@@ -0,0 +1,812 @@
+#define DEBG(x)
+#define DEBG1(x)
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+   version c10p1, 10 January 1993 */
+
+/* 
+ * Adapted for booting Linux by Hannu Savolainen 1993
+ * based on gzip-1.0.3 
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: inflate.c,v 0.10 1993/02/04 13:21:06 jloup Exp $";
+#endif
+
+#include <linux/malloc.h>
+
+#include <linux/rd_gz_gzip.h>
+#define slide window
+
+#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
+#  include <sys/types.h>
+#  include <stdlib.h>
+#endif
+
+struct huft {
+  uch e;                /* number of extra bits or operation */
+  uch b;                /* number of bits in this code or subcode */
+  union {
+    ush n;              /* literal, length base, or distance base */
+    struct huft *t;     /* pointer to next level of table */
+  } v;
+};
+
+
+/* Function prototypes */
+int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
+                   struct huft **, int *));
+int huft_free OF((struct huft *));
+int inflate_codes OF((struct huft *, struct huft *, int, int));
+int inflate_stored OF((void));
+int inflate_fixed OF((void));
+int inflate_dynamic OF((void));
+int inflate_block OF((int *));
+int inflate OF((void));
+
+
+#define wp outcnt
+#define flush_output(w) (wp=(w),flush_window())
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static unsigned border[] = {    /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ush cplens[] = {         /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* note: see note #13 above about the 258 in this list. */
+static ush cplext[] = {         /* Extra bits for literal codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
+static ush cpdist[] = {         /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+static ush cpdext[] = {         /* Extra bits for distance codes */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+
+ulg bb;                         /* bit buffer */
+unsigned bk;                    /* bits in bit buffer */
+
+ush mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#ifdef CRYPT
+  uch cc;
+#  define NEXTBYTE() \
+     (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
+#else
+#  define NEXTBYTE()  (uch)get_byte()
+#endif
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+int lbits = 9;          /* bits in base literal/length lookup table */
+int dbits = 6;          /* bits in base distance lookup table */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16         /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288       /* maximum number of codes in any set */
+
+
+unsigned hufts;         /* track memory usage */
+
+
+int huft_build(b, n, s, d, e, t, m)
+unsigned *b;            /* code lengths in bits (all assumed <= BMAX) */
+unsigned n;             /* number of codes (assumed <= N_MAX) */
+unsigned s;             /* number of simple-valued codes (0..s-1) */
+ush *d;                 /* list of base values for non-simple codes */
+ush *e;                 /* list of extra bits for non-simple codes */
+struct huft **t;        /* result: starting table */
+int *m;                 /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return zero on success, one if
+   the given code set is incomplete (the tables are still built in this
+   case), two if the input is invalid (all zero length codes or an
+   oversubscribed set of lengths), and three if not enough memory. */
+{
+  unsigned a;                   /* counter for codes of length k */
+  unsigned c[BMAX+1];           /* bit length count table */
+  unsigned f;                   /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register unsigned i;          /* counter, current code */
+  register unsigned j;          /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  register unsigned *p;         /* pointer into c[], b[], or v[] */
+  register struct huft *q;      /* points to current table */
+  struct huft r;                /* table entry for structure assignment */
+  struct huft *u[BMAX];         /* table stack */
+  unsigned v[N_MAX];            /* values in order of bit length */
+  register int w;               /* bits before this table == (l * h) */
+  unsigned x[BMAX+1];           /* bit offsets, then code stack */
+  unsigned *xp;                 /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  unsigned z;                   /* number of entries in current table */
+
+DEBG("huft1 ");
+
+  /* Generate counts for each bit length */
+  memzero(c, sizeof(c));
+  p = b;  i = n;
+  do {
+    c[*p++]++;                  /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (struct huft *)NULL;
+    *m = 0;
+    return 0;
+  }
+
+DEBG("huft2 ");
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((unsigned)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((unsigned)l > i)
+    l = i;
+  *m = l;
+
+DEBG("huft3 ");
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return 2;                 /* bad input: more codes than bits */
+  if ((y -= c[i]) < 0)
+    return 2;
+  c[i] += y;
+
+DEBG("huft4 ");
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+DEBG("huft5 ");
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+
+DEBG("h6 ");
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */
+  q = (struct huft *)NULL;      /* ditto */
+  z = 0;                        /* ditto */
+DEBG("h6a ");
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+DEBG("h6b ");
+    a = c[k];
+    while (a--)
+    {
+DEBG("h6b1 ");
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+DEBG1("1 ");
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = (z = g - w) > (unsigned)l ? l : z;  /* upper limit on table size */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+DEBG1("2 ");
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          while (++j < z)       /* try smaller tables up to z bits */
+          {
+            if ((f <<= 1) <= *++xp)
+              break;            /* enough codes to use up j bits */
+            f -= *xp;           /* else deduct codes from patterns */
+          }
+        }
+DEBG1("3 ");
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate and link in new table */
+        q = (struct huft *)malloc((z + 1)*sizeof(struct huft));
+DEBG1("4 ");
+        hufts += z + 1;         /* track memory usage */
+        *t = q + 1;             /* link to list for huft_free() */
+        *(t = &(q->v.t)) = (struct huft *)NULL;
+        u[h] = ++q;             /* table starts after link */
+
+DEBG1("5 ");
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.b = (uch)l;         /* bits to dump before this table */
+          r.e = (uch)(16 + j);  /* bits in this table */
+          r.v.t = q;            /* pointer to this table */
+          j = i >> (w - l);     /* (get around Turbo C bug) */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+DEBG1("6 ");
+      }
+DEBG("h6c ");
+
+      /* set up table entry in r */
+      r.b = (uch)(k - w);
+      if (p >= v + n)
+        r.e = 99;               /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.e = (uch)(*p < 256 ? 16 : 15);    /* 256 is end-of-block code */
+        r.v.n = *p++;           /* simple code is just the value */
+      }
+      else
+      {
+        r.e = (uch)e[*p - s];   /* non-simple--look up in lists */
+        r.v.n = d[*p++ - s];
+      }
+DEBG("h6d ");
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      while ((i & ((1 << w) - 1)) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+      }
+DEBG("h6e ");
+    }
+DEBG("h6f ");
+  }
+
+DEBG("huft7 ");
+
+  /* Return true (1) if we were given an incomplete table */
+  return y != 0 && g != 1;
+}
+
+
+
+int huft_free(t)
+struct huft *t;         /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+   list of the tables it made, with the links in a dummy first entry of
+   each table. */
+{
+  register struct huft *p, *q;
+
+
+  /* Go through linked list, freeing from the malloced (t[-1]) address. */
+  p = t;
+  while (p != (struct huft *)NULL)
+  {
+    q = (--p)->v.t;
+    free(p);
+    p = q;
+  } 
+  return 0;
+}
+
+
+int inflate_codes(tl, td, bl, bd)
+struct huft *tl, *td;   /* literal/length and distance decoder tables */
+int bl, bd;             /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+   Return an error code or zero if it all goes ok. */
+{
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned ml, md;      /* masks for bl and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local copies of globals */
+  b = bb;                       /* initialize bit buffer */
+  k = bk;
+  w = wp;                       /* initialize window position */
+
+  /* inflate the coded data */
+  ml = mask_bits[bl];           /* precompute masks for speed */
+  md = mask_bits[bd];
+  for (;;)                      /* do until end of block */
+  {
+    NEEDBITS((unsigned)bl)
+    if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+      do {
+        if (e == 99)
+          return 1;
+        DUMPBITS(t->b)
+        e -= 16;
+        NEEDBITS(e)
+      } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+    DUMPBITS(t->b)
+    if (e == 16)                /* then it's a literal */
+    {
+      slide[w++] = (uch)t->v.n;
+      if (w == WSIZE)
+      {
+        flush_output(w);
+        w = 0;
+      }
+    }
+    else                        /* it's an EOB or a length */
+    {
+      /* exit if end of block */
+      if (e == 15)
+        break;
+
+      /* get length of block to copy */
+      NEEDBITS(e)
+      n = t->v.n + ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e);
+
+      /* decode distance of block to copy */
+      NEEDBITS((unsigned)bd)
+      if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      NEEDBITS(e)
+      d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e)
+
+      /* do the copy */
+      do {
+        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+#if !defined(NOMEMCPY) && !defined(DEBUG)
+        if (w - d >= e)         /* (this test assumes unsigned comparison) */
+        {
+          memcpy(slide + w, slide + d, e);
+          w += e;
+          d += e;
+        }
+        else                      /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+          do {
+            slide[w++] = slide[d++];
+          } while (--e);
+        if (w == WSIZE)
+        {
+          flush_output(w);
+          w = 0;
+        }
+      } while (n);
+    }
+  }
+
+
+  /* restore the globals from the locals */
+  wp = w;                       /* restore global window pointer */
+  bb = b;                       /* restore global bit buffer */
+  bk = k;
+
+  /* done */
+  return 0;
+}
+
+
+
+int inflate_stored()
+/* "decompress" an inflated type 0 (stored) block. */
+{
+  unsigned n;           /* number of bytes in block */
+  unsigned w;           /* current window position */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+DEBG("<stor");
+
+  /* make local copies of globals */
+  b = bb;                       /* initialize bit buffer */
+  k = bk;
+  w = wp;                       /* initialize window position */
+
+
+  /* go to byte boundary */
+  n = k & 7;
+  DUMPBITS(n);
+
+
+  /* get the length and its complement */
+  NEEDBITS(16)
+  n = ((unsigned)b & 0xffff);
+  DUMPBITS(16)
+  NEEDBITS(16)
+  if (n != (unsigned)((~b) & 0xffff))
+    return 1;                   /* error in compressed data */
+  DUMPBITS(16)
+
+
+  /* read and output the compressed data */
+  while (n--)
+  {
+    NEEDBITS(8)
+    slide[w++] = (uch)b;
+    if (w == WSIZE)
+    {
+      flush_output(w);
+      w = 0;
+    }
+    DUMPBITS(8)
+  }
+
+
+  /* restore the globals from the locals */
+  wp = w;                       /* restore global window pointer */
+  bb = b;                       /* restore global bit buffer */
+  bk = k;
+
+  DEBG(">");
+  return 0;
+}
+
+
+
+int inflate_fixed()
+/* decompress an inflated type 1 (fixed Huffman codes) block.  We should
+   either replace this with a custom decoder, or at least precompute the
+   Huffman tables. */
+{
+  int i;                /* temporary variable */
+  struct huft *tl;      /* literal/length code table */
+  struct huft *td;      /* distance code table */
+  int bl;               /* lookup bits for tl */
+  int bd;               /* lookup bits for td */
+  unsigned l[288];      /* length list for huft_build */
+
+DEBG("<fix");
+
+  /* set up literal table */
+  for (i = 0; i < 144; i++)
+    l[i] = 8;
+  for (; i < 256; i++)
+    l[i] = 9;
+  for (; i < 280; i++)
+    l[i] = 7;
+  for (; i < 288; i++)          /* make a complete, but wrong code set */
+    l[i] = 8;
+  bl = 7;
+  if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
+    return i;
+
+
+  /* set up distance table */
+  for (i = 0; i < 30; i++)      /* make an incomplete code set */
+    l[i] = 5;
+  bd = 5;
+  if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
+  {
+    huft_free(tl);
+
+    DEBG(">");
+    return i;
+  }
+
+
+  /* decompress until an end-of-block code */
+  if (inflate_codes(tl, td, bl, bd))
+    return 1;
+
+
+  /* free the decoding tables, return */
+  huft_free(tl);
+  huft_free(td);
+  return 0;
+}
+
+
+
+int inflate_dynamic()
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+  int i;                /* temporary variables */
+  unsigned j;
+  unsigned l;           /* last length */
+  unsigned m;           /* mask for bit lengths table */
+  unsigned n;           /* number of lengths to get */
+  struct huft *tl;      /* literal/length code table */
+  struct huft *td;      /* distance code table */
+  int bl;               /* lookup bits for tl */
+  int bd;               /* lookup bits for td */
+  unsigned nb;          /* number of bit length codes */
+  unsigned nl;          /* number of literal/length codes */
+  unsigned nd;          /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+  unsigned ll[288+32];  /* literal/length and distance code lengths */
+#else
+  unsigned ll[286+30];  /* literal/length and distance code lengths */
+#endif
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+DEBG("<dyn");
+
+  /* make local bit buffer */
+  b = bb;
+  k = bk;
+
+
+  /* read in table lengths */
+  NEEDBITS(5)
+  nl = 257 + ((unsigned)b & 0x1f);      /* number of literal/length codes */
+  DUMPBITS(5)
+  NEEDBITS(5)
+  nd = 1 + ((unsigned)b & 0x1f);        /* number of distance codes */
+  DUMPBITS(5)
+  NEEDBITS(4)
+  nb = 4 + ((unsigned)b & 0xf);         /* number of bit length codes */
+  DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+  if (nl > 288 || nd > 32)
+#else
+  if (nl > 286 || nd > 30)
+#endif
+    return 1;                   /* bad lengths */
+
+DEBG("dyn1 ");
+
+  /* read in bit-length-code lengths */
+  for (j = 0; j < nb; j++)
+  {
+    NEEDBITS(3)
+    ll[border[j]] = (unsigned)b & 7;
+    DUMPBITS(3)
+  }
+  for (; j < 19; j++)
+    ll[border[j]] = 0;
+
+DEBG("dyn2 ");
+
+  /* build decoding table for trees--single level, 7 bit lookup */
+  bl = 7;
+  if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
+  {
+    if (i == 1)
+      huft_free(tl);
+    return i;                   /* incomplete code set */
+  }
+
+DEBG("dyn3 ");
+
+  /* read in literal and distance code lengths */
+  n = nl + nd;
+  m = mask_bits[bl];
+  i = l = 0;
+  while ((unsigned)i < n)
+  {
+    NEEDBITS((unsigned)bl)
+    j = (td = tl + ((unsigned)b & m))->b;
+    DUMPBITS(j)
+    j = td->v.n;
+    if (j < 16)                 /* length of code in bits (0..15) */
+      ll[i++] = l = j;          /* save last length in l */
+    else if (j == 16)           /* repeat last length 3 to 6 times */
+    {
+      NEEDBITS(2)
+      j = 3 + ((unsigned)b & 3);
+      DUMPBITS(2)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = l;
+    }
+    else if (j == 17)           /* 3 to 10 zero length codes */
+    {
+      NEEDBITS(3)
+      j = 3 + ((unsigned)b & 7);
+      DUMPBITS(3)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = 0;
+      l = 0;
+    }
+    else                        /* j == 18: 11 to 138 zero length codes */
+    {
+      NEEDBITS(7)
+      j = 11 + ((unsigned)b & 0x7f);
+      DUMPBITS(7)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = 0;
+      l = 0;
+    }
+  }
+
+DEBG("dyn4 ");
+
+  /* free decoding table for trees */
+  huft_free(tl);
+
+DEBG("dyn5 ");
+
+  /* restore the global bit buffer */
+  bb = b;
+  bk = k;
+
+DEBG("dyn5a ");
+
+  /* build the decoding tables for literal/length and distance codes */
+  bl = lbits;
+  if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
+  {
+DEBG("dyn5b ");
+    if (i == 1) {
+      error(" incomplete literal tree\n");
+      huft_free(tl);
+    }
+    return i;                   /* incomplete code set */
+  }
+DEBG("dyn5c ");
+  bd = dbits;
+  if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
+  {
+DEBG("dyn5d ");
+    if (i == 1) {
+      error(" incomplete distance tree\n");
+#ifdef PKZIP_BUG_WORKAROUND
+      i = 0;
+    }
+#else
+      huft_free(td);
+    }
+    huft_free(tl);
+    return i;                   /* incomplete code set */
+#endif
+  }
+
+DEBG("dyn6 ");
+
+  /* decompress until an end-of-block code */
+  if (inflate_codes(tl, td, bl, bd))
+    return 1;
+
+DEBG("dyn7 ");
+
+  /* free the decoding tables, return */
+  huft_free(tl);
+  huft_free(td);
+
+  DEBG(">");
+  return 0;
+}
+
+
+
+int inflate_block(e)
+int *e;                 /* last block flag */
+/* decompress an inflated block */
+{
+  unsigned t;           /* block type */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+  DEBG("<blk");
+
+  /* make local bit buffer */
+  b = bb;
+  k = bk;
+
+
+  /* read in last block bit */
+  NEEDBITS(1)
+  *e = (int)b & 1;
+  DUMPBITS(1)
+
+
+  /* read in block type */
+  NEEDBITS(2)
+  t = (unsigned)b & 3;
+  DUMPBITS(2)
+
+
+  /* restore the global bit buffer */
+  bb = b;
+  bk = k;
+
+  /* inflate that block type */
+  if (t == 2)
+    return inflate_dynamic();
+  if (t == 0)
+    return inflate_stored();
+  if (t == 1)
+    return inflate_fixed();
+
+  DEBG(">");
+
+  /* bad block type */
+  return 2;
+}
+
+
+
+int inflate()
+/* decompress an inflated entry */
+{
+  int e;                /* last block flag */
+  int r;                /* result code */
+  unsigned h;           /* maximum struct huft's malloc'ed */
+
+
+  /* initialize window, bit buffer */
+  wp = 0;
+  bk = 0;
+  bb = 0;
+
+
+  /* decompress until the last block */
+  h = 0;
+  do {
+    hufts = 0;
+    if ((r = inflate_block(&e)) != 0)
+      return r;
+    if (hufts > h)
+      h = hufts;
+  } while (!e);
+
+  /* Undo too much lookahead. The next read will be byte aligned so we
+   * can discard unused bits in the last meaningful byte.
+   */
+  while (bk >= 8) {
+    bk -= 8;
+    inptr--;
+  }
+
+  /* flush out slide */
+  flush_output(wp);
+
+
+  /* return success */
+#ifdef DEBUG
+  fprintf(stderr, "<%u> ", h);
+#endif /* DEBUG */
+  return 0;
+}
diff -u --recursive --new-file linux-1.2.11/drivers/block/rd_gz_unzip.c linux/drivers/block/rd_gz_unzip.c
--- linux-1.2.11/drivers/block/rd_gz_unzip.c	Wed Dec 31 17:00:00 1969
+++ linux/drivers/block/rd_gz_unzip.c	Sun Jul 16 20:48:01 1995
@@ -0,0 +1,185 @@
+/* unzip.c -- decompress files in gzip or pkzip format.
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ *
+ * Adapted for Linux booting by Hannu Savolainen 1993
+ *
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ *
+ * The code in this file is derived from the file funzip.c written
+ * and put in the public domain by Mark Adler.
+ */
+
+/*
+   This version can extract files in gzip or pkzip format.
+   For the latter, only the first entry is extracted, and it has to be
+   either deflated or stored.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: unzip.c,v 0.9 1993/02/10 16:07:22 jloup Exp $";
+#endif
+
+#include <linux/malloc.h>
+#include <linux/kernel.h>
+
+#include <linux/rd_gz_gzip.h>
+#include <linux/rd_gz_crypt.h>
+
+#include <stdio.h>
+
+/* PKZIP header definitions */
+#define LOCSIG 0x04034b50L      /* four-byte lead-in (lsb first) */
+#define LOCFLG 6                /* offset of bit flag */
+#define  CRPFLG 1               /*  bit for encrypted entry */
+#define  EXTFLG 8               /*  bit for extended local header */
+#define LOCHOW 8                /* offset of compression method */
+#define LOCTIM 10               /* file mod time (for decryption) */
+#define LOCCRC 14               /* offset of crc */
+#define LOCSIZ 18               /* offset of compressed size */
+#define LOCLEN 22               /* offset of uncompressed length */
+#define LOCFIL 26               /* offset of file name field length */
+#define LOCEXT 28               /* offset of extra field length */
+#define LOCHDR 30               /* size of local header, including sig */
+#define EXTHDR 16               /* size of extended local header, inc sig */
+
+
+/* Globals */
+
+int decrypt;      /* flag to turn on decryption */
+char *key;        /* not used--needed to link crypt.c */
+int pkzip = 0;    /* set for a pkzip file */
+int extended = 0; /* set if extended local header */
+
+/* ===========================================================================
+ * Check zip file and advance inptr to the start of the compressed data.
+ * Get ofname from the local header if necessary.
+ */
+int check_zipfile(in)
+    int in;   /* input file descriptors */
+{
+    uch *h = inbuf + inptr; /* first local header */
+
+    /* ifd = in; */
+
+    /* Check validity of local header, and skip name and extra fields */
+    inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT);
+
+    if (inptr > insize || LG(h) != LOCSIG) {
+	error("input not a zip");
+    }
+    method = h[LOCHOW];
+    if (method != STORED && method != DEFLATED) {
+	error("first entry not deflated or stored--can't extract");
+    }
+
+    /* If entry encrypted, decrypt and validate encryption header */
+    if ((decrypt = h[LOCFLG] & CRPFLG) != 0) {
+	error("encrypted file\n");
+	exit_code = ERROR;
+	return -1;
+    }
+
+    /* Save flags for unzip() */
+    extended = (h[LOCFLG] & EXTFLG) != 0;
+    pkzip = 1;
+
+    /* Get ofname and time stamp from local header (to be done) */
+    return 0;
+}
+
+/* ===========================================================================
+ * Unzip in to out.  This routine works on both gzip and pkzip files.
+ *
+ * IN assertions: the buffer inbuf contains already the beginning of
+ *   the compressed data, from offsets inptr to insize-1 included.
+ *   The magic header has already been checked. The output buffer is cleared.
+ */
+void unzip(in, out)
+    int in, out;   /* input and output file descriptors */
+{
+    ulg orig_crc = 0;       /* original crc */
+    ulg orig_len = 0;       /* original uncompressed length */
+    int n;
+    uch buf[EXTHDR];        /* extended local header */
+
+    /* ifd = in;
+    ofd = out; */
+
+    updcrc(NULL, 0);           /* initialize crc */
+
+    if (pkzip && !extended) {  /* crc and length at the end otherwise */
+	orig_crc = LG(inbuf + LOCCRC);
+	orig_len = LG(inbuf + LOCLEN);
+    }
+
+    printk("%d\n", inptr); 
+
+    /* Decompress */
+    if (method == DEFLATED)  {
+
+	int res = inflate();
+
+	if (res == 3) {
+	    error("out of memory");
+	} else if (res != 0) {
+	    error("invalid compressed format");
+	}
+
+    } else if (pkzip && method == STORED) {
+
+	register ulg n = LG(inbuf + LOCLEN);
+
+	if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) {
+
+	    error("length mismatch");
+	}
+	while (n--) {
+	    uch c = (uch)get_byte();
+#ifdef CRYPT
+	    if (decrypt) zdecode(c);
+#endif
+	    if (!test) put_char(c);
+	}
+    } else {
+	error("internal error, invalid method");
+    }
+
+    /* Get the crc and original length */
+    if (!pkzip) {
+        /* crc32  (see algorithm.doc)
+	 * uncompressed input size modulo 2^32
+         */
+	for (n = 0; n < 8; n++) {
+	    buf[n] = (uch)get_byte(); /* may cause an error if EOF */
+	}
+	orig_crc = LG(buf);
+	orig_len = LG(buf+4);
+
+    } else if (extended) {  /* If extended header, check it */
+	/* signature - 4bytes: 0x50 0x4b 0x07 0x08
+	 * CRC-32 value
+         * compressed size 4-bytes
+         * uncompressed size 4-bytes
+	 */
+	for (n = 0; n < EXTHDR; n++) {
+	    buf[n] = (uch)get_byte(); /* may cause an error if EOF */
+	}
+	orig_crc = LG(buf+4);
+	orig_len = LG(buf+12);
+    }
+
+    /* Validate decompression */
+    if (orig_crc != updcrc(outbuf, 0)) {
+	error("crc error");
+    }
+    if (orig_len != bytes_out) {
+	error("length error");
+    }
+
+    /* Check if there are more entries in a pkzip file */
+    if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
+	    error("zip file has more than one entry");
+    }
+    extended = pkzip = 0; /* for next file */
+}
diff -u --recursive --new-file linux-1.2.11/fs/buffer.c linux/fs/buffer.c
--- linux-1.2.11/fs/buffer.c	Sun Jul 16 20:46:16 1995
+++ linux/fs/buffer.c	Sun Jul 16 20:48:01 1995
@@ -185,7 +185,7 @@
 			 if (!bh->b_dirt || pass>=2)
 				  continue;
 			 /* don't bother about locked buffers */
-			 if (bh->b_lock)
+			 if (bh->b_lock || bh->b_prot)
 				 continue;
 			 bh->b_count++;
 			 bh->b_flushtime = 0;
@@ -262,6 +262,8 @@
 		for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; bh = bh->b_next_free) {
 			if (bh->b_dev != dev)
 				continue;
+			if (bh->b_prot)
+				continue;	
 			wait_on_buffer(bh);
 			if (bh->b_dev != dev)
 				continue;
@@ -563,7 +565,7 @@
 				 continue;
 			 };
 			 
-			 if (bh->b_count || bh->b_size != size)
+			 if (bh->b_prot || bh->b_count || bh->b_size != size)
 				  continue;
 			 
 			 /* Buffers are written in the order they are placed 
@@ -605,6 +607,8 @@
 		if(candidate[i] == bh) candidate[i] = NULL;  /* Got last one */
 		if (bh->b_count || bh->b_size != size)
 			 panic("Busy buffer in candidate list\n");
+		if (bh->b_prot)
+			panic ("Protected buffer in candidate list\n");	
 		if (mem_map[MAP_NR((unsigned long) bh->b_data)] != 1)
 			 panic("Shared buffer in candidate list\n");
 		if (BADNESS(bh)) panic("Buffer in candidate list with BADNESS != 0\n");
@@ -634,7 +638,7 @@
 					continue;
 				};
 				
-				if (bh->b_count || bh->b_size != size)
+				if (bh->b_prot || bh->b_count || bh->b_size != size)
 					 continue;
 				
 				/* Buffers are written in the order they are
@@ -1064,6 +1068,7 @@
 	while (1) {
 		arr[block++] = bh;
 		bh->b_count = 1;
+		bh->b_prot = 0;	
 		bh->b_dirt = 0;
 		bh->b_flushtime = 0;
 		bh->b_uptodate = 0;
@@ -1233,7 +1238,7 @@
 	do {
 		if (!tmp)
 			return 0;
-		if (tmp->b_count || tmp->b_dirt || tmp->b_lock || tmp->b_wait)
+		if (tmp->b_prot || tmp->b_count || tmp->b_dirt || tmp->b_lock || tmp->b_wait)
 			return 0;
 		tmp = tmp->b_this_page;
 	} while (tmp != bh);
@@ -1347,7 +1352,7 @@
 		bh = free_list[isize];
 		if(!bh) continue;
 		for (i=0 ; !i || bh != free_list[isize]; bh = bh->b_next_free, i++) {
-			if (bh->b_count || !bh->b_this_page)
+			if (bh->b_count || bh->b_prot || !bh->b_this_page)
 				 continue;
 			if (try_to_free(bh, &bh))
 				 return 1;
@@ -1367,7 +1372,7 @@
 		for ( ; i-- > 0 ; bh = bh->b_next_free) {
 			/* We may have stalled while waiting for I/O to complete. */
 			if(bh->b_list != nlist) goto repeat1;
-			if (bh->b_count || !bh->b_this_page)
+			if (bh->b_prot || bh->b_count || !bh->b_this_page)
 				 continue;
 			if(size && bh->b_size != size) continue;
 			if (bh->b_lock)
@@ -1396,7 +1401,7 @@
 void show_buffers(void)
 {
 	struct buffer_head * bh;
-	int found = 0, locked = 0, dirty = 0, used = 0, lastused = 0;
+	int found = 0, locked = 0, protected = 0, dirty = 0, used = 0, lastused = 0;
 	int shared;
 	int nlist, isize;
 
@@ -1405,13 +1410,15 @@
 	printk("Buffer blocks:   %6d\n",nr_buffers);
 
 	for(nlist = 0; nlist < NR_LIST; nlist++) {
-	  shared = found = locked = dirty = used = lastused = 0;
+	  shared = found = locked = dirty = used = protected = lastused = 0;
 	  bh = lru_list[nlist];
 	  if(!bh) continue;
 	  do {
 		found++;
 		if (bh->b_lock)
 			locked++;
+		if (bh->b_prot)
+			protected++;
 		if (bh->b_dirt)
 			dirty++;
 		if(mem_map[MAP_NR(((unsigned long) bh->b_data))] !=1) shared++;
@@ -1419,8 +1426,8 @@
 			used++, lastused = found;
 		bh = bh->b_next_free;
 	      } while (bh != lru_list[nlist]);
-	printk("Buffer[%d] mem: %d buffers, %d used (last=%d), %d locked, %d dirty %d shrd\n",
-		nlist, found, used, lastused, locked, dirty, shared);
+	printk("Buffer[%d] mem: %d buffers, %d used (last=%d), %d locked, %d protected %d dirty %d shrd\n",
+		nlist, found, used, lastused, locked, protected, dirty, shared);
 	};
 	printk("Size    [LAV]     Free  Clean  Unshar     Lck    Lck1   Dirty  Shared\n");
 	for(isize = 0; isize<NR_SIZES; isize++){
@@ -1453,8 +1460,7 @@
 	do {
 		if (!tmp)
 			 return 0;
-		
-		if (tmp->b_count || tmp->b_dirt || tmp->b_lock)
+		if (tmp->b_prot || tmp->b_count || tmp->b_dirt || tmp->b_lock)
 			 return 0;
 		tmp = tmp->b_this_page;
 	} while (tmp != bh);
@@ -1548,6 +1554,7 @@
 		bh->b_dirt = 0;
 		bh->b_flushtime = 0;
 		bh->b_lock = 0;
+		bh->b_prot = 0;
 		bh->b_uptodate = 0;
 		bh->b_req = 0;
 		bh->b_dev = dev;
@@ -1719,7 +1726,7 @@
 					  continue;
 				  }
 				 
-				 if (bh->b_lock || !bh->b_dirt)
+				 if (bh->b_lock || !bh->b_dirt || bh->b_prot)
 					  continue;
 				 ndirty++;
 				 if(bh->b_flushtime > jiffies) continue;
diff -u --recursive --new-file linux-1.2.11/include/linux/fs.h linux/include/linux/fs.h
--- linux-1.2.11/include/linux/fs.h	Sun Jul 16 20:46:21 1995
+++ linux/include/linux/fs.h	Sun Jul 16 20:48:01 1995
@@ -136,6 +136,7 @@
 	unsigned short b_count;		/* users using this block */
 	unsigned char b_uptodate;
 	unsigned char b_dirt;		/* 0-clean,1-dirty */
+	unsigned char b_prot;		/* 0-regular,1-protected */
 	unsigned char b_lock;		/* 0 - ok, 1 -locked */
 	unsigned char b_req;		/* 0 if the buffer has been invalidated */
 	unsigned char b_list;		/* List that this buffer appears */
diff -u --recursive --new-file linux-1.2.11/include/linux/rd_gz_crypt.h linux/include/linux/rd_gz_crypt.h
--- linux-1.2.11/include/linux/rd_gz_crypt.h	Wed Dec 31 17:00:00 1969
+++ linux/include/linux/rd_gz_crypt.h	Sun Jul 16 20:48:01 1995
@@ -0,0 +1,12 @@
+/* crypt.h (dummy version) -- do not perform encryption
+ * Hardly worth copyrighting :-)
+ */
+
+#ifdef CRYPT
+#  undef CRYPT      /* dummy version */
+#endif
+
+#define RAND_HEAD_LEN  12  /* length of encryption random header */
+
+#define zencode
+#define zdecode
diff -u --recursive --new-file linux-1.2.11/include/linux/rd_gz_gzip.h linux/include/linux/rd_gz_gzip.h
--- linux-1.2.11/include/linux/rd_gz_gzip.h	Wed Dec 31 17:00:00 1969
+++ linux/include/linux/rd_gz_gzip.h	Sun Jul 16 20:48:01 1995
@@ -0,0 +1,278 @@
+/* gzip.h -- common declarations for all gzip modules
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if defined(__STDC__) || defined(PROTO)
+#  define OF(args)  args
+#else
+#  define OF(args)  ()
+#endif
+
+#ifdef __STDC__
+   typedef void *voidp;
+#else
+   typedef char *voidp;
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+#define memzero(s, n) memset((s), 0, (n))
+#define malloc(size) kmalloc(size, GFP_KERNEL)
+#define free(ptr) kfree_s((ptr), 0)
+
+#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
+#  include <memory.h>
+#endif
+
+#ifndef RETSIGTYPE
+#  define RETSIGTYPE void
+#endif
+
+#define local static
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+/* Return codes from gzip */
+#define OK      0
+#define ERROR   1
+#define WARNING 2
+
+/* Compression methods (see algorithm.doc) */
+#define STORED     0
+#define COMPRESSED 1
+#define PACKED     2
+/* methods 3 to 7 reserved */
+#define DEFLATED   8
+extern int method;         /* compression method */
+
+/* To save memory for 16 bit systems, some arrays are overlayed between
+ * the various modules:
+ * deflate:  prev+head   window      d_buf  l_buf  outbuf
+ * unlzw:    tab_prefix  tab_suffix  stack  inbuf  outbuf
+ * inflate:              window             inbuf
+ * unpack:               window             inbuf
+ * For compression, input is done in window[]. For decompression, output
+ * is done in window except for unlzw.
+ */
+
+#ifndef	INBUFSIZ
+#  define INBUFSIZ  0x800  /* input buffer size */
+#endif
+#define INBUF_EXTRA  64     /* required by unlzw() */
+
+#ifndef	OUTBUFSIZ
+#  define OUTBUFSIZ  0x800000  /* output buffer size */
+#endif
+#define OUTBUF_EXTRA 2048   /* required by unlzw() */
+
+#define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
+
+#ifdef DYN_ALLOC
+#  define EXTERN(type, array)  extern type * near array
+#  define DECLARE(type, array, size)  type * near array
+#  define ALLOC(type, array, size) { \
+      array = (type*)fcalloc((unsigned)(((size)+1L)/2), 2*sizeof(type)); \
+      if (array == NULL) error("insufficient memory"); \
+   }
+#  define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
+#else
+#  define EXTERN(type, array)  extern type array[]
+#  define DECLARE(type, array, size)  type array[size]
+#  define ALLOC(type, array, size)
+#  define FREE(array)
+#endif
+
+EXTERN(uch, inbuf);
+extern unsigned char * outbuf;
+EXTERN(ush, d_buf);          /* buffer for distances, see trees.c */
+EXTERN(uch, window);         /* Sliding window and suffix table (unlzw) */
+#define tab_suffix window
+#ifndef MAXSEG_64K
+#  define tab_prefix prev    /* hash link (see deflate.c) */
+#  define head (prev+WSIZE)  /* hash head (see deflate.c) */
+   EXTERN(ush, tab_prefix);  /* prefix code (see unlzw.c) */
+#else
+#  define tab_prefix0 prev
+#  define head tab_prefix1
+   EXTERN(ush, tab_prefix0); /* prefix for even codes */
+   EXTERN(ush, tab_prefix1); /* prefix for odd  codes */
+#endif
+
+extern unsigned insize; /* valid bytes in inbuf */
+extern unsigned inptr;  /* index of next byte to be processed in inbuf */
+extern unsigned outcnt; /* bytes in output buffer */
+
+extern long bytes_in;   /* number of input bytes */
+extern long bytes_out;  /* number of output bytes */
+extern long overhead;   /* number of bytes in gzip header */
+
+#define isize bytes_in
+/* for compatibility with old zip sources (to be cleaned) */
+
+extern int  ifd;        /* input file descriptor */
+extern int  ofd;        /* output file descriptor */
+extern char ifname[];   /* input filename or "stdin" */
+extern char ofname[];   /* output filename or "stdout" */
+
+extern ulg time_stamp;  /* original time stamp (modification time) */
+extern long ifile_size; /* input file size, -1 for devices (debug only) */
+
+extern int exit_code;   /* program exit code */
+
+typedef int file_t;     /* Do not use stdio */
+#define NO_FILE  (-1)   /* in memory compression */
+
+
+#define	GZIP_MAGIC     "\037\213" /* Magic header for gzip files, 1F 8B */
+#define	OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
+#define	PKZIP_MAGIC  "PK\003\004" /* Magic header for pkzip files */
+#define	PACK_MAGIC     "\037\036" /* Magic header for packed files */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+/* internal file attribute */
+#define UNKNOWN (-1)
+#define BINARY  0
+#define ASCII   1
+
+#ifndef WSIZE
+#  define WSIZE 0x8000     /* window size--must be a power of two, and */
+#endif                     /*  at least 32K for zip's deflate method */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST  (WSIZE-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+extern int decrypt;        /* flag to turn on decryption */
+extern int save_orig_name; /* set if original name must be saved */
+extern int verbose;        /* be verbose (-v) */
+extern int level;          /* compression level */
+extern int test;           /* check .z file integrity */
+extern int to_stdout;      /* output to stdout (-c) */
+
+extern int get_byte(void); 
+
+/* put_byte is used for the compressed output, put_char for the
+ * uncompressed output. However unlzw() uses window for its
+ * suffix table instead of its output buffer, so it does not use put_char.
+ * (to be cleaned up).
+ */
+#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
+   flush_outbuf();}
+#define put_char(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\
+   flush_window();}
+
+/* Output a 16 bit value, lsb first */
+#define put_short(w) \
+{ if (outcnt < OUTBUFSIZ-2) { \
+    outbuf[outcnt++] = (uch) ((w) & 0xff); \
+    outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \
+  } else { \
+    put_byte((uch)((w) & 0xff)); \
+    put_byte((uch)((ush)(w) >> 8)); \
+  } \
+}
+
+/* Output a 32 bit value to the bit stream, lsb first */
+#define put_long(n) { \
+    put_short((n) & 0xffff); \
+    put_short(((ulg)(n)) >> 16); \
+}
+
+#define seekable()    0  /* force sequential output */
+#define translate_eol 0  /* no option -a yet */
+
+#define tolow(c)  (isupper(c) ? (c)-'A'+'a' : (c))    /* force to lower case */
+
+/* Macros for getting two-byte and four-byte header values */
+#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
+#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+	/* in zip.c: */
+extern void zip    OF((int in, int out));
+extern int file_read  OF((char *buf,  unsigned size));
+
+	/* in unzip.c */
+extern void unzip        OF((int in, int out));
+extern int check_zipfile OF((int in));
+
+	/* in unpack.c */
+extern void unpack        OF((int in, int out));
+
+	/* in gzip.c */
+RETSIGTYPE abort_gzip   OF((void));
+
+        /* in deflate.c */
+void lm_init OF((int pack_level, ush *flags));
+ulg  deflate OF((void));
+
+        /* in trees.c */
+void ct_init     OF((ush *attr, int *method));
+int  ct_tally    OF((int dist, int lc));
+ulg  flush_block OF((char *buf, ulg stored_len, int eof));
+
+        /* in bits.c */
+void     bi_init    OF((file_t zipfile));
+void     send_bits  OF((int value, int length));
+unsigned bi_reverse OF((unsigned value, int length));
+void     bi_windup  OF((void));
+void     copy_block OF((char *buf, unsigned len, int header));
+extern   int (*read_buf) OF((char *buf, unsigned size));
+
+	/* in util.c: */
+extern ulg  updcrc        OF((uch *s, unsigned n));
+extern void clear_bufs    OF((void));
+extern int  fill_inbuf    OF((void));
+extern void flush_outbuf  OF((void));
+extern void flush_window  OF((void));
+extern char *strlwr       OF((char *s));
+extern char *basename     OF((char *fname));
+extern char *add_envopt   OF((int *argcp, char ***argvp, char *env));
+extern void error         OF((char *m));
+extern void warn          OF((char *a, char *b));
+extern void read_error    OF((void));
+extern void write_error   OF((void));
+extern void display_ratio OF((long num, long den));
+extern voidp xmalloc      OF((unsigned int size));
+
+	/* in inflate.c */
+extern int inflate OF((void));
diff -u --recursive --new-file linux-1.2.11/include/linux/rd_gz_lzw.h linux/include/linux/rd_gz_lzw.h
--- linux-1.2.11/include/linux/rd_gz_lzw.h	Wed Dec 31 17:00:00 1969
+++ linux/include/linux/rd_gz_lzw.h	Sun Jul 16 20:48:01 1995
@@ -0,0 +1,42 @@
+/* lzw.h -- define the lzw functions.
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if !defined(OF) && defined(lint)
+#  include "gzip.h"
+#endif
+
+#ifndef BITS
+#  define BITS 16
+#endif
+#define INIT_BITS 9              /* Initial number of bits per code */
+
+#define	LZW_MAGIC  "\037\235"   /* Magic header for lzw files, 1F 9D */
+
+#define BIT_MASK    0x1f /* Mask for 'number of compression bits' */
+/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
+ * It's a pity that old uncompress does not check bit 0x20. That makes
+ * extension of the format actually undesirable because old compress
+ * would just crash on the new format instead of giving a meaningful
+ * error message. It does check the number of bits, but it's more
+ * helpful to say "unsupported format, get a new version" than
+ * "can only handle 16 bits".
+ */
+
+#define BLOCK_MODE  0x80
+/* Block compression: if table is full and compression rate is dropping,
+ * clear the dictionary.
+ */
+
+#define LZW_RESERVED 0x60 /* reserved bits */
+
+#define	CLEAR  256       /* flush the dictionary */
+#define FIRST  (CLEAR+1) /* first free entry */
+
+extern int maxbits;      /* max bits per code for LZW */
+extern int block_mode;   /* block compress mode -C compatible with 2.0 */
+
+extern void lzw    OF((int in, int out));
+extern void unlzw  OF((int in, int out));
