diff -r -c -N linux/.config linux993l/.config
*** linux/.config	Mon Dec 21 20:44:20 1992
--- linux993l/.config	Fri Jan 15 13:43:56 1993
***************
*** 26,33 ****
--- 26,37 ----
  # Filesystems
  #
  CONFIG_MINIX_FS = CONFIG_MINIX_FS
+ CONFIG_LINUX_FS = CONFIG_LINUX_FS
+ CONFIG_EXT_FS = CONFIG_EXT_FS
+ CONFIG_MSDOS_FS = CONFIG_MSDOS_FS
  CONFIG_PROC_FS = CONFIG_PROC_FS
  
  #
  # Various character device drivers..
  #
+ CONFIG_MS_BUSMOUSE = CONFIG_MS_BUSMOUSE
diff -r -c -N linux/.version linux993l/.version
*** linux/.version	Sun Dec 20 14:31:20 1992
--- linux993l/.version	Fri Jan 15 14:16:46 1993
***************
*** 1 ****
! 46
--- 1 ----
! 51
diff -r -c -N linux/Makefile linux993l/Makefile
*** linux/Makefile	Fri Jan  1 21:45:57 1993
--- linux993l/Makefile	Fri Jan 15 13:12:49 1993
***************
*** 13,19 ****
  # default of FLOPPY is used by 'build'.
  #
  
! ROOT_DEV = /dev/hdb1
  
  #
  # uncomment the correct keyboard:
--- 13,19 ----
  # default of FLOPPY is used by 'build'.
  #
  
! ROOT_DEV = /dev/hda2
  
  #
  # uncomment the correct keyboard:
***************
*** 32,40 ****
  # 0x08 - tilde (~)
  # 0x10 - dieresis (umlaut)
  
! KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
  # KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x9F
! # KEYBOARD = -DKBD_US -DKBDFLAGS=0
  # KEYBOARD = -DKBD_GR -DKBDFLAGS=0
  # KEYBOARD = -DKBD_GR_LATIN1 -DKBDFLAGS=0x9F
  # KEYBOARD = -DKBD_FR -DKBDFLAGS=0
--- 32,40 ----
  # 0x08 - tilde (~)
  # 0x10 - dieresis (umlaut)
  
! # KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0
  # KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x9F
! KEYBOARD = -DKBD_US -DKBDFLAGS=0
  # KEYBOARD = -DKBD_GR -DKBDFLAGS=0
  # KEYBOARD = -DKBD_GR_LATIN1 -DKBDFLAGS=0x9F
  # KEYBOARD = -DKBD_FR -DKBDFLAGS=0
***************
*** 56,62 ****
  # The number is the same as you would ordinarily press at bootup.
  #
  
! SVGA_MODE=	-DSVGA_MODE=1
  
  # 
  # Edit the SOUND_SUPPORT line to suit your setup if you have configured
--- 56,62 ----
  # The number is the same as you would ordinarily press at bootup.
  #
  
! SVGA_MODE=	-DSVGA_MODE=NORMAL_VGA
  
  # 
  # Edit the SOUND_SUPPORT line to suit your setup if you have configured
***************
*** 142,148 ****
  
  Version: dummy
  	@./makever.sh
! 	@echo \#define UTS_RELEASE \"0.99.pl2-`cat .version`\" > tools/version.h
  	@echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
  	@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
  	@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
--- 142,148 ----
  
  Version: dummy
  	@./makever.sh
! 	@echo \#define UTS_RELEASE \"0.99.pl3-`cat .version`\" > tools/version.h
  	@echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
  	@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
  	@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
diff -r -c -N linux/config.in linux993l/config.in
*** linux/config.in	Fri Jan  1 21:45:58 1993
--- linux993l/config.in	Fri Jan 15 13:04:51 1993
***************
*** 46,55 ****
  .
  Standard (minix) fs support
  CONFIG_MINIX_FS y/n y
  Extended fs support
! CONFIG_EXT_FS y/n n
  msdos fs support
! CONFIG_MSDOS_FS y/n n
  /proc filesystem support
  CONFIG_PROC_FS y/n y
  NFS filesystem support
--- 46,57 ----
  .
  Standard (minix) fs support
  CONFIG_MINIX_FS y/n y
+ Long Standard (linux) fs support
+ CONFIG_LINUX_FS y/n y
  Extended fs support
! CONFIG_EXT_FS y/n y
  msdos fs support
! CONFIG_MSDOS_FS y/n y
  /proc filesystem support
  CONFIG_PROC_FS y/n y
  NFS filesystem support
***************
*** 70,76 ****
  PS/2 mouse (aka 'auxiliary device') support
  CONFIG_PSMOUSE y/n n
  MicroSoft busmouse support
! CONFIG_MS_BUSMOUSE y/n n
  ATIXL busmouse support
  CONFIG_ATIXL_BUSMOUSE y/n n
  Soundcard support (not really there yet)
--- 72,78 ----
  PS/2 mouse (aka 'auxiliary device') support
  CONFIG_PSMOUSE y/n n
  MicroSoft busmouse support
! CONFIG_MS_BUSMOUSE y/n y
  ATIXL busmouse support
  CONFIG_ATIXL_BUSMOUSE y/n n
  Soundcard support (not really there yet)
diff -r -c -N linux/fs/Makefile linux993l/fs/Makefile
*** linux/fs/Makefile	Fri Dec 11 21:48:46 1992
--- linux993l/fs/Makefile	Fri Jan 15 14:12:58 1993
***************
*** 7,16 ****
  #
  # Note 2! The CFLAGS definitions are now in the main makefile...
  
! SUBDIRS = minix ext msdos proc isofs nfs
  
  ifdef CONFIG_MINIX_FS
  FS_SUBDIRS := $(FS_SUBDIRS) minix
  endif
  ifdef CONFIG_EXT_FS
  FS_SUBDIRS := $(FS_SUBDIRS) ext
--- 7,19 ----
  #
  # Note 2! The CFLAGS definitions are now in the main makefile...
  
! SUBDIRS = minix linux ext msdos proc isofs nfs
  
  ifdef CONFIG_MINIX_FS
  FS_SUBDIRS := $(FS_SUBDIRS) minix
+ endif
+ ifdef CONFIG_LINUX_FS
+ FS_SUBDIRS := $(FS_SUBDIRS) linux
  endif
  ifdef CONFIG_EXT_FS
  FS_SUBDIRS := $(FS_SUBDIRS) ext
diff -r -c -N linux/fs/filesystems.c linux993l/fs/filesystems.c
*** linux/fs/filesystems.c	Fri Dec 11 21:39:12 1992
--- linux993l/fs/filesystems.c	Fri Jan 15 13:02:04 1993
***************
*** 11,16 ****
--- 11,19 ----
  #ifdef CONFIG_MINIX_FS
  #include <linux/minix_fs.h>
  #endif
+ #ifdef CONFIG_LINUX_FS
+ #include <linux/linux_fs.h>
+ #endif
  #ifdef CONFIG_PROC_FS
  #include <linux/proc_fs.h>
  #endif
***************
*** 30,35 ****
--- 33,41 ----
  struct file_system_type file_systems[] = {
  #ifdef CONFIG_MINIX_FS
  	{minix_read_super,	"minix",	1},
+ #endif
+ #ifdef CONFIG_LINUX_FS
+ 	{linux_read_super,	"linux",	1},
  #endif
  #ifdef CONFIG_EXT_FS
  	{ext_read_super,	"ext",		1},
diff -r -c -N linux/fs/linux/Makefile linux993l/fs/linux/Makefile
*** linux/fs/linux/Makefile
--- linux993l/fs/linux/Makefile	Mon Jan 11 10:47:10 1993
***************
*** 0 ****
--- 1,34 ----
+ #
+ # Makefile for the linux linux-filesystem routines.
+ #
+ # Note! Dependencies are done automagically by 'make dep', which also
+ # removes any old dependencies. DON'T put your own dependencies here
+ # unless it's something special (ie not a .c file).
+ #
+ # Note 2! The CFLAGS definitions are now in the main makefile...
+ 
+ .c.s:
+ 	$(CC) $(CFLAGS) -S $<
+ .c.o:
+ 	$(CC) $(CFLAGS) -c $<
+ .s.o:
+ 	$(AS) -o $*.o $<
+ 
+ OBJS=	bitmap.o truncate.o namei.o inode.o \
+ 	file.o dir.o symlink.o blkdev.o chrdev.o fifo.o
+ 
+ linux.o: $(OBJS)
+ 	$(LD) -r -o linux.o $(OBJS)
+ 
+ clean:
+ 	rm -f core *.o *.a *.s
+ 
+ dep:
+ 	$(CPP) -M *.c > .depend
+ 
+ #
+ # include a dependency file if one exists
+ #
+ ifeq (.depend,$(wildcard .depend))
+ include .depend
+ endif
diff -r -c -N linux/fs/linux/bitmap.c linux993l/fs/linux/bitmap.c
*** linux/fs/linux/bitmap.c
--- linux993l/fs/linux/bitmap.c	Mon Jan 11 10:47:10 1993
***************
*** 0 ****
--- 1,234 ----
+ /*
+  *  linux/fs/linux/bitmap.c
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  */
+ 
+ /* bitmap.c contains the code that handles the inode and block bitmaps */
+ 
+ #include <linux/sched.h>
+ #include <linux/linux_fs.h>
+ #include <linux/stat.h>
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+ 
+ #define clear_block(addr) \
+ __asm__("cld\n\t" \
+ 	"rep\n\t" \
+ 	"stosl" \
+ 	::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
+ 
+ #define set_bit(nr,addr) ({\
+ char res; \
+ __asm__ __volatile__("btsl %1,%2\n\tsetb %0": \
+ "=q" (res):"r" (nr),"m" (*(addr))); \
+ res;})
+ 
+ #define clear_bit(nr,addr) ({\
+ char res; \
+ __asm__ __volatile__("btrl %1,%2\n\tsetnb %0": \
+ "=q" (res):"r" (nr),"m" (*(addr))); \
+ res;})
+ 
+ #define find_first_zero(addr) ({ \
+ int __res; \
+ __asm__("cld\n" \
+ 	"1:\tlodsl\n\t" \
+ 	"notl %%eax\n\t" \
+ 	"bsfl %%eax,%%edx\n\t" \
+ 	"jne 2f\n\t" \
+ 	"addl $32,%%ecx\n\t" \
+ 	"cmpl $8192,%%ecx\n\t" \
+ 	"jl 1b\n\t" \
+ 	"xorl %%edx,%%edx\n" \
+ 	"2:\taddl %%edx,%%ecx" \
+ 	:"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \
+ __res;})
+ 
+ static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
+ 
+ static unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
+ 	unsigned numbits)
+ {
+ 	unsigned i, j, end, sum = 0;
+ 	struct buffer_head *bh;
+   
+ 	for (i=0; (i<numblocks) && numbits; i++) {
+ 		if (!(bh=map[i])) 
+ 			return(0);
+ 		if (numbits >= (8*BLOCK_SIZE)) { 
+ 			end = BLOCK_SIZE;
+ 			numbits -= 8*BLOCK_SIZE;
+ 		} else {
+ 			int tmp;
+ 			end = numbits >> 3;
+ 			numbits &= 0x7;
+ 			tmp = bh->b_data[end] & ((1<<numbits)-1);
+ 			sum += nibblemap[tmp&0xf] + nibblemap[(tmp>>4)&0xf];
+ 			numbits = 0;
+ 		}  
+ 		for (j=0; j<end; j++)
+ 			sum += nibblemap[bh->b_data[j] & 0xf] 
+ 				+ nibblemap[(bh->b_data[j]>>4)&0xf];
+ 	}
+ 	return(sum);
+ }
+ 
+ void linux_free_block(struct super_block * sb, int block)
+ {
+ 	struct buffer_head * bh;
+ 	unsigned int bit,zone;
+ 
+ 	if (!sb) {
+ 		printk("trying to free block on nonexistent device\n");
+ 		return;
+ 	}
+ 	if (block < sb->u.linux_sb.s_firstdatazone ||
+ 	    block >= sb->u.linux_sb.s_nzones) {
+ 		printk("trying to free block not in datazone\n");
+ 		return;
+ 	}
+ 	bh = get_hash_table(sb->s_dev,block,BLOCK_SIZE);
+ 	if (bh)
+ 		bh->b_dirt=0;
+ 	brelse(bh);
+ 	zone = block - sb->u.linux_sb.s_firstdatazone + 1;
+ 	bit = zone & 8191;
+ 	zone >>= 13;
+ 	bh = sb->u.linux_sb.s_zmap[zone];
+ 	if (!bh) {
+ 		printk("linux_free_block: nonexistent bitmap buffer\n");
+ 		return;
+ 	}
+ 	if (clear_bit(bit,bh->b_data))
+ 		printk("free_block (%04x:%d): bit already cleared\n",sb->s_dev,block);
+ 	bh->b_dirt = 1;
+ 	return;
+ }
+ 
+ int linux_new_block(struct super_block * sb)
+ {
+ 	struct buffer_head * bh;
+ 	int i,j;
+ 
+ 	if (!sb) {
+ 		printk("trying to get new block from nonexistant device\n");
+ 		return 0;
+ 	}
+ repeat:
+ 	j = 8192;
+ 	for (i=0 ; i<8 ; i++)
+ 		if ((bh=sb->u.linux_sb.s_zmap[i]) != NULL)
+ 			if ((j=find_first_zero(bh->b_data))<8192)
+ 				break;
+ 	if (i>=8 || !bh || j>=8192)
+ 		return 0;
+ 	if (set_bit(j,bh->b_data)) {
+ 		printk("new_block: bit already set");
+ 		goto repeat;
+ 	}
+ 	bh->b_dirt = 1;
+ 	j += i*8192 + sb->u.linux_sb.s_firstdatazone-1;
+ 	if (j >= sb->u.linux_sb.s_nzones)
+ 		return 0;
+ 	if (!(bh = getblk(sb->s_dev,j,BLOCK_SIZE))) {
+ 		printk("new_block: cannot get block");
+ 		return 0;
+ 	}
+ 	if (bh->b_count != 1) {
+ 		printk("new block: count is != 1");
+ 		return 0;
+ 	}
+ 	clear_block(bh->b_data);
+ 	bh->b_uptodate = 1;
+ 	bh->b_dirt = 1;
+ 	brelse(bh);
+ 	return j;
+ }
+ 
+ unsigned long linux_count_free_blocks(struct super_block *sb)
+ {
+ 	return (sb->u.linux_sb.s_nzones - count_used(sb->u.linux_sb.s_zmap,sb->u.linux_sb.s_zmap_blocks,sb->u.linux_sb.s_nzones))
+ 		 << sb->u.linux_sb.s_log_zone_size;
+ }
+ 
+ void linux_free_inode(struct inode * inode)
+ {
+ 	struct buffer_head * bh;
+ 
+ 	if (!inode)
+ 		return;
+ 	if (!inode->i_dev) {
+ 		printk("free_inode: inode has no device\n");
+ 		return;
+ 	}
+ 	if (inode->i_count != 1) {
+ 		printk("free_inode: inode has count=%d\n",inode->i_count);
+ 		return;
+ 	}
+ 	if (inode->i_nlink) {
+ 		printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
+ 		return;
+ 	}
+ 	if (!inode->i_sb) {
+ 		printk("free_inode: inode on nonexistent device\n");
+ 		return;
+ 	}
+ 	if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.linux_sb.s_ninodes) {
+ 		printk("free_inode: inode 0 or nonexistent inode\n");
+ 		return;
+ 	}
+ 	if (!(bh=inode->i_sb->u.linux_sb.s_imap[inode->i_ino>>13])) {
+ 		printk("free_inode: nonexistent imap in superblock\n");
+ 		return;
+ 	}
+ 	if (clear_bit(inode->i_ino&8191,bh->b_data))
+ 		printk("free_inode: bit %d already cleared.\n",inode->i_ino);
+ 	bh->b_dirt = 1;
+ 	clear_inode(inode);
+ }
+ 
+ struct inode * linux_new_inode(const struct inode * dir)
+ {
+ 	struct super_block * sb;
+ 	struct inode * inode;
+ 	struct buffer_head * bh;
+ 	int i,j;
+ 
+ 	if (!dir || !(inode = get_empty_inode()))
+ 		return NULL;
+ 	sb = dir->i_sb;
+ 	inode->i_sb = sb;
+ 	inode->i_flags = inode->i_sb->s_flags;
+ 	j = 8192;
+ 	for (i=0 ; i<8 ; i++)
+ 		if ((bh = inode->i_sb->u.linux_sb.s_imap[i]) != NULL)
+ 			if ((j=find_first_zero(bh->b_data))<8192)
+ 				break;
+ 	if (!bh || j >= 8192 || j+i*8192 > inode->i_sb->u.linux_sb.s_ninodes) {
+ 		iput(inode);
+ 		return NULL;
+ 	}
+ 	if (set_bit(j,bh->b_data)) {	/* shouldn't happen */
+ 		printk("new_inode: bit already set");
+ 		iput(inode);
+ 		return NULL;
+ 	}
+ 	bh->b_dirt = 1;
+ 	inode->i_count = 1;
+ 	inode->i_nlink = 1;
+ 	inode->i_dev = sb->s_dev;
+ 	inode->i_uid = current->euid;
+ 	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->egid;
+ 	inode->i_dirt = 1;
+ 	inode->i_ino = j + i*8192;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ 	inode->i_op = NULL;
+ 	inode->i_blocks = inode->i_blksize = 0;
+ 	return inode;
+ }
+ 
+ unsigned long linux_count_free_inodes(struct super_block *sb)
+ {
+ 	return sb->u.linux_sb.s_ninodes - count_used(sb->u.linux_sb.s_imap,sb->u.linux_sb.s_imap_blocks,sb->u.linux_sb.s_ninodes);
+ }
diff -r -c -N linux/fs/linux/blkdev.c linux993l/fs/linux/blkdev.c
*** linux/fs/linux/blkdev.c
--- linux993l/fs/linux/blkdev.c	Mon Jan 11 10:47:10 1993
***************
*** 0 ****
--- 1,62 ----
+ /*
+  *  linux/fs/linux/blkdev.c
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  */
+ 
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/linux_fs.h>
+ #include <linux/tty.h>
+ #include <linux/stat.h>
+ #include <linux/fcntl.h>
+ 
+ /*
+  * Called every time a linux block special file is opened
+  */
+ static int blkdev_open(struct inode * inode, struct file * filp)
+ {
+ 	int i;
+ 
+ 	i = MAJOR(inode->i_rdev);
+ 	if (i >= MAX_BLKDEV || !blkdev_fops[i])
+ 		return -ENODEV;
+ 	filp->f_op = blkdev_fops[i];
+ 	if (filp->f_op->open)
+ 		return filp->f_op->open(inode,filp);
+ 	return 0;
+ }	
+ 
+ /*
+  * Dummy default file-operations: the only thing this does
+  * is contain the open that then fills in the correct operations
+  * depending on the special file...
+  */
+ static struct file_operations def_blk_fops = {
+ 	NULL,		/* lseek */
+ 	NULL,		/* read */
+ 	NULL,		/* write */
+ 	NULL,		/* readdir */
+ 	NULL,		/* select */
+ 	NULL,		/* ioctl */
+ 	NULL,		/* mmap */
+ 	blkdev_open,	/* open */
+ 	NULL,		/* release */
+ };
+ 
+ struct inode_operations linux_blkdev_inode_operations = {
+ 	&def_blk_fops,		/* default file operations */
+ 	NULL,			/* create */
+ 	NULL,			/* lookup */
+ 	NULL,			/* link */
+ 	NULL,			/* unlink */
+ 	NULL,			/* symlink */
+ 	NULL,			/* mkdir */
+ 	NULL,			/* rmdir */
+ 	NULL,			/* mknod */
+ 	NULL,			/* rename */
+ 	NULL,			/* readlink */
+ 	NULL,			/* follow_link */
+ 	NULL,			/* bmap */
+ 	NULL			/* truncate */
+ };
diff -r -c -N linux/fs/linux/chrdev.c linux993l/fs/linux/chrdev.c
*** linux/fs/linux/chrdev.c
--- linux993l/fs/linux/chrdev.c	Mon Jan 11 10:47:10 1993
***************
*** 0 ****
--- 1,63 ----
+ /*
+  *  linux/fs/linux/chrdev.c
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  */
+ 
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/linux_fs.h>
+ #include <linux/tty.h>
+ #include <linux/stat.h>
+ #include <linux/fcntl.h>
+ 
+ /*
+  * Called every time a linux character special file is opened
+  */
+ static int chrdev_open(struct inode * inode, struct file * filp)
+ {
+ 	int i;
+ 
+ 	i = MAJOR(inode->i_rdev);
+ 	if (i >= MAX_CHRDEV || !chrdev_fops[i])
+ 		return -ENODEV;
+ 	filp->f_op = chrdev_fops[i];
+ 	if (filp->f_op->open)
+ 		return filp->f_op->open(inode,filp);
+ 	return 0;
+ }
+ 
+ /*
+  * Dummy default file-operations: the only thing this does
+  * is contain the open that then fills in the correct operations
+  * depending on the special file...
+  */
+ static struct file_operations def_chr_fops = {
+ 	NULL,		/* lseek */
+ 	NULL,		/* read */
+ 	NULL,		/* write */
+ 	NULL,		/* readdir */
+ 	NULL,		/* select */
+ 	NULL,		/* ioctl */
+ 	NULL,		/* mmap */
+ 	chrdev_open,	/* open */
+ 	NULL,		/* release */
+ };
+ 
+ struct inode_operations linux_chrdev_inode_operations = {
+ 	&def_chr_fops,		/* default file operations */
+ 	NULL,			/* create */
+ 	NULL,			/* lookup */
+ 	NULL,			/* link */
+ 	NULL,			/* unlink */
+ 	NULL,			/* symlink */
+ 	NULL,			/* mkdir */
+ 	NULL,			/* rmdir */
+ 	NULL,			/* mknod */
+ 	NULL,			/* rename */
+ 	NULL,			/* readlink */
+ 	NULL,			/* follow_link */
+ 	NULL,			/* bmap */
+ 	NULL			/* truncate */
+ };
+ 
diff -r -c -N linux/fs/linux/dir.c linux993l/fs/linux/dir.c
*** linux/fs/linux/dir.c
--- linux993l/fs/linux/dir.c	Mon Jan 11 10:47:10 1993
***************
*** 0 ****
--- 1,97 ----
+ /*
+  *  linux/fs/linux/dir.c
+  *
+  *  Copyright (C) 1991, 1992 Linus Torvalds
+  *
+  *  linux directory handling functions
+  */
+ 
+ #include <asm/segment.h>
+ 
+ #include <linux/errno.h>
+ #include <linux/fs.h>
+ #include <linux/linux_fs.h>
+ #include <linux/stat.h>
+ 
+ static int linux_dir_read(struct inode * inode, struct file * filp, char * buf, int count)
+ {
+ 	return -EISDIR;
+ }
+ 
+ static int linux_readdir(struct inode *, struct file *, struct dirent *, int);
+ 
+ static struct file_operations linux_dir_operations = {
+ 	NULL,			/* lseek - default */
+ 	linux_dir_read,		/* read */
+ 	NULL,			/* write - bad */
+ 	linux_readdir,		/* readdir */
+ 	NULL,			/* select - default */
+ 	NULL,			/* ioctl - default */
+ 	NULL,			/* mmap */
+ 	NULL,			/* no special open code */
+ 	NULL			/* no special release code */
+ };
+ 
+ /*
+  * directories can handle most operations...
+  */
+ struct inode_operations linux_dir_inode_operations = {
+ 	&linux_dir_operations,	/* default directory file-ops */
+ 	linux_create,		/* create */
+ 	linux_lookup,		/* lookup */
+ 	linux_link,		/* link */
+ 	linux_unlink,		/* unlink */
+ 	linux_symlink,		/* symlink */
+ 	linux_mkdir,		/* mkdir */
+ 	linux_rmdir,		/* rmdir */
+ 	linux_mknod,		/* mknod */
+ 	linux_rename,		/* rename */
+ 	NULL,			/* readlink */
+ 	NULL,			/* follow_link */
+ 	NULL,			/* bmap */
+ 	linux_truncate		/* truncate */
+ };
+ 
+ static int linux_readdir(struct inode * inode, struct file * filp,
+ 	struct dirent * dirent, int count)
+ {
+ 	unsigned int offset,i;
+ 	char c;
+ 	struct buffer_head * bh;
+ 	struct linux_dir_entry * de;
+ 
+ 	if (!inode || !S_ISDIR(inode->i_mode))
+ 		return -EBADF;
+ 	if (filp->f_pos & (sizeof (struct linux_dir_entry) - 1))
+ 		return -EBADF;
+ 	while (filp->f_pos < inode->i_size) {
+ 		offset = filp->f_pos & 1023;
+ 		bh = linux_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
+ 		if (!bh) {
+ 			filp->f_pos += 1024-offset;
+ 			continue;
+ 		}
+ 		de = (struct linux_dir_entry *) (offset + bh->b_data);
+ 		while (offset < 1024 && filp->f_pos < inode->i_size) {
+ 			offset += sizeof (struct linux_dir_entry);
+ 			filp->f_pos += sizeof (struct linux_dir_entry);
+ 			if (de->inode) {
+ 				for (i = 0; i < LINUX_NAME_LEN; i++)
+ 					if ((c = de->name[i]) != 0)
+ 						put_fs_byte(c,i+dirent->d_name);
+ 					else
+ 						break;
+ 				if (i) {
+ 					put_fs_long(de->inode,&dirent->d_ino);
+ 					put_fs_byte(0,i+dirent->d_name);
+ 					put_fs_word(i,&dirent->d_reclen);
+ 					brelse(bh);
+ 					return i;
+ 				}
+ 			}
+ 			de++;
+ 		}
+ 		brelse(bh);
+ 	}
+ 	return 0;
+ }
diff -r -c -N linux/fs/linux/fifo.c linux993l/fs/linux/fifo.c
*** linux/fs/linux/fifo.c
--- linux993l/fs/linux/fifo.c	Mon Jan 11 10:47:10 1993
***************
*** 0 ****
--- 1,27 ----
+ /*
+  *  linux/fs/fifo.c
+  *
+  *  written by Paul H. Hargrove
+  */
+ 
+ #include <linux/sched.h>
+ #include <linux/linux_fs.h>
+ 
+ extern struct file_operations def_fifo_fops;
+ 
+ struct inode_operations linux_fifo_inode_operations = {
+ 	&def_fifo_fops,		/* default file operations */
+ 	NULL,			/* create */
+ 	NULL,			/* lookup */
+ 	NULL,			/* link */
+ 	NULL,			/* unlink */
+ 	NULL,			/* symlink */
+ 	NULL,			/* mkdir */
+ 	NULL,			/* rmdir */
+ 	NULL,			/* mknod */
+ 	NULL,			/* rename */
+ 	NULL,			/* readlink */
+ 	NULL,			/* follow_link */
+ 	NULL,			/* bmap */
+ 	NULL			/* truncate */
+ };
diff -r -c -N linux/fs/linux/file.c linux993l/fs/linux/file.c
*** linux/fs/linux/file.c
--- linux993l/fs/linux/file.c	Mon Jan 11 10:47:10 1993
***************
*** 0 ****
--- 1,247 ----
+ /*
+  *  linux/fs/linux/file.c
+  *
+  *  Copyright (C) 1991, 1992 Linus Torvalds
+  *
+  *  linux regular file handling primitives
+  */
+ 
+ #include <asm/segment.h>
+ #include <asm/system.h>
+ 
+ #include <linux/sched.h>
+ #include <linux/linux_fs.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/fcntl.h>
+ #include <linux/stat.h>
+ #include <linux/locks.h>
+ 
+ #define	NBUF	16
+ 
+ #define MIN(a,b) (((a)<(b))?(a):(b))
+ #define MAX(a,b) (((a)>(b))?(a):(b))
+ 
+ #include <linux/fs.h>
+ #include <linux/linux_fs.h>
+ 
+ static int linux_file_read(struct inode *, struct file *, char *, int);
+ static int linux_file_write(struct inode *, struct file *, char *, int);
+ 
+ /*
+  * We have mostly NULL's here: the current defaults are ok for
+  * the linux filesystem.
+  */
+ static struct file_operations linux_file_operations = {
+ 	NULL,			/* lseek - default */
+ 	linux_file_read,	/* read */
+ 	linux_file_write,	/* write */
+ 	NULL,			/* readdir - bad */
+ 	NULL,			/* select - default */
+ 	NULL,			/* ioctl - default */
+ 	NULL,			/* mmap */
+ 	NULL,			/* no special open is needed */
+ 	NULL			/* release */
+ };
+ 
+ struct inode_operations linux_file_inode_operations = {
+ 	&linux_file_operations,	/* default file operations */
+ 	NULL,			/* create */
+ 	NULL,			/* lookup */
+ 	NULL,			/* link */
+ 	NULL,			/* unlink */
+ 	NULL,			/* symlink */
+ 	NULL,			/* mkdir */
+ 	NULL,			/* rmdir */
+ 	NULL,			/* mknod */
+ 	NULL,			/* rename */
+ 	NULL,			/* readlink */
+ 	NULL,			/* follow_link */
+ 	linux_bmap,		/* bmap */
+ 	linux_truncate		/* truncate */
+ };
+ 
+ static int linux_file_read(struct inode * inode, struct file * filp, char * buf, int count)
+ {
+ 	int read,left,chars;
+ 	int block, blocks, offset;
+ 	int bhrequest, uptodate;
+ 	struct buffer_head ** bhb, ** bhe;
+ 	struct buffer_head * bhreq[NBUF];
+ 	struct buffer_head * buflist[NBUF];
+ 	unsigned int size;
+ 
+ 	if (!inode) {
+ 		printk("linux_file_read: inode = NULL\n");
+ 		return -EINVAL;
+ 	}
+ 	if (!S_ISREG(inode->i_mode)) {
+ 		printk("linux_file_read: mode = %07o\n",inode->i_mode);
+ 		return -EINVAL;
+ 	}
+ 	offset = filp->f_pos;
+ 	size = inode->i_size;
+ 	if (offset > size)
+ 		left = 0;
+ 	else
+ 		left = size - offset;
+ 	if (left > count)
+ 		left = count;
+ 	if (left <= 0)
+ 		return 0;
+ 	read = 0;
+ 	block = offset >> BLOCK_SIZE_BITS;
+ 	offset &= BLOCK_SIZE-1;
+ 	size = (size + (BLOCK_SIZE-1)) >> BLOCK_SIZE_BITS;
+ 	blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+ 	bhb = bhe = buflist;
+ 	if (filp->f_reada) {
+ 		blocks += read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
+ 		if (block + blocks > size)
+ 			blocks = size - block;
+ 	}
+ 
+ 	/* We do this in a two stage process.  We first try and request
+ 	   as many blocks as we can, then we wait for the first one to
+ 	   complete, and then we try and wrap up as many as are actually
+ 	   done.  This routine is rather generic, in that it can be used
+ 	   in a filesystem by substituting the appropriate function in
+ 	   for getblk.
+ 
+ 	   This routine is optimized to make maximum use of the various
+ 	   buffers and caches. */
+ 
+ 	do {
+ 		bhrequest = 0;
+ 		uptodate = 1;
+ 		while (blocks) {
+ 			--blocks;
+ 			*bhb = linux_getblk(inode, block++, 0);
+ 			if (*bhb && !(*bhb)->b_uptodate) {
+ 				uptodate = 0;
+ 				bhreq[bhrequest++] = *bhb;
+ 			}
+ 
+ 			if (++bhb == &buflist[NBUF])
+ 				bhb = buflist;
+ 
+ 			/* If the block we have on hand is uptodate, go ahead
+ 			   and complete processing. */
+ 			if (uptodate)
+ 				break;
+ 			if (bhb == bhe)
+ 				break;
+ 		}
+ 
+ 		/* Now request them all */
+ 		if (bhrequest)
+ 			ll_rw_block(READ, bhrequest, bhreq);
+ 
+ 		do { /* Finish off all I/O that has actually completed */
+ 			if (*bhe) {
+ 				wait_on_buffer(*bhe);
+ 				if (!(*bhe)->b_uptodate) {	/* read error? */
+ 					left = 0;
+ 					break;
+ 				}
+ 			}
+ 			if (left < BLOCK_SIZE - offset)
+ 				chars = left;
+ 			else
+ 				chars = BLOCK_SIZE - offset;
+ 			filp->f_pos += chars;
+ 			left -= chars;
+ 			read += chars;
+ 			if (*bhe) {
+ 				memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+ 				brelse(*bhe);
+ 				buf += chars;
+ 			} else {
+ 				while (chars-->0)
+ 					put_fs_byte(0,buf++);
+ 			}
+ 			offset = 0;
+ 			if (++bhe == &buflist[NBUF])
+ 				bhe = buflist;
+ 		} while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
+ 	} while (left > 0);
+ 
+ /* Release the read-ahead blocks */
+ 	while (bhe != bhb) {
+ 		brelse(*bhe);
+ 		if (++bhe == &buflist[NBUF])
+ 			bhe = buflist;
+ 	};
+ 	if (!read)
+ 		return -EIO;
+ 	filp->f_reada = 1;
+ 	if (!IS_RDONLY(inode)) {
+ 		inode->i_atime = CURRENT_TIME;
+ 		inode->i_dirt = 1;
+ 	}
+ 	return read;
+ }
+ 
+ static int linux_file_write(struct inode * inode, struct file * filp, char * buf, int count)
+ {
+ 	off_t pos;
+ 	int written,c;
+ 	struct buffer_head * bh;
+ 	char * p;
+ 
+ 	if (!inode) {
+ 		printk("linux_file_write: inode = NULL\n");
+ 		return -EINVAL;
+ 	}
+ 	if (!S_ISREG(inode->i_mode)) {
+ 		printk("linux_file_write: mode = %07o\n",inode->i_mode);
+ 		return -EINVAL;
+ 	}
+ /*
+  * ok, append may not work when many processes are writing at the same time
+  * but so what. That way leads to madness anyway.
+  */
+ 	if (filp->f_flags & O_APPEND)
+ 		pos = inode->i_size;
+ 	else
+ 		pos = filp->f_pos;
+ 	written = 0;
+ 	while (written<count) {
+ 		bh = linux_getblk(inode,pos/BLOCK_SIZE,1);
+ 		if (!bh) {
+ 			if (!written)
+ 				written = -ENOSPC;
+ 			break;
+ 		}
+ 		c = BLOCK_SIZE - (pos % BLOCK_SIZE);
+ 		if (c > count-written)
+ 			c = count-written;
+ 		if (c != BLOCK_SIZE && !bh->b_uptodate) {
+ 			ll_rw_block(READ, 1, &bh);
+ 			wait_on_buffer(bh);
+ 			if (!bh->b_uptodate) {
+ 				brelse(bh);
+ 				if (!written)
+ 					written = -EIO;
+ 				break;
+ 			}
+ 		}
+ 		p = (pos % BLOCK_SIZE) + bh->b_data;
+ 		pos += c;
+ 		if (pos > inode->i_size) {
+ 			inode->i_size = pos;
+ 			inode->i_dirt = 1;
+ 		}
+ 		written += c;
+ 		memcpy_fromfs(p,buf,c);
+ 		buf += c;
+ 		bh->b_uptodate = 1;
+ 		bh->b_dirt = 1;
+ 		brelse(bh);
+ 	}
+ 	inode->i_mtime = CURRENT_TIME;
+ 	inode->i_ctime = CURRENT_TIME;
+ 	filp->f_pos = pos;
+ 	inode->i_dirt = 1;
+ 	return written;
+ }
diff -r -c -N linux/fs/linux/inode.c linux993l/fs/linux/inode.c
*** linux/fs/linux/inode.c
--- linux993l/fs/linux/inode.c	Mon Jan 11 10:47:10 1993
***************
*** 0 ****
--- 1,377 ----
+ /*
+  *  linux/fs/linux/inode.c
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  */
+ 
+ #include <linux/sched.h>
+ #include <linux/linux_fs.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/string.h>
+ #include <linux/stat.h>
+ #include <linux/locks.h>
+ 
+ #include <asm/system.h>
+ #include <asm/segment.h>
+ 
+ void linux_put_inode(struct inode *inode)
+ {
+ 	if (inode->i_nlink)
+ 		return;
+ 	inode->i_size = 0;
+ 	linux_truncate(inode);
+ 	linux_free_inode(inode);
+ }
+ 
+ void linux_put_super(struct super_block *sb)
+ {
+ 	int i;
+ 
+ 	lock_super(sb);
+ 	sb->s_dev = 0;
+ 	for(i = 0 ; i < LINUX_I_MAP_SLOTS ; i++)
+ 		brelse(sb->u.linux_sb.s_imap[i]);
+ 	for(i = 0 ; i < LINUX_Z_MAP_SLOTS ; i++)
+ 		brelse(sb->u.linux_sb.s_zmap[i]);
+ 	unlock_super(sb);
+ 	return;
+ }
+ 
+ static struct super_operations linux_sops = { 
+ 	linux_read_inode,
+ 	NULL,
+ 	linux_write_inode,
+ 	linux_put_inode,
+ 	linux_put_super,
+ 	NULL,
+ 	linux_statfs
+ };
+ 
+ struct super_block *linux_read_super(struct super_block *s,void *data)
+ {
+ 	struct buffer_head *bh;
+ 	struct linux_super_block *ms;
+ 	int i,dev=s->s_dev,block;
+ 
+ 	if (32 != sizeof (struct linux_inode))
+ 		panic("bad i-node size");
+ 	lock_super(s);
+ 	if (!(bh = bread(dev,1,BLOCK_SIZE))) {
+ 		s->s_dev=0;
+ 		unlock_super(s);
+ 		printk("LINUX-fs: unable to read superblock\n");
+ 		return NULL;
+ 	}
+ 	ms = (struct linux_super_block *) bh->b_data;
+ 	s->s_blocksize = 1024;
+ 	s->u.linux_sb.s_ninodes = ms->s_ninodes;
+ 	s->u.linux_sb.s_nzones = ms->s_nzones;
+ 	s->u.linux_sb.s_imap_blocks = ms->s_imap_blocks;
+ 	s->u.linux_sb.s_zmap_blocks = ms->s_zmap_blocks;
+ 	s->u.linux_sb.s_firstdatazone = ms->s_firstdatazone;
+ 	s->u.linux_sb.s_log_zone_size = ms->s_log_zone_size;
+ 	s->u.linux_sb.s_max_size = ms->s_max_size;
+ 	s->s_magic = ms->s_magic;
+ 	brelse(bh);
+ 	if (s->s_magic != LINUX_SUPER_MAGIC) {
+ 		s->s_dev = 0;
+ 		unlock_super(s);
+ 		printk("LINUX-fs magic match failed\n");
+ 		return NULL;
+ 	}
+ 	for (i=0;i < LINUX_I_MAP_SLOTS;i++)
+ 		s->u.linux_sb.s_imap[i] = NULL;
+ 	for (i=0;i < LINUX_Z_MAP_SLOTS;i++)
+ 		s->u.linux_sb.s_zmap[i] = NULL;
+ 	block=2;
+ 	for (i=0 ; i < s->u.linux_sb.s_imap_blocks ; i++)
+ 		if ((s->u.linux_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
+ 			block++;
+ 		else
+ 			break;
+ 	for (i=0 ; i < s->u.linux_sb.s_zmap_blocks ; i++)
+ 		if ((s->u.linux_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE)) != NULL)
+ 			block++;
+ 		else
+ 			break;
+ 	if (block != 2+s->u.linux_sb.s_imap_blocks+s->u.linux_sb.s_zmap_blocks) {
+ 		for(i=0;i<LINUX_I_MAP_SLOTS;i++)
+ 			brelse(s->u.linux_sb.s_imap[i]);
+ 		for(i=0;i<LINUX_Z_MAP_SLOTS;i++)
+ 			brelse(s->u.linux_sb.s_zmap[i]);
+ 		s->s_dev=0;
+ 		unlock_super(s);
+ 		printk("LINUX-fs: bad superblock or unable to read bitmaps\n");
+ 		return NULL;
+ 	}
+ 	s->u.linux_sb.s_imap[0]->b_data[0] |= 1;
+ 	s->u.linux_sb.s_zmap[0]->b_data[0] |= 1;
+ 	/* set up enough so that it can read an inode */
+ 	s->s_dev = dev;
+ 	s->s_op = &linux_sops;
+ 	s->s_mounted = iget(s,LINUX_ROOT_INO);
+ 	unlock_super(s);
+ 	if (!s->s_mounted) {
+ 		s->s_dev = 0;
+ 		printk("LINUX-fs: get root inode failed\n");
+ 		return NULL;
+ 	}
+ 	return s;
+ }
+ 
+ void linux_statfs(struct super_block *sb, struct statfs *buf)
+ {
+ 	long tmp;
+ 
+ 	put_fs_long(LINUX_SUPER_MAGIC, &buf->f_type);
+ 	put_fs_long(1024, &buf->f_bsize);
+ 	put_fs_long(sb->u.linux_sb.s_nzones << sb->u.linux_sb.s_log_zone_size, &buf->f_blocks);
+ 	tmp = linux_count_free_blocks(sb);
+ 	put_fs_long(tmp, &buf->f_bfree);
+ 	put_fs_long(tmp, &buf->f_bavail);
+ 	put_fs_long(sb->u.linux_sb.s_ninodes, &buf->f_files);
+ 	put_fs_long(linux_count_free_inodes(sb), &buf->f_ffree);
+ 	/* Don't know what value to put in buf->f_fsid */
+ }
+ 
+ #define inode_bmap(inode,nr) ((inode)->u.linux_i.i_data[(nr)])
+ 
+ static int block_bmap(struct buffer_head * bh, int nr)
+ {
+ 	int tmp;
+ 
+ 	if (!bh)
+ 		return 0;
+ 	tmp = ((unsigned short *) bh->b_data)[nr];
+ 	brelse(bh);
+ 	return tmp;
+ }
+ 
+ int linux_bmap(struct inode * inode,int block)
+ {
+ 	int i;
+ 
+ 	if (block<0) {
+ 		printk("linux_bmap: block<0");
+ 		return 0;
+ 	}
+ 	if (block >= 7+512+512*512) {
+ 		printk("linux_bmap: block>big");
+ 		return 0;
+ 	}
+ 	if (block < 7)
+ 		return inode_bmap(inode,block);
+ 	block -= 7;
+ 	if (block < 512) {
+ 		i = inode_bmap(inode,7);
+ 		if (!i)
+ 			return 0;
+ 		return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
+ 	}
+ 	block -= 512;
+ 	i = inode_bmap(inode,8);
+ 	if (!i)
+ 		return 0;
+ 	i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>9);
+ 	if (!i)
+ 		return 0;
+ 	return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 511);
+ }
+ 
+ static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create)
+ {
+ 	int tmp;
+ 	unsigned short *p;
+ 	struct buffer_head * result;
+ 
+ 	p = inode->u.linux_i.i_data + nr;
+ repeat:
+ 	tmp = *p;
+ 	if (tmp) {
+ 		result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
+ 		if (tmp == *p)
+ 			return result;
+ 		brelse(result);
+ 		goto repeat;
+ 	}
+ 	if (!create)
+ 		return NULL;
+ 	tmp = linux_new_block(inode->i_sb);
+ 	if (!tmp)
+ 		return NULL;
+ 	result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
+ 	if (*p) {
+ 		linux_free_block(inode->i_sb,tmp);
+ 		brelse(result);
+ 		goto repeat;
+ 	}
+ 	*p = tmp;
+ 	inode->i_ctime = CURRENT_TIME;
+ 	inode->i_dirt = 1;
+ 	return result;
+ }
+ 
+ static struct buffer_head * block_getblk(struct inode * inode, 
+ 	struct buffer_head * bh, int nr, int create)
+ {
+ 	int tmp;
+ 	unsigned short *p;
+ 	struct buffer_head * result;
+ 
+ 	if (!bh)
+ 		return NULL;
+ 	if (!bh->b_uptodate) {
+ 		ll_rw_block(READ, 1, &bh);
+ 		wait_on_buffer(bh);
+ 		if (!bh->b_uptodate) {
+ 			brelse(bh);
+ 			return NULL;
+ 		}
+ 	}
+ 	p = nr + (unsigned short *) bh->b_data;
+ repeat:
+ 	tmp = *p;
+ 	if (tmp) {
+ 		result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
+ 		if (tmp == *p) {
+ 			brelse(bh);
+ 			return result;
+ 		}
+ 		brelse(result);
+ 		goto repeat;
+ 	}
+ 	if (!create) {
+ 		brelse(bh);
+ 		return NULL;
+ 	}
+ 	tmp = linux_new_block(inode->i_sb);
+ 	if (!tmp) {
+ 		brelse(bh);
+ 		return NULL;
+ 	}
+ 	result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
+ 	if (*p) {
+ 		linux_free_block(inode->i_sb,tmp);
+ 		brelse(result);
+ 		goto repeat;
+ 	}
+ 	*p = tmp;
+ 	bh->b_dirt = 1;
+ 	brelse(bh);
+ 	return result;
+ }
+ 
+ struct buffer_head * linux_getblk(struct inode * inode, int block, int create)
+ {
+ 	struct buffer_head * bh;
+ 
+ 	if (block<0) {
+ 		printk("linux_getblk: block<0");
+ 		return NULL;
+ 	}
+ 	if (block >= 7+512+512*512) {
+ 		printk("linux_getblk: block>big");
+ 		return NULL;
+ 	}
+ 	if (block < 7)
+ 		return inode_getblk(inode,block,create);
+ 	block -= 7;
+ 	if (block < 512) {
+ 		bh = inode_getblk(inode,7,create);
+ 		return block_getblk(inode, bh, block, create);
+ 	}
+ 	block -= 512;
+ 	bh = inode_getblk(inode,8,create);
+ 	bh = block_getblk(inode, bh, block>>9, create);
+ 	return block_getblk(inode, bh, block & 511, create);
+ }
+ 
+ struct buffer_head * linux_bread(struct inode * inode, int block, int create)
+ {
+ 	struct buffer_head * bh;
+ 
+ 	bh = linux_getblk(inode,block,create);
+ 	if (!bh || bh->b_uptodate)
+ 		return bh;
+ 	ll_rw_block(READ, 1, &bh);
+ 	wait_on_buffer(bh);
+ 	if (bh->b_uptodate)
+ 		return bh;
+ 	brelse(bh);
+ 	return NULL;
+ }
+ 
+ void linux_read_inode(struct inode * inode)
+ {
+ 	struct buffer_head * bh;
+ 	struct linux_inode * raw_inode;
+ 	int block, ino;
+ 
+ 	ino = inode->i_ino;
+ 	block = 2 + inode->i_sb->u.linux_sb.s_imap_blocks +
+ 		    inode->i_sb->u.linux_sb.s_zmap_blocks +
+ 		    (ino-1)/LINUX_INODES_PER_BLOCK;
+ 	if (!(bh=bread(inode->i_dev,block, BLOCK_SIZE)))
+ 		panic("unable to read i-node block");
+ 	raw_inode = ((struct linux_inode *) bh->b_data) +
+ 		    (ino-1)%LINUX_INODES_PER_BLOCK;
+ 	inode->i_mode = raw_inode->i_mode;
+ 	inode->i_uid = raw_inode->i_uid;
+ 	inode->i_gid = raw_inode->i_gid;
+ 	inode->i_nlink = raw_inode->i_nlinks;
+ 	inode->i_size = raw_inode->i_size;
+ 	inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
+ 	inode->i_blocks = inode->i_blksize = 0;
+ 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+ 		inode->i_rdev = raw_inode->i_zone[0];
+ 	else for (block = 0; block < 9; block++)
+ 		inode->u.linux_i.i_data[block] = raw_inode->i_zone[block];
+ 	brelse(bh);
+ 	inode->i_op = NULL;
+ 	if (S_ISREG(inode->i_mode))
+ 		inode->i_op = &linux_file_inode_operations;
+ 	else if (S_ISDIR(inode->i_mode))
+ 		inode->i_op = &linux_dir_inode_operations;
+ 	else if (S_ISLNK(inode->i_mode))
+ 		inode->i_op = &linux_symlink_inode_operations;
+ 	else if (S_ISCHR(inode->i_mode))
+ 		inode->i_op = &linux_chrdev_inode_operations;
+ 	else if (S_ISBLK(inode->i_mode))
+ 		inode->i_op = &linux_blkdev_inode_operations;
+ 	else if (S_ISFIFO(inode->i_mode)) {
+ 		inode->i_op = &linux_fifo_inode_operations;
+ 		inode->i_pipe = 1;
+ 		PIPE_BASE(*inode) = NULL;
+ 		PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
+ 		PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
+ 		PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
+ 	}
+ }
+ 
+ void linux_write_inode(struct inode * inode)
+ {
+ 	struct buffer_head * bh;
+ 	struct linux_inode * raw_inode;
+ 	int block;
+ 
+ 	block = 2 + inode->i_sb->u.linux_sb.s_imap_blocks + inode->i_sb->u.linux_sb.s_zmap_blocks +
+ 		(inode->i_ino-1)/LINUX_INODES_PER_BLOCK;
+ 	if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
+ 		panic("unable to read i-node block");
+ 	raw_inode = ((struct linux_inode *)bh->b_data) +
+ 		(inode->i_ino-1)%LINUX_INODES_PER_BLOCK;
+ 	raw_inode->i_mode = inode->i_mode;
+ 	raw_inode->i_uid = inode->i_uid;
+ 	raw_inode->i_gid = inode->i_gid;
+ 	raw_inode->i_nlinks = inode->i_nlink;
+ 	raw_inode->i_size = inode->i_size;
+ 	raw_inode->i_time = inode->i_mtime;
+ 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+ 		raw_inode->i_zone[0] = inode->i_rdev;
+ 	else for (block = 0; block < 9; block++)
+ 		raw_inode->i_zone[block] = inode->u.linux_i.i_data[block];
+ 	inode->i_dirt=0;
+ 	bh->b_dirt=1;
+ 	brelse(bh);
+ }
diff -r -c -N linux/fs/linux/lfs.h linux993l/fs/linux/lfs.h
*** linux/fs/linux/lfs.h
--- linux993l/fs/linux/lfs.h	Mon Jan 11 11:13:08 1993
***************
*** 0 ****
--- 1,116 ----
+ #ifndef _LINUX_LINUX_FS_H
+ #define _LINUX_LINUX_FS_H
+ 
+ /*
+  * The linux filesystem constants/structures
+  */
+ 
+ /*
+  * Thanks to Kees J Bot for sending me the definitions of the new
+  * linux filesystem (aka V2) with bigger inodes and 32-bit block
+  * pointers. It's not actually implemented yet, but I'll look into
+  * it.
+  */
+ 
+ #define LINUX_NAME_LEN 14
+ #define LINUX_ROOT_INO 1
+ 
+ #define LINUX_I_MAP_SLOTS	8
+ #define LINUX_Z_MAP_SLOTS	8
+ #define LINUX_SUPER_MAGIC	0x137F
+ #define NEW_LINUX_SUPER_MAGIC	0x2468
+ 
+ #define LINUX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct linux_inode)))
+ #define LINUX_DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct linux_dir_entry)))
+ 
+ struct linux_inode {
+ 	unsigned short i_mode;
+ 	unsigned short i_uid;
+ 	unsigned long i_size;
+ 	unsigned long i_time;
+ 	unsigned char i_gid;
+ 	unsigned char i_nlinks;
+ 	unsigned short i_zone[9];
+ };
+ 
+ /*
+  * The new linux inode has all the time entries, as well as
+  * long block numbers and a third indirect block (7+1+1+1
+  * instead of 7+1+1). Also, some previously 8-bit values are
+  * now 16-bit. The inode is now 64 bytes instead of 32.
+  */
+ struct new_linux_inode {
+ 	unsigned short i_mode;
+ 	unsigned short i_nlinks;
+ 	unsigned short i_uid;
+ 	unsigned short i_gid;
+ 	unsigned long i_size;
+ 	unsigned long i_atime;
+ 	unsigned long i_mtime;
+ 	unsigned long i_ctime;
+ 	unsigned long i_zone[10];
+ };
+ 
+ /*
+  * linux super-block data on disk
+  */
+ struct linux_super_block {
+ 	unsigned short s_ninodes;
+ 	unsigned short s_nzones;
+ 	unsigned short s_imap_blocks;
+ 	unsigned short s_zmap_blocks;
+ 	unsigned short s_firstdatazone;
+ 	unsigned short s_log_zone_size;
+ 	unsigned long s_max_size;
+ 	unsigned short s_magic;
+ };
+ 
+ struct linux_dir_entry {
+ 	unsigned short inode;
+ 	char name[LINUX_NAME_LEN];
+ };
+ 
+ extern int linux_lookup(struct inode * dir,const char * name, int len,
+ 	struct inode ** result);
+ extern int linux_create(struct inode * dir,const char * name, int len, int mode,
+ 	struct inode ** result);
+ extern int linux_mkdir(struct inode * dir, const char * name, int len, int mode);
+ extern int linux_rmdir(struct inode * dir, const char * name, int len);
+ extern int linux_unlink(struct inode * dir, const char * name, int len);
+ extern int linux_symlink(struct inode * inode, const char * name, int len,
+ 	const char * symname);
+ extern int linux_link(struct inode * oldinode, struct inode * dir, const char * name, int len);
+ extern int linux_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
+ extern int linux_rename(struct inode * old_dir, const char * old_name, int old_len,
+ 	struct inode * new_dir, const char * new_name, int new_len);
+ extern struct inode * linux_new_inode(const struct inode * dir);
+ extern void linux_free_inode(struct inode * inode);
+ extern unsigned long linux_count_free_inodes(struct super_block *sb);
+ extern int linux_new_block(struct super_block * sb);
+ extern void linux_free_block(struct super_block * sb, int block);
+ extern unsigned long linux_count_free_blocks(struct super_block *sb);
+ 
+ extern int linux_bmap(struct inode *,int);
+ 
+ extern struct buffer_head * linux_getblk(struct inode *, int, int);
+ extern struct buffer_head * linux_bread(struct inode *, int, int);
+ 
+ extern void linux_truncate(struct inode *);
+ extern void linux_put_super(struct super_block *);
+ extern struct super_block *linux_read_super(struct super_block *,void *);
+ extern void linux_read_inode(struct inode *);
+ extern void linux_write_inode(struct inode *);
+ extern void linux_put_inode(struct inode *);
+ extern void linux_statfs(struct super_block *, struct statfs *);
+ 
+ extern struct inode_operations linux_file_inode_operations;
+ extern struct inode_operations linux_dir_inode_operations;
+ extern struct inode_operations linux_symlink_inode_operations;
+ extern struct inode_operations linux_chrdev_inode_operations;
+ extern struct inode_operations linux_blkdev_inode_operations;
+ extern struct inode_operations linux_fifo_inode_operations;
+ 
+ extern struct file_operations linux_file_operations;
+ extern struct file_operations linux_dir_operations;
+ 
+ #endif
diff -r -c -N linux/fs/linux/lfsck.c linux993l/fs/linux/lfsck.c
*** linux/fs/linux/lfsck.c
--- linux993l/fs/linux/lfsck.c	Fri Jan 15 14:41:38 1993
***************
*** 0 ****
--- 1,678 ----
+ /*
+  * fsck.c - a file system consistency checker for Linux.
+  *
+  * (C) 1991 Linus Torvalds. This file may be redistributed as per
+  * the GNU copyright.
+  */
+ 
+ /*
+  * 09.11.91  -  made the first rudimetary functions
+  *
+  * 10.11.91  -  updated, does checking, no repairs yet.
+  *		Sent out to the mailing-list for testing.
+  *
+  * 14.11.91  -	Testing seems to have gone well. Added some
+  *		correction-code, and changed some functions.
+  *
+  * 15.11.91  -  More correction code. Hopefully it notices most
+  *		cases now, and tries to do something about them.
+  *
+  * 16.11.91  -  More corrections (thanks to Mika Jalava). Most
+  *		things seem to work now. Yeah, sure.
+  *
+  * I've had no time to add comments - hopefully the function names
+  * are comments enough. As with all file system checkers, this assumes
+  * the file system is quiescent - don't use it on a mounted device
+  * unless you can be sure nobody is writing to it (and remember that the
+  * kernel can write to it when it searches for files).
+  *
+  * Usuage: fsck [-larvsm] device
+  *	-l for a listing of all the filenames
+  *	-a for automatic repairs (not implemented)
+  *	-r for repairs (interactive) (not implemented)
+  *	-v for verbose (tells how many files)
+  *	-s for super-block info
+  *	-m for linux-like "mode not cleared" warnings
+  *
+  * The device may be a block device or a image of one, but this isn't
+  * enforced (but it's not much fun on a character device :-). 
+  */
+ 
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <fcntl.h>
+ #include <ctype.h>
+ #include <stdlib.h>
+ #include <termios.h>
+ #include <sys/stat.h>
+ 
+ #include <linux/fs.h>
+ #include <linux/linux_fs.h>
+ #define NAME_LEN LINUX_NAME_LEN
+ 
+ #ifndef __GNUC__
+ #error "needs gcc for the bitop-__asm__'s"
+ #endif
+ 
+ #ifndef __linux__
+ #define volatile
+ #endif
+ 
+ #define ROOT_INO 1
+ 
+ #define d_inode linux_inode
+ #define UPPER(size,n) ((size+((n)-1))/(n))
+ #define INODE_SIZE (sizeof(struct d_inode))
+ #define INODE_BLOCKS UPPER(INODES,LINUX_INODES_PER_BLOCK)
+ #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
+ 
+ #define BITS_PER_BLOCK (BLOCK_SIZE<<3)
+ 
+ extern int isatty(int);
+ 
+ static char * program_name = "fsck";
+ static char * device_name = NULL;
+ static int IN;
+ static int repair=0, automatic=0, verbose=0, list=0, show=0, warn_mode=0;
+ static int directory=0, regular=0, blockdev=0, chardev=0, links=0,
+ 		symlinks=0, total=0;
+ 
+ static int changed = 0; /* flags if the filesystem has been changed */
+ 
+ /* File-name data */
+ #define MAX_DEPTH 50
+ static int name_depth = 0;
+ static char name_list[MAX_DEPTH][NAME_LEN+1];
+ 
+ static char * inode_buffer = NULL;
+ #define Inode (((struct d_inode *) inode_buffer)-1)
+ static char super_block_buffer[BLOCK_SIZE];
+ #define Super (*(struct linux_super_block *)super_block_buffer)
+ #define INODES ((unsigned long)Super.s_ninodes)
+ #define ZONES ((unsigned long)Super.s_nzones)
+ #define IMAPS ((unsigned long)Super.s_imap_blocks)
+ #define ZMAPS ((unsigned long)Super.s_zmap_blocks)
+ #define FIRSTZONE ((unsigned long)Super.s_firstdatazone)
+ #define ZONESIZE ((unsigned long)Super.s_log_zone_size)
+ #define MAXSIZE ((unsigned long)Super.s_max_size)
+ #define MAGIC (Super.s_magic)
+ #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS)
+ 
+ static char inode_map[BLOCK_SIZE * LINUX_I_MAP_SLOTS];
+ static char zone_map[BLOCK_SIZE * LINUX_Z_MAP_SLOTS];
+ 
+ static unsigned char * inode_count = NULL;
+ static unsigned char * zone_count = NULL;
+ 
+ void recursive_check(unsigned int ino);
+ 
+ #define bitop(name,op) \
+ static inline int name(char * addr,unsigned int nr) \
+ { \
+ int __res; \
+ __asm__ __volatile__("bt" op "l %1,%2; adcl $0,%0" \
+ :"=g" (__res) \
+ :"r" (nr),"m" (*(addr)),"0" (0)); \
+ return __res; \
+ }
+ 
+ bitop(bit,"")
+ bitop(setbit,"s")
+ bitop(clrbit,"r")
+ 
+ #define inode_in_use(x) (bit(inode_map,(x)))
+ #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1))
+ 
+ #define mark_inode(x) (setbit(inode_map,(x)),changed=1)
+ #define unmark_inode(x) (clrbit(inode_map,(x)),changed=1)
+ 
+ #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1),changed=1)
+ #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1),changed=1)
+ 
+ /*
+  * Volatile to let gcc know that this doesn't return. When trying
+  * to compile this under linux, volatile gives a warning, as
+  * exit() isn't defined as volatile under linux.
+  */
+ volatile void fatal_error(const char * fmt_string)
+ {
+ 	fprintf(stderr,fmt_string,program_name,device_name);
+ 	exit(1);
+ }
+ 
+ #define usage() fatal_error("Usage: %s [-larvsm] /dev/name\n")
+ #define die(str) fatal_error("%s: " str "\n")
+ 
+ /*
+  * This simply goes through the file-name data and prints out the
+  * current file.
+  */
+ void print_current_name(void)
+ {
+ 	int i=0;
+ 
+ 	while (i<name_depth)
+ 		printf("/%.30s",name_list[i++]);
+ }
+ 
+ int ask(const char * string,int def)
+ {
+ 	int c;
+ 
+ 	if (!repair) {
+ 		printf("\n");
+ 		return 0;
+ 	}
+ 	if (automatic) {
+ 		printf("\n");
+ 		return def;
+ 	}
+ 	printf(def?"%s (y/n)? ":"%s (n/y)? ",string);
+ 	for (;;) {
+ 		fflush(stdout);
+ 		if ((c=getchar())==EOF)
+ 			return def;
+ 		c=toupper(c);
+ 		if (c == 'Y') {
+ 			def = 1;
+ 			break;
+ 		} else if (c == 'N') {
+ 			def = 0;
+ 			break;
+ 		} else if (c == ' ' || c == '\n')
+ 			break;
+ 	}
+ 	if (def)
+ 		printf("y\n");
+ 	else
+ 		printf("n\n");
+ 	return def;
+ }
+ 
+ /*
+  * check_zone_nr checks to see that *nr is a valid zone nr. If it
+  * isn't, it will possibly be repaired. Check_zone_nr returns != 0
+  * if it changed the nr.
+  */
+ int check_zone_nr(unsigned short * nr)
+ {
+ 	if (!*nr)
+ 		return 0;
+ 	if (*nr < FIRSTZONE)
+ 		printf("Zone nr < FIRSTZONE in file `");
+ 	else if (*nr >= ZONES)
+ 		printf("Zone nr > ZONES in file `");
+ 	else
+ 		return 0;
+ 	print_current_name();
+ 	printf("'.");
+ 	if (ask("Remove block",1)) {
+ 		*nr=0;
+ 		changed = 1;
+ 		return 1;
+ 	}
+ 	return 0;
+ }
+ 
+ /*
+  * read-block reads block *nr into the buffer at addr. It returns
+  * 0 if the *nr is unchanged, 1 if it was changed.
+  */
+ int read_block(unsigned short * nr, char * addr)
+ {
+ 	int blk_chg = check_zone_nr(nr);
+ 
+ 	if (!*nr || *nr >= ZONES) {
+ 		memset(addr,0,BLOCK_SIZE);
+ 		return changed;
+ 	}
+ 	if (BLOCK_SIZE*(*nr) != lseek(IN, BLOCK_SIZE*(*nr), SEEK_SET))
+ 		die("seek failed in read_block");
+ 	if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) {
+ 		printf("Read error: bad block in file '");
+ 		print_current_name();
+ 		printf("'\n");
+ 		memset(addr,0,BLOCK_SIZE);
+ 	}
+ 	return blk_chg;
+ }
+ 
+ /*
+  * write_block writes block nr to disk.
+  */
+ inline void write_block(unsigned int nr, char * addr)
+ {
+ 	if (!nr)
+ 		return;
+ 	if (nr < FIRSTZONE || nr >= ZONES) {
+ 		printf("Internal error: trying to write bad block\n"
+ 		"Write request ignored\n");
+ 		return;
+ 	}
+ 	if (BLOCK_SIZE*nr != lseek(IN, BLOCK_SIZE*nr, SEEK_SET))
+ 		die("seek failed in write_block");
+ 	if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) {
+ 		printf("Write error: bad block in file '");
+ 		print_current_name();
+ 		printf("'\n");
+ 	}
+ }
+ 
+ /*
+  * mapped-read-block reads block nr blknr from the specified file.
+  * it returns 1 if the inode has been changed due to bad zone nrs
+  */
+ inline int mapped_read_block(struct d_inode * inode,
+ 	unsigned int blknr, char * addr)
+ {
+ 	unsigned short ind[BLOCK_SIZE>>1];
+ 	unsigned short dind[BLOCK_SIZE>>1];
+ 	int result;
+ 
+ 	if (blknr<7)
+ 		return read_block(blknr + inode->i_zone,addr);
+ 	blknr -= 7;
+ 	if (blknr<512) {
+ 		result = read_block(7 + inode->i_zone, (char *) ind);
+ 		if (read_block(blknr + ind,addr))
+ 			write_block(inode->i_zone[7], (char *) ind);
+ 		return result;
+ 	}
+ 	blknr -= 512;
+ 	result = read_block(8 + inode->i_zone, (char *) dind);
+ 	if (read_block(blknr/512 + dind, (char *) ind))
+ 		write_block(inode->i_zone[8], (char *) dind);
+ 	if (read_block(blknr%512 + ind,addr))
+ 		write_block(dind[blknr/512], (char *) ind);
+ 	return result;
+ }
+ 
+ void write_tables(void)
+ {
+ 	if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
+ 		die("seek failed in write_tables");
+ 	if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE))
+ 		die("unable to write super-block");
+ 	if (IMAPS*BLOCK_SIZE != write(IN,inode_map,IMAPS*BLOCK_SIZE))
+ 		die("Unable to write inode map");
+ 	if (ZMAPS*BLOCK_SIZE != write(IN,zone_map,ZMAPS*BLOCK_SIZE))
+ 		die("Unable to write zone map");
+ 	if (INODE_BUFFER_SIZE != write(IN,inode_buffer,INODE_BUFFER_SIZE))
+ 		die("Unable to write inodes");
+ }
+ 
+ void read_tables(void)
+ {
+ 	memset(inode_map,0,sizeof(inode_map));
+ 	memset(zone_map,0,sizeof(zone_map));
+ 	if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
+ 		die("seek failed");
+ 	if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE))
+ 		die("unable to read super block");
+ 	if (MAGIC != LINUX_SUPER_MAGIC)
+ 		die("bad magic number in super-block");
+ 	if (ZONESIZE != 0 || BLOCK_SIZE != 1024)
+ 		die("Only 1k blocks/zones supported");
+ 	if (!IMAPS || IMAPS > LINUX_I_MAP_SLOTS)
+ 		die("bad s_imap_blocks field in super-block");
+ 	if (!ZMAPS || ZMAPS > LINUX_Z_MAP_SLOTS)
+ 		die("bad s_zmap_blocks field in super-block");
+ 	inode_buffer = malloc(INODE_BUFFER_SIZE);
+ 	if (!inode_buffer)
+ 		die("Unable to allocate buffer for inodes");
+ 	inode_count = malloc(INODES);
+ 	if (!inode_count)
+ 		die("Unable to allocate buffer for inode count");
+ 	zone_count = malloc(ZONES);
+ 	if (!zone_count)
+ 		die("Unable to allocate buffer for zone count");
+ 	if (IMAPS*BLOCK_SIZE != read(IN,inode_map,IMAPS*BLOCK_SIZE))
+ 		die("Unable to read inode map");
+ 	if (ZMAPS*BLOCK_SIZE != read(IN,zone_map,ZMAPS*BLOCK_SIZE))
+ 		die("Unable to read zone map");
+ 	if (INODE_BUFFER_SIZE != read(IN,inode_buffer,INODE_BUFFER_SIZE))
+ 		die("Unable to read inodes");
+ 	if (NORM_FIRSTZONE != FIRSTZONE)
+ 		printf("Warning: Firstzone != Norm_firstzone\n");
+ 	if (show) {
+ 		printf("%d inodes\n",INODES);
+ 		printf("%d blocks\n",ZONES);
+ 		printf("Firstdatazone=%d (%d)\n",FIRSTZONE,NORM_FIRSTZONE);
+ 		printf("Zonesize=%d\n",BLOCK_SIZE<<ZONESIZE);
+ 		printf("Maxsize=%d\n\n",MAXSIZE);
+ 	}
+ }
+ 
+ struct d_inode * get_inode(unsigned int nr)
+ {
+ 	struct d_inode * inode;
+ 
+ 	if (!nr || nr > INODES)
+ 		return NULL;
+ 	total++;
+ 	inode = Inode + nr;
+ 	if (!inode_count[nr]) {
+ 		if (!inode_in_use(nr)) {
+ 			printf("Inode %d marked not used, but used for file '",
+ 				nr);
+ 			print_current_name();
+ 			printf("'\n");
+ 			if (repair)
+ 				if (ask("Mark in use",1))
+ 					mark_inode(nr);
+ 		}
+ 		if (S_ISDIR(inode->i_mode))
+ 			directory++;
+ 		else if (S_ISREG(inode->i_mode))
+ 			regular++;
+ 		else if (S_ISCHR(inode->i_mode))
+ 			chardev++;
+ 		else if (S_ISBLK(inode->i_mode))
+ 			blockdev++;
+ 		else if (S_ISLNK(inode->i_mode))
+ 			symlinks++;
+ 	} else
+ 		links++;
+ 	if (!++inode_count[nr]) {
+ 		printf("Warning: inode count too big.\n");
+ 		inode_count[nr]--;
+ 	}
+ 	return inode;
+ }
+ 
+ void check_root(void)
+ {
+ 	struct d_inode * inode = Inode + ROOT_INO;
+ 
+ 	if (!inode || !S_ISDIR(inode->i_mode))
+ 		die("root inode isn't a directory");
+ }
+ 
+ static int add_zone(unsigned short * znr)
+ {
+ 	int result;
+ 
+ 	result=check_zone_nr(znr);
+ 	if (!*znr || *znr >= ZONES)
+ 		return result;
+ 	if (zone_count[*znr]) {
+ 		printf("Block has been used before. Now in file `");
+ 		print_current_name();
+ 		printf("'.");
+ 		if (ask("Clear",1)) {
+ 			*znr = 0;
+ 			changed = 1;
+ 		}
+ 	}
+ 	if (!*znr || *znr >= ZONES)
+ 		return result;
+ 	if (!zone_in_use(*znr)) {
+ 		printf("Block %d in file `",*znr);
+ 		print_current_name();
+ 		printf("' is marked not in use.");
+ 		if (ask("Correct",1))
+ 			mark_zone(*znr);
+ 	}
+ 	if (!++zone_count[*znr])
+ 		zone_count[*znr]--;
+ 	return result;
+ }
+ 
+ static int add_zone_ind(unsigned short * znr)
+ {
+ 	static char blk[BLOCK_SIZE];
+ 	int i, result, chg_blk=0;
+ 
+ 	result = add_zone(znr);
+ 	if (!*znr || *znr>=ZONES)
+ 		return result;
+ 	read_block(znr,blk);
+ 	for (i=0 ; i < (BLOCK_SIZE>>1) ; i++)
+ 		chg_blk |= add_zone(i + (unsigned short *) blk);
+ 	if (chg_blk)
+ 		write_block(*znr,blk);
+ 	return result;
+ }
+ 
+ static int add_zone_dind(unsigned short * znr)
+ {
+ 	static char blk[BLOCK_SIZE];
+ 	int i, result, blk_chg=0;
+ 
+ 	result = add_zone(znr);
+ 	if (!*znr || *znr >= ZONES)
+ 		return result;
+ 	read_block(znr,blk);
+ 	for (i=0 ; i < (BLOCK_SIZE>>1) ; i++)
+ 		blk_chg |= add_zone_ind(i + (unsigned short *) blk);
+ 	if (blk_chg)
+ 		write_block(*znr,blk);
+ 	return result;
+ }
+ 
+ void check_zones(unsigned int i)
+ {
+ 	struct d_inode * inode;
+ 
+ 	if (!i || i >= INODES)
+ 		return;
+ 	if (inode_count[i] > 1)	/* have we counted this file already? */
+ 		return;
+ 	inode = Inode + i;
+ 	if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
+ 	    !S_ISLNK(inode->i_mode))
+ 		return;
+ 	for (i=0 ; i<7 ; i++)
+ 		add_zone(i + inode->i_zone);
+ 	add_zone_ind(7 + inode->i_zone);
+ 	add_zone_dind(8 + inode->i_zone);
+ }
+ 
+ void check_file(struct d_inode * dir, unsigned int offset)
+ {
+ 	static char blk[BLOCK_SIZE];
+ 	struct d_inode * inode;
+ 	int ino;
+ 	char * name;
+ 
+ 	changed |= mapped_read_block(dir,offset/BLOCK_SIZE,blk);
+ 	name = blk + (offset % BLOCK_SIZE) + 2;
+ 	ino = * (unsigned short *) (name-2);
+ 	inode = get_inode(ino);
+ 	if (!offset)
+ 		if (!inode || strcmp(".",name)) {
+ 			print_current_name();
+ 			printf(": bad directory: '.' isn't first\n");
+ 		} else return;
+ 	if (offset == 32)
+ 		if (!inode || strcmp("..",name)) {
+ 			print_current_name();
+ 			printf(": bad directory: '..' isn't second\n");
+ 		} else return;
+ 	if (!inode)
+ 		return;
+ 	if (name_depth < MAX_DEPTH)
+ 		strncpy(name_list[name_depth],name,30);
+ 	name_depth++;	
+ 	if (list) {
+ 		if (verbose)
+ 			printf("%6d %07o ",ino,inode->i_mode);
+ 		print_current_name();
+ 		if (S_ISDIR(inode->i_mode))
+ 			printf(":\n");
+ 		else
+ 			printf("\n");
+ 	}
+ 	check_zones(ino);
+ 	if (inode && S_ISDIR(inode->i_mode))
+ 		recursive_check(ino);
+ 	name_depth--;
+ 	return;
+ }
+ 
+ void recursive_check(unsigned int ino)
+ {
+ 	struct d_inode * dir;
+ 	unsigned int offset;
+ 
+ 	dir = Inode + ino;
+ 	if (!S_ISDIR(dir->i_mode))
+ 		die("internal error");
+ 	if (dir->i_size < 64) {
+ 		print_current_name();
+ 		printf(": bad directory: size<64");
+ 	}
+ 	for (offset = 0 ; offset < dir->i_size ; offset += 32)
+ 		check_file(dir,offset);
+ }
+ 
+ int bad_zone(int i)
+ {
+ 	char buffer[1024];
+ 
+ 	if (BLOCK_SIZE*i != lseek(IN, BLOCK_SIZE*i, SEEK_SET))
+ 		die("seek failed in bad_zone");
+ 	return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE));
+ }
+ 
+ void check_counts(void)
+ {
+ 	int i;
+ 
+ 	for (i=1 ; i < INODES ; i++) {
+ 		if (!inode_in_use(i) && Inode[i].i_mode && warn_mode) {
+ 			printf("Inode %d mode not cleared.",i);
+ 			if (ask("Clear",1)) {
+ 				Inode[i].i_mode = 0;
+ 				changed = 1;
+ 			}
+ 		}
+ 		if (inode_in_use(i)*Inode[i].i_nlinks == inode_count[i])
+ 			continue;
+ 		if (!inode_count[i]) {
+ 			printf("Inode %d not used, marked used in the bitmap.",
+ 				i);
+ 			if (ask("Clear",1))
+ 				unmark_inode(i);
+ 		} else if (!inode_in_use(i)) {
+ 			printf("Inode %d used, marked unused in the bitmap.",
+ 				i);
+ 			if (ask("Set",1))
+ 				mark_inode(i);
+ 		}
+ 		if (inode_in_use(i) && Inode[i].i_nlinks != inode_count[i]) {
+ 			printf("Inode %d, i_nlinks=%d, counted=%d.",
+ 				i,Inode[i].i_nlinks,inode_count[i]);
+ 			if (ask("Set i_nlinks to count",1)) {
+ 				Inode[i].i_nlinks=inode_count[i];
+ 				changed=1;
+ 			}
+ 		}
+ 	}
+ 	for (i=FIRSTZONE ; i < ZONES ; i++) {
+ 		if (zone_in_use(i) == zone_count[i])
+ 			continue;
+ 		if (!zone_count[i]) {
+ 			if (bad_zone(i))
+ 				continue;
+ 			printf("Zone %d: marked in use, no file uses it.",i);
+ 			if (ask("Unmark",1))
+ 				unmark_zone(i);
+ 			continue;
+ 		}
+ 		printf("Zone %d: %sin use, counted=%d\n",
+ 		i,zone_in_use(i)?"":"not ",zone_count[i]);
+ 	}
+ }
+ 
+ void check(void)
+ {
+ 	memset(inode_count,0,INODES*sizeof(*inode_count));
+ 	memset(zone_count,0,ZONES*sizeof(*zone_count));
+ 	check_zones(ROOT_INO);
+ 	recursive_check(ROOT_INO);
+ 	check_counts();
+ }
+ 
+ int main(int argc, char ** argv)
+ {
+ 	struct termios termios,tmp;
+ 	int count;
+ 
+ 	if (argc && *argv)
+ 		program_name = *argv;
+ 	if (INODE_SIZE * LINUX_INODES_PER_BLOCK != BLOCK_SIZE)
+ 		die("bad inode size");
+ 	while (argc-- > 1) {
+ 		argv++;
+ 		if (argv[0][0] != '-')
+ 			if (device_name)
+ 				usage();
+ 			else
+ 				device_name = argv[0];
+ 		else while (*++argv[0])
+ 			switch (argv[0][0]) {
+ 				case 'l': list=1; break;
+ 				case 'a': automatic=1; repair=1; break;
+ 				case 'r': automatic=0; repair=1; break;
+ 				case 'v': verbose=1; break;
+ 				case 's': show=1; break;
+ 				case 'm': warn_mode=1; break;
+ 				default: usage();
+ 			}
+ 	}
+ 	if (!device_name)
+ 		usage();
+ 	if (repair && !automatic) {
+ 		if (!isatty(0) || !isatty(1))
+ 			die("need terminal for interactive repairs");
+ 		tcgetattr(0,&termios);
+ 		tmp = termios;
+ 		tmp.c_lflag &= ~(ICANON|ECHO);
+ 		tcsetattr(0,TCSANOW,&tmp);
+ 	}
+ 	IN = open(device_name,repair?O_RDWR:O_RDONLY);
+ 	if (IN < 0)
+ 		die("unable to open '%s'");
+ 	for (count=0 ; count<3 ; count++)
+ 		sync();
+ 	read_tables();
+ 	check_root();
+ 	check();
+ 	if (verbose) {
+ 		int i, free;
+ 
+ 		for (i=1,free=0 ; i<INODES ; i++)
+ 			if (!inode_in_use(i))
+ 				free++;
+ 		printf("\n%6d inodes used (%d%%)\n",(INODES-1-free),
+ 			100*(INODES-1-free)/INODES);
+ 		for (i=FIRSTZONE,free=0 ; i<ZONES ; i++)
+ 			if (!zone_in_use(i))
+ 				free++;
+ 		printf("%6d zones used (%d%%)\n",(ZONES-free),
+ 			100*(ZONES-free)/ZONES);
+ 		printf("\n%6d regular files\n"
+ 		"%6d directories\n"
+ 		"%6d character device files\n"
+ 		"%6d block device files\n"
+ 		"%6d links\n"
+ 		"%6d symbolic links\n"
+ 		"------\n"
+ 		"%6d files\n",
+ 		regular,directory,chardev,blockdev,
+ 		links-2*directory+1,symlinks,total-2*directory+1);
+ 	}
+ 	if (changed) {
+ 		write_tables();
+ 		printf(	"----------------------------\n"
+ 			"FILE SYSTEM HAS BEEN CHANGED\n"
+ 			"----------------------------\n");
+ 		for (count=0 ; count<3 ; count++)
+ 			sync();
+ 	}
+ 	if (repair && !automatic)
+ 		tcsetattr(0,TCSANOW,&termios);
+ 	return (0);
+ }
diff -r -c -N linux/fs/linux/linuxfs.msg linux993l/fs/linux/linuxfs.msg
*** linux/fs/linux/linuxfs.msg
--- linux993l/fs/linux/linuxfs.msg	Fri Jan 15 12:55:33 1993
***************
*** 0 ****
--- 1,108 ----
+ Rick,
+   i followed the instructions u gave in the message below, using magic nr:
+ 
+ #define LINUX_SUPER_MAGIC	0x138F
+ #define NEW_LINUX_SUPER_MAGIC	0x2469
+ 
+ recompiled and the filesystem seems to work fine (untarred files with 
+ long names, mv, cp ). ur `skeleton' was very helpful for me (not a 
+ programmer, cept in elisp,tex and metafont)
+ 
+  however, lfsck is broken..any suggestions about what i need to change
+ in lfsck.c?
+ 
+ -------
+ Rick's reply:
+ 
+ Sorry for the delay.  As you can guess, this was just an experiment
+ and I didn't follow through and test out lfsck.  It got blown away
+ with my last upgrade and I don't have time to repeat it all now.  But
+ from looking at it I would try changing the "magic" dependencies
+ rooted in the numbers 14 or 16.  Obviously, 14 should be changed to 30
+ and 16 should be changed to 32.  Also, 32 should be changed to 64,
+ etc.  I think that might be all you need.
+ 
+ Good luck,
+ 
+ Rick
+ 
+ -----------------
+ did the above patches to fsck (lfsck)..works great!
+ 
+ ---------------------------------------------------
+ Rick Sladkey's jrs@world.std.com
+ msg on making minix fs with longer filenames:
+ ---------------------------------------------------
+ 
+ Better not to mess with the minix file system.  If you really want to
+ do this, here is a procedure.  This is just a skeleton, I might
+ have forgotten something.
+ 
+ First create a directory and a new filesystem type called say "linux"
+ based on the minix one.  You can do this as follows:
+ 
+ $ cd /usr/src/linux/fs
+ $ mkdir linux
+ $ cd minix
+ $ for i in Makefile *.c
+ > do
+ >	sed -e 's/MINIX/LINUX/g' -e 's/minix/linux/g' $i >../linux/$i
+ > done
+ $
+ 
+ Then do the same thing for the include files:
+ 
+ $ cd /usr/src/linux/include
+ $ for i in fs.h fs_i.h fs_sb.h
+ > do
+ >	sed -e 's/MINIX/LINUX/g' -e 's/minix/linux/g' minix_$i >linux_$i
+ > done
+ $
+ 
+ Now edit /usr/src/include/linux/fs.h and add entries for "linux" just
+ like you see for "minix".  Search for minix and you will get the idea.
+ 
+ Then add the "linux" filesystem type to the superblock table in
+ /usr/src/linux/fs/filesystems.c.  Again, you should be able to figure
+ out what to do by looking at the other filesystems there.
+ 
+ Then add the "linux" subdirectory to the /usr/src/linux/fs/Makefile.
+ 
+ Finally add an entry into /usr/src/linux/config.in for the new
+ filesystem type and rerun make config.
+ 
+ After rebuilding the kernel, you will have a new filesystem that is
+ called "linux" but behaves exactly like the "minix" one does.
+ 
+ Now go ahead and make the change you are proposing.  Edit
+ /usr/src/linux/include/linux/linux_fs.h and change the define of
+ LINUX_NAME_LEN from 14 to 30, 62, 126, 254, 510 or 1022.  I recommend
+ 30.  You will pay for it if you make it too large.  Also change the
+ filesystem magic number so you don't get any accidents with similar
+ filesystem types.
+ 
+ Rebuild the kernel again and you have a new filesystem type that is
+ much like the minix one but allows filenames to be up to 30 characters
+ in length.
+ 
+ Now you have to create a new mkfs and fsck for the filesystem type of
+ "linux".  Get system-0.97.tar.Z (or whatever) and perform the sed
+ trick to create mklfs.c from mkmfs.c and lfsck.c from mfsck.c.  There
+ is a dependency on the number 16 in mkmfs.c.  Fix the lines that have
+ the "\0\0\0" stuff in them and add 16 more "\0"s to each one.  Then
+ search for the numbers 32 and 48 and change them to 2*32 and 3*32.
+ 
+ Now make mklfs.  You should be able to use mklfs to make a new
+ filesystem on a partition.
+ 
+ Then you can mount it in the obvious way, "mount -t linux /dev/disk
+ /mnt" and test that it works.  Do "ls -al" and make sure the "." and
+ ".."  entries are OK.  Touch a file with a name longer that 14 chars.
+ Untar an archive, etc.
+ 
+ You did say that you have a complete backup, didn't you?  I thought so.
+ --
+ Rick Sladkey
+ jrs@world.std.com
+ 
+ 
diff -r -c -N linux/fs/linux/mklfs.c linux993l/fs/linux/mklfs.c
*** linux/fs/linux/mklfs.c
--- linux993l/fs/linux/mklfs.c	Fri Jan 15 14:41:24 1993
***************
*** 0 ****
--- 1,451 ----
+ /*
+  * mkfs.c - make a linux (linux) file-system.
+  *
+  * (C) 1991 Linus Torvalds. This file may be redistributed as per
+  * the Linux copyright.
+  * mklfs.c patched for long filenames (as per sladkey's msg) --tgd
+ 
+  */
+ 
+ /*
+  * 24.11.91  -	time began. Used the fsck sources to get started.
+  *
+  * 25.11.91  -	corrected some bugs. Added support for ".badblocks"
+  *		The algorithm for ".badblocks" is a bit weird, but
+  *		it should work. Oh, well.
+  *
+  * 25.01.92  -  Added the -l option for getting the list of bad blocks
+  *              out of a named file. (Dave Rivers, rivers@ponds.uucp)
+  *
+  * 28.02.92  -	added %-information when using -c.
+  *
+  * Usage:  mkfs [-c] device size-in-blocks
+  *         mkfs [-l filename ] device size-in-blocks
+  *
+  *	-c for readablility checking (SLOW!)
+  *      -l for getting a list of bad blocks from a file.
+  *
+  * The device may be a block device or a image of one, but this isn't
+  * enforced (but it's not much fun on a character device :-). 
+  */
+ 
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <signal.h>
+ #include <fcntl.h>
+ #include <ctype.h>
+ #include <stdlib.h>
+ #include <termios.h>
+ #include <sys/stat.h>
+ 
+ #include <linux/fs.h>
+ #include <linux/linux_fs.h>
+ 
+ #ifndef __GNUC__
+ #error "needs gcc for the bitop-__asm__'s"
+ #endif
+ 
+ #ifndef __linux__
+ #define volatile
+ #endif
+ 
+ #define LINUX_ROOT_INO 1
+ #define LINUX_BAD_INO 2
+ 
+ #define TEST_BUFFER_BLOCKS 16
+ #define MAX_GOOD_BLOCKS 512
+ 
+ #define UPPER(size,n) ((size+((n)-1))/(n))
+ #define INODE_SIZE (sizeof(struct linux_inode))
+ #define INODE_BLOCKS UPPER(INODES,LINUX_INODES_PER_BLOCK)
+ #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
+ 
+ #define BITS_PER_BLOCK (BLOCK_SIZE<<3)
+ 
+ static char * program_name = "mkfs";
+ static char * device_name = NULL;
+ static int DEV = -1;
+ static long BLOCKS = 0;
+ static int check = 0;
+ static int badblocks = 0;
+ 
+ #define ROOT_INO_STRING "\001\000"
+ #define BAD_INO_STRING "\002\000"
+ 
+ static char root_block[BLOCK_SIZE] =
+ ROOT_INO_STRING ".\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ ROOT_INO_STRING "..\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ BAD_INO_STRING  ".badblocks\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+ 
+ static char * inode_buffer = NULL;
+ #define Inode (((struct linux_inode *) inode_buffer)-1)
+ static char super_block_buffer[BLOCK_SIZE];
+ #define Super (*(struct linux_super_block *)super_block_buffer)
+ #define INODES ((unsigned long)Super.s_ninodes)
+ #define ZONES ((unsigned long)Super.s_nzones)
+ #define IMAPS ((unsigned long)Super.s_imap_blocks)
+ #define ZMAPS ((unsigned long)Super.s_zmap_blocks)
+ #define FIRSTZONE ((unsigned long)Super.s_firstdatazone)
+ #define ZONESIZE ((unsigned long)Super.s_log_zone_size)
+ #define MAXSIZE ((unsigned long)Super.s_max_size)
+ #define MAGIC (Super.s_magic)
+ #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS)
+ 
+ static char inode_map[BLOCK_SIZE * LINUX_I_MAP_SLOTS];
+ static char zone_map[BLOCK_SIZE * LINUX_Z_MAP_SLOTS];
+ 
+ static unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
+ static int used_good_blocks = 0;
+ 
+ #define bitop(name,op) \
+ static inline int name(char * addr,unsigned int nr) \
+ { \
+ int __res; \
+ __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
+ :"=g" (__res) \
+ :"r" (nr),"m" (*(addr)),"0" (0)); \
+ return __res; \
+ }
+ 
+ bitop(bit,"")
+ bitop(setbit,"s")
+ bitop(clrbit,"r")
+ 
+ #define inode_in_use(x) (bit(inode_map,(x)))
+ #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1))
+ 
+ #define mark_inode(x) (setbit(inode_map,(x)))
+ #define unmark_inode(x) (clrbit(inode_map,(x)))
+ 
+ #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1))
+ #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1))
+ 
+ /*
+  * Volatile to let gcc know that this doesn't return. When trying
+  * to compile this under linux, volatile gives a warning, as
+  * exit() isn't defined as volatile under linux.
+  */
+ volatile void fatal_error(const char * fmt_string) {
+ 	fprintf(stderr,fmt_string,program_name,device_name);
+ 	exit(1);
+ }
+ 
+ #define usage() fatal_error("usage: %s [-c | -l filename] /dev/name blocks\n")
+ #define die(str) fatal_error("%s: " str "\n")
+ 
+ void write_tables(void) {
+ 
+ 	if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET))
+ 		die("seek failed in write_tables");
+ 	if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE))
+ 		die("unable to write super-block");
+ 	if (IMAPS*BLOCK_SIZE != write(DEV,inode_map,IMAPS*BLOCK_SIZE))
+ 		die("Unable to write inode map");
+ 	if (ZMAPS*BLOCK_SIZE != write(DEV,zone_map,ZMAPS*BLOCK_SIZE))
+ 		die("Unable to write zone map");
+ 	if (INODE_BUFFER_SIZE != write(DEV,inode_buffer,INODE_BUFFER_SIZE))
+ 		die("Unable to write inodes");
+ }
+ 
+ void write_block(int blk, char *buffer) {
+ 
+ 	if (blk*BLOCK_SIZE != lseek(DEV, blk*BLOCK_SIZE, SEEK_SET))
+ 		die("seek failed in write_block");
+ 	if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE))
+ 		die("write failed in write_block");
+ }
+ 
+ int get_free_block(void) {
+ 
+ 	int blk;
+ 
+ 	if (used_good_blocks+1 >= MAX_GOOD_BLOCKS)
+ 		die("too many bad blocks");
+ 	if (used_good_blocks)
+ 		blk = good_blocks_table[used_good_blocks-1]+1;
+ 	else
+ 		blk = FIRSTZONE;
+ 	while (blk < ZONES && zone_in_use(blk))
+ 		blk++;
+ 	if (blk >= ZONES)
+ 		die("not enough good blocks");
+ 	good_blocks_table[used_good_blocks] = blk;
+ 	used_good_blocks++;
+ 	return blk;
+ }
+ 
+ void mark_good_blocks(void) {
+ 
+ 	int blk;
+ 
+ 	for (blk=0 ; blk < used_good_blocks ; blk++)
+ 		mark_zone(good_blocks_table[blk]);
+ }
+ 
+ inline int next(int zone) {
+ 
+ 	if (!zone)
+ 		zone = FIRSTZONE-1;
+ 	while (++zone < ZONES)
+ 		if (zone_in_use(zone))
+ 			return zone;
+ 	return 0;
+ }
+ 
+ void make_bad_inode(void) {
+ 
+ 	struct linux_inode * inode = &Inode[LINUX_BAD_INO];
+ 	int i,j,zone;
+ 	int ind=0,dind=0;
+ 	unsigned short ind_block[BLOCK_SIZE>>1];
+ 	unsigned short dind_block[BLOCK_SIZE>>1];
+ 
+ #define NEXT_BAD (zone = next(zone))
+ 
+ 	if (!badblocks)
+ 		return;
+ 	mark_inode(LINUX_BAD_INO);
+ 	inode->i_nlinks = 1;
+ 	inode->i_time = time(NULL);
+ 	inode->i_mode = S_IFREG + 0000;
+ 	inode->i_size = badblocks*BLOCK_SIZE;
+ 	zone = next(0);
+ 	for (i=0 ; i<7 ; i++) {
+ 		inode->i_zone[i] = zone;
+ 		if (!NEXT_BAD)
+ 			goto end_bad;
+ 	}
+ 	inode->i_zone[7] = ind = get_free_block();
+ 	memset(ind_block,0,BLOCK_SIZE);
+ 	for (i=0 ; i<512 ; i++) {
+ 		ind_block[i] = zone;
+ 		if (!NEXT_BAD)
+ 			goto end_bad;
+ 	}
+ 	inode->i_zone[8] = dind = get_free_block();
+ 	memset(dind_block,0,BLOCK_SIZE);
+ 	for (i=0 ; i<512 ; i++) {
+ 		write_block(ind,(char *) ind_block);
+ 		dind_block[i] = ind = get_free_block();
+ 		memset(ind_block,0,BLOCK_SIZE);
+ 		for (j=0 ; j<512 ; j++) {
+ 			ind_block[j] = zone;
+ 			if (!NEXT_BAD)
+ 				goto end_bad;
+ 		}
+ 	}
+ 	die("too many bad blocks");
+ end_bad:
+ 	if (ind)
+ 		write_block(ind, (char *) ind_block);
+ 	if (dind)
+ 		write_block(dind, (char *) dind_block);
+ }
+ 
+ void make_root_inode(void) {
+ 
+ 	struct linux_inode *inode = &Inode[LINUX_ROOT_INO];
+ 
+ 	mark_inode(LINUX_ROOT_INO);
+ 	inode->i_zone[0] = get_free_block();
+ 	inode->i_nlinks = 2;
+ 	inode->i_time = time(NULL);
+ 	if (badblocks)
+ 		inode->i_size = 3*32;
+ 	else
+ 		inode->i_size = 2*32;
+ 	inode->i_mode = S_IFDIR + 0755;
+ 	write_block(inode->i_zone[0],root_block);
+ }
+ 
+ void setup_tables(void) {
+ 	int i;
+ 
+ 	memset(inode_map,0xff,sizeof(inode_map));
+ 	memset(zone_map,0xff,sizeof(zone_map));
+ 	memset(super_block_buffer,0,BLOCK_SIZE);
+ 	MAGIC = LINUX_SUPER_MAGIC;
+ 	ZONESIZE = 0;
+ 	MAXSIZE = (7+512+512*512)*1024;
+ 	ZONES = BLOCKS;
+ /* some magic nrs: 1 inode / 3 blocks */
+ 	INODES = BLOCKS/3;
+ /* I don't want some off-by-one errors, so this hack... */
+ 	if ((INODES & 8191) > 8188)
+ 		INODES -= 5;
+ 	if ((INODES & 8191) < 10)
+ 		INODES -= 20;
+ 	IMAPS = UPPER(INODES,BITS_PER_BLOCK);
+ 	ZMAPS = 0;
+ 	while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK))
+ 		ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK);
+ 	FIRSTZONE = NORM_FIRSTZONE;
+ 	for (i = FIRSTZONE ; i<ZONES ; i++)
+ 		unmark_zone(i);
+ 	for (i = LINUX_ROOT_INO ; i<INODES ; i++)
+ 		unmark_inode(i);
+ 	inode_buffer = malloc(INODE_BUFFER_SIZE);
+ 	if (!inode_buffer)
+ 		die("Unable to allocate buffer for inodes");
+ 	memset(inode_buffer,0,INODE_BUFFER_SIZE);
+ 	printf("%d inodes\n",INODES);
+ 	printf("%d blocks\n",ZONES);
+ 	printf("Firstdatazone=%d (%d)\n",FIRSTZONE,NORM_FIRSTZONE);
+ 	printf("Zonesize=%d\n",BLOCK_SIZE<<ZONESIZE);
+ 	printf("Maxsize=%d\n\n",MAXSIZE);
+ }
+ 
+ /*
+  * Perform a test of a block; return the number of
+  * blocks readable/writeable.
+  */
+ long do_check(char * buffer, int try, unsigned int current_block) {
+ 
+ 	long got;
+ 	
+ 	/* Seek to the correct loc. */
+ 	if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) !=
+                        current_block * BLOCK_SIZE ) {
+                  die("seek failed during testing of blocks");
+ 	}
+ 
+ 
+ 	/* Try the read */
+ 	got = read(DEV, buffer, try * BLOCK_SIZE);
+ 	if (got < 0) got = 0;	
+ 	if (got & (BLOCK_SIZE - 1 )) {
+ 		printf("Weird values in do_check: probably bugs\n");
+ 	}
+ 	got /= BLOCK_SIZE;
+ 	return got;
+ }
+ 
+ static unsigned int currently_testing = 0;
+ 
+ void alarm_intr(int alnum) {
+ 	if (currently_testing > ZONES)
+ 		return;
+ 	signal(SIGALRM,alarm_intr);
+ 	alarm(5);
+ 	if (!currently_testing)
+ 		return;
+ 	printf("%d... ", currently_testing);
+ 	fflush(stdout);
+ }
+ 
+ void check_blocks(void) {
+ 
+ 	int try,got;
+ 	static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
+ 
+ 	currently_testing=0;
+ 	signal(SIGALRM,alarm_intr);
+ 	alarm(5);
+ 	while (currently_testing < ZONES) {
+ 		if (lseek(DEV,currently_testing*BLOCK_SIZE,SEEK_SET) !=
+ 		currently_testing*BLOCK_SIZE)
+ 			die("seek failed in check_blocks");
+ 		try = TEST_BUFFER_BLOCKS;
+ 		if (currently_testing + try > ZONES)
+ 			try = ZONES-currently_testing;
+ 		got = do_check(buffer, try, currently_testing);
+ 		currently_testing += got;
+ 		if (got == try)
+ 			continue;
+ 		if (currently_testing < FIRSTZONE)
+ 			die("bad blocks before data-area: cannot make fs");
+ 		mark_zone(currently_testing);
+ 		badblocks++;
+ 		currently_testing++;
+ 	}
+ 	if (badblocks)
+ 		printf("%d bad block%s\n",badblocks,(badblocks>1)?"s":"");
+ }
+ 
+ void get_list_blocks(char *filename) {
+ 
+ 	FILE *listfile;
+ 	unsigned long blockno;
+ 
+ 	listfile=fopen(filename,"r");
+ 	if(listfile == (FILE *)NULL) {
+ 		die("Can't open file of bad blocks");
+ 	}
+ 	while(!feof(listfile)) {
+ 		fscanf(listfile,"%d\n", &blockno);
+ 		mark_zone(blockno);
+ 		badblocks++;
+ 	}
+ 	if(badblocks) {
+ 		printf("%d bad block%s\n", badblocks, (badblocks>1)?"s":"");
+ 	}
+ }
+ 
+ int main(int argc, char **argv) {
+ 
+ 	char * tmp;
+ 	struct stat statbuf;
+ 	char * listfile = NULL;
+ 
+ 	if (argc && *argv)
+ 		program_name = *argv;
+ 	if (INODE_SIZE * LINUX_INODES_PER_BLOCK != BLOCK_SIZE)
+ 		die("bad inode size");
+ 	while (argc-- > 1) {
+ 		argv++;
+ 		if (argv[0][0] != '-')
+ 			if (device_name) {
+ 				BLOCKS = strtol(argv[0],&tmp,0);
+ 				if (*tmp) {
+ 					printf("strtol error");
+ 					usage();
+ 				}
+ 			} else
+ 				device_name = argv[0];
+ 		else { 
+ 			if(argv[0][1] == 'l') {
+ 				listfile = argv[1];
+ 				argv++;
+ 				if (!(argc--))
+ 					usage();
+ 			} else {
+                 		while (*(++argv[0])) {
+ 					switch (argv[0][0]) {
+ 						case 'c': check=1; break;
+ 						default: usage();
+ 					}
+ 				}
+ 			}
+ 		}
+ 	}
+ 	if (!device_name) {
+ 		usage();
+ 	}
+ 	if (BLOCKS < 10) {
+ 		die("number of blocks must be greater than 10.");
+ 	}
+ 	if (BLOCKS > 65536) {
+ 		die("number of blocks must be less than 65536.");
+ 	}
+ 	DEV = open(device_name,O_RDWR );
+ 	if (DEV<0)
+ 		die("unable to open %s");
+ 	if (fstat(DEV,&statbuf)<0)
+ 		die("unable to stat %s");
+ 	if (!S_ISBLK(statbuf.st_mode))
+ 		check=0;
+ 	else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
+ 		die("will not try to make filesystem on '%s'");
+ 	setup_tables();
+ 	if (check)
+ 		check_blocks();
+         else if (listfile)
+                 get_list_blocks(listfile);
+ 	make_root_inode();
+ 	make_bad_inode();
+ 	mark_good_blocks();
+ 	write_tables();
+ 	putchar('\n');
+ 	return 0;
+ }
diff -r -c -N linux/fs/linux/namei.c linux993l/fs/linux/namei.c
*** linux/fs/linux/namei.c
--- linux993l/fs/linux/namei.c	Mon Jan 11 10:47:11 1993
***************
*** 0 ****
--- 1,776 ----
+ /*
+  *  linux/fs/linux/namei.c
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  */
+ 
+ #include <linux/sched.h>
+ #include <linux/linux_fs.h>
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+ #include <linux/stat.h>
+ #include <linux/fcntl.h>
+ #include <linux/errno.h>
+ 
+ #include <asm/segment.h>
+ 
+ /*
+  * comment out this line if you want names > LINUX_NAME_LEN chars to be
+  * truncated. Else they will be disallowed.
+  */
+ /* #define NO_TRUNCATE */
+ 
+ /*
+  * ok, we cannot use strncmp, as the name is not in our data space.
+  * Thus we'll have to use linux_match. No big problem. Match also makes
+  * some sanity tests.
+  *
+  * NOTE! unlike strncmp, linux_match returns 1 for success, 0 for failure.
+  */
+ static int linux_match(int len,const char * name,struct linux_dir_entry * de)
+ {
+ 	register int same __asm__("ax");
+ 
+ 	if (!de || !de->inode || len > LINUX_NAME_LEN)
+ 		return 0;
+ 	/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
+ 	if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
+ 		return 1;
+ 	if (len < LINUX_NAME_LEN && de->name[len])
+ 		return 0;
+ 	__asm__("cld\n\t"
+ 		"fs ; repe ; cmpsb\n\t"
+ 		"setz %%al"
+ 		:"=a" (same)
+ 		:"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
+ 		:"cx","di","si");
+ 	return same;
+ }
+ 
+ /*
+  *	linux_find_entry()
+  *
+  * finds an entry in the specified directory with the wanted name. It
+  * returns the cache buffer in which the entry was found, and the entry
+  * itself (as a parameter - res_dir). It does NOT read the inode of the
+  * entry - you'll have to do that yourself if you want to.
+  */
+ static struct buffer_head * linux_find_entry(struct inode * dir,
+ 	const char * name, int namelen, struct linux_dir_entry ** res_dir)
+ {
+ 	int entries, i;
+ 	struct buffer_head * bh;
+ 	struct linux_dir_entry * de;
+ 
+ 	*res_dir = NULL;
+ 	if (!dir)
+ 		return NULL;
+ #ifdef NO_TRUNCATE
+ 	if (namelen > LINUX_NAME_LEN)
+ 		return NULL;
+ #else
+ 	if (namelen > LINUX_NAME_LEN)
+ 		namelen = LINUX_NAME_LEN;
+ #endif
+ 	entries = dir->i_size / (sizeof (struct linux_dir_entry));
+ 	bh = linux_bread(dir,0,0);
+ 	if (!bh)
+ 		return NULL;
+ 	i = 0;
+ 	de = (struct linux_dir_entry *) bh->b_data;
+ 	while (i < entries) {
+ 		if ((char *)de >= BLOCK_SIZE+bh->b_data) {
+ 			brelse(bh);
+ 			bh = linux_bread(dir,i/LINUX_DIR_ENTRIES_PER_BLOCK,0);
+ 			if (!bh) {
+ 				i += LINUX_DIR_ENTRIES_PER_BLOCK;
+ 				continue;
+ 			}
+ 			de = (struct linux_dir_entry *) bh->b_data;
+ 		}
+ 		if (linux_match(namelen,name,de)) {
+ 			*res_dir = de;
+ 			return bh;
+ 		}
+ 		de++;
+ 		i++;
+ 	}
+ 	brelse(bh);
+ 	return NULL;
+ }
+ 
+ int linux_lookup(struct inode * dir,const char * name, int len,
+ 	struct inode ** result)
+ {
+ 	int ino;
+ 	struct linux_dir_entry * de;
+ 	struct buffer_head * bh;
+ 
+ 	*result = NULL;
+ 	if (!dir)
+ 		return -ENOENT;
+ 	if (!S_ISDIR(dir->i_mode)) {
+ 		iput(dir);
+ 		return -ENOENT;
+ 	}
+ 	if (!(bh = linux_find_entry(dir,name,len,&de))) {
+ 		iput(dir);
+ 		return -ENOENT;
+ 	}
+ 	ino = de->inode;
+ 	brelse(bh);
+ 	if (!(*result = iget(dir->i_sb,ino))) {
+ 		iput(dir);
+ 		return -EACCES;
+ 	}
+ 	iput(dir);
+ 	return 0;
+ }
+ 
+ /*
+  *	linux_add_entry()
+  *
+  * adds a file entry to the specified directory, using the same
+  * semantics as linux_find_entry(). It returns NULL if it failed.
+  *
+  * NOTE!! The inode part of 'de' is left at 0 - which means you
+  * may not sleep between calling this and putting something into
+  * the entry, as someone else might have used it while you slept.
+  *
+  * Arggh. To avoid race-conditions, we copy the name into kernel
+  * space before actually writing it into the buffer...
+  */
+ static struct buffer_head * linux_add_entry(struct inode * dir,
+ 	const char * name, int namelen, struct linux_dir_entry ** res_dir)
+ {
+ 	int i;
+ 	struct buffer_head * bh;
+ 	struct linux_dir_entry * de;
+ 	char name_buffer[LINUX_NAME_LEN];
+ 
+ 	*res_dir = NULL;
+ 	if (!dir)
+ 		return NULL;
+ 	if (namelen > LINUX_NAME_LEN) {
+ #ifdef NO_TRUNCATE
+ 		return NULL;
+ #else
+ 		namelen = LINUX_NAME_LEN;
+ #endif
+ 	}
+ 	if (!namelen)
+ 		return NULL;
+ 	bh =  linux_bread(dir,0,0);
+ 	if (!bh)
+ 		return NULL;
+ 	for (i = 0; i < LINUX_NAME_LEN ; i++)
+ 		name_buffer[i] = (i<namelen) ? get_fs_byte(name+i) : 0;
+ 	i = 0;
+ 	de = (struct linux_dir_entry *) bh->b_data;
+ 	while (1) {
+ 		if ((char *)de >= BLOCK_SIZE+bh->b_data) {
+ 			brelse(bh);
+ 			bh = linux_bread(dir,i/LINUX_DIR_ENTRIES_PER_BLOCK,1);
+ 			if (!bh)
+ 				return NULL;
+ 			de = (struct linux_dir_entry *) bh->b_data;
+ 		}
+ 		if (i*sizeof(struct linux_dir_entry) >= dir->i_size) {
+ 			de->inode=0;
+ 			dir->i_size = (i+1)*sizeof(struct linux_dir_entry);
+ 			dir->i_dirt = 1;
+ 			dir->i_ctime = CURRENT_TIME;
+ 		}
+ 		if (!de->inode) {
+ 			dir->i_mtime = CURRENT_TIME;
+ 			memcpy(de->name,name_buffer,LINUX_NAME_LEN);
+ 			bh->b_dirt = 1;
+ 			*res_dir = de;
+ 			return bh;
+ 		}
+ 		de++;
+ 		i++;
+ 	}
+ 	brelse(bh);
+ 	return NULL;
+ }
+ 
+ int linux_create(struct inode * dir,const char * name, int len, int mode,
+ 	struct inode ** result)
+ {
+ 	struct inode * inode;
+ 	struct buffer_head * bh;
+ 	struct linux_dir_entry * de;
+ 
+ 	*result = NULL;
+ 	if (!dir)
+ 		return -ENOENT;
+ 	inode = linux_new_inode(dir);
+ 	if (!inode) {
+ 		iput(dir);
+ 		return -ENOSPC;
+ 	}
+ 	inode->i_op = &linux_file_inode_operations;
+ 	inode->i_mode = mode;
+ 	inode->i_dirt = 1;
+ 	bh = linux_add_entry(dir,name,len,&de);
+ 	if (!bh) {
+ 		inode->i_nlink--;
+ 		inode->i_dirt = 1;
+ 		iput(inode);
+ 		iput(dir);
+ 		return -ENOSPC;
+ 	}
+ 	de->inode = inode->i_ino;
+ 	bh->b_dirt = 1;
+ 	brelse(bh);
+ 	iput(dir);
+ 	*result = inode;
+ 	return 0;
+ }
+ 
+ int linux_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
+ {
+ 	struct inode * inode;
+ 	struct buffer_head * bh;
+ 	struct linux_dir_entry * de;
+ 
+ 	if (!dir)
+ 		return -ENOENT;
+ 	bh = linux_find_entry(dir,name,len,&de);
+ 	if (bh) {
+ 		brelse(bh);
+ 		iput(dir);
+ 		return -EEXIST;
+ 	}
+ 	inode = linux_new_inode(dir);
+ 	if (!inode) {
+ 		iput(dir);
+ 		return -ENOSPC;
+ 	}
+ 	inode->i_uid = current->euid;
+ 	inode->i_mode = mode;
+ 	inode->i_op = NULL;
+ 	if (S_ISREG(inode->i_mode))
+ 		inode->i_op = &linux_file_inode_operations;
+ 	else if (S_ISDIR(inode->i_mode)) {
+ 		inode->i_op = &linux_dir_inode_operations;
+ 		if (dir->i_mode & S_ISGID)
+ 			inode->i_mode |= S_ISGID;
+ 	}
+ 	else if (S_ISLNK(inode->i_mode))
+ 		inode->i_op = &linux_symlink_inode_operations;
+ 	else if (S_ISCHR(inode->i_mode))
+ 		inode->i_op = &linux_chrdev_inode_operations;
+ 	else if (S_ISBLK(inode->i_mode))
+ 		inode->i_op = &linux_blkdev_inode_operations;
+ 	else if (S_ISFIFO(inode->i_mode)) {
+ 		inode->i_op = &linux_fifo_inode_operations;
+ 		inode->i_pipe = 1;
+ 		PIPE_BASE(*inode) = NULL;
+ 		PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
+ 		PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
+ 		PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
+ 	}
+ 	if (S_ISBLK(mode) || S_ISCHR(mode))
+ 		inode->i_rdev = rdev;
+ 	inode->i_mtime = inode->i_atime = CURRENT_TIME;
+ 	inode->i_dirt = 1;
+ 	bh = linux_add_entry(dir,name,len,&de);
+ 	if (!bh) {
+ 		inode->i_nlink--;
+ 		inode->i_dirt = 1;
+ 		iput(inode);
+ 		iput(dir);
+ 		return -ENOSPC;
+ 	}
+ 	de->inode = inode->i_ino;
+ 	bh->b_dirt = 1;
+ 	brelse(bh);
+ 	iput(dir);
+ 	iput(inode);
+ 	return 0;
+ }
+ 
+ int linux_mkdir(struct inode * dir, const char * name, int len, int mode)
+ {
+ 	struct inode * inode;
+ 	struct buffer_head * bh, *dir_block;
+ 	struct linux_dir_entry * de;
+ 	
+ 	bh = linux_find_entry(dir,name,len,&de);
+ 	if (bh) {
+ 		brelse(bh);
+ 		iput(dir);
+ 		return -EEXIST;
+ 	}
+ 	if (dir->i_nlink > 250) {
+ 		iput(dir);
+ 		return -EMLINK;
+ 	}
+ 	inode = linux_new_inode(dir);
+ 	if (!inode) {
+ 		iput(dir);
+ 		return -ENOSPC;
+ 	}
+ 	inode->i_op = &linux_dir_inode_operations;
+ 	inode->i_size = 2 * sizeof (struct linux_dir_entry);
+ 	inode->i_mtime = inode->i_atime = CURRENT_TIME;
+ 	dir_block = linux_bread(inode,0,1);
+ 	if (!dir_block) {
+ 		iput(dir);
+ 		inode->i_nlink--;
+ 		inode->i_dirt = 1;
+ 		iput(inode);
+ 		return -ENOSPC;
+ 	}
+ 	de = (struct linux_dir_entry *) dir_block->b_data;
+ 	de->inode=inode->i_ino;
+ 	strcpy(de->name,".");
+ 	de++;
+ 	de->inode = dir->i_ino;
+ 	strcpy(de->name,"..");
+ 	inode->i_nlink = 2;
+ 	dir_block->b_dirt = 1;
+ 	brelse(dir_block);
+ 	inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
+ 	if (dir->i_mode & S_ISGID)
+ 		inode->i_mode |= S_ISGID;
+ 	inode->i_dirt = 1;
+ 	bh = linux_add_entry(dir,name,len,&de);
+ 	if (!bh) {
+ 		iput(dir);
+ 		inode->i_nlink=0;
+ 		iput(inode);
+ 		return -ENOSPC;
+ 	}
+ 	de->inode = inode->i_ino;
+ 	bh->b_dirt = 1;
+ 	dir->i_nlink++;
+ 	dir->i_dirt = 1;
+ 	iput(dir);
+ 	iput(inode);
+ 	brelse(bh);
+ 	return 0;
+ }
+ 
+ /*
+  * routine to check that the specified directory is empty (for rmdir)
+  */
+ static int empty_dir(struct inode * inode)
+ {
+ 	int nr, len;
+ 	struct buffer_head * bh;
+ 	struct linux_dir_entry * de;
+ 
+ 	len = inode->i_size / sizeof (struct linux_dir_entry);
+ 	if (len<2 || !(bh = linux_bread(inode,0,0))) {
+ 	    	printk("warning - bad directory on dev %04x\n",inode->i_dev);
+ 		return 1;
+ 	}
+ 	de = (struct linux_dir_entry *) bh->b_data;
+ 	if (de[0].inode != inode->i_ino || !de[1].inode || 
+ 	    strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
+ 	    	printk("warning - bad directory on dev %04x\n",inode->i_dev);
+ 		return 1;
+ 	}
+ 	nr = 2;
+ 	de += 2;
+ 	while (nr<len) {
+ 		if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
+ 			brelse(bh);
+ 			bh = linux_bread(inode,nr/LINUX_DIR_ENTRIES_PER_BLOCK,0);
+ 			if (!bh) {
+ 				nr += LINUX_DIR_ENTRIES_PER_BLOCK;
+ 				continue;
+ 			}
+ 			de = (struct linux_dir_entry *) bh->b_data;
+ 		}
+ 		if (de->inode) {
+ 			brelse(bh);
+ 			return 0;
+ 		}
+ 		de++;
+ 		nr++;
+ 	}
+ 	brelse(bh);
+ 	return 1;
+ }
+ 
+ int linux_rmdir(struct inode * dir, const char * name, int len)
+ {
+ 	int retval;
+ 	struct inode * inode;
+ 	struct buffer_head * bh;
+ 	struct linux_dir_entry * de;
+ 
+ 	inode = NULL;
+ 	bh = linux_find_entry(dir,name,len,&de);
+ 	retval = -ENOENT;
+ 	if (!bh)
+ 		goto end_rmdir;
+ 	retval = -EPERM;
+ 	if (!(inode = iget(dir->i_sb, de->inode)))
+ 		goto end_rmdir;
+ 	if ((dir->i_mode & S_ISVTX) && current->euid &&
+ 	   inode->i_uid != current->euid)
+ 		goto end_rmdir;
+ 	if (inode->i_dev != dir->i_dev)
+ 		goto end_rmdir;
+ 	if (inode == dir)	/* we may not delete ".", but "../dir" is ok */
+ 		goto end_rmdir;
+ 	if (!S_ISDIR(inode->i_mode)) {
+ 		retval = -ENOTDIR;
+ 		goto end_rmdir;
+ 	}
+ 	if (!empty_dir(inode)) {
+ 		retval = -ENOTEMPTY;
+ 		goto end_rmdir;
+ 	}
+ 	if (inode->i_count > 1) {
+ 		retval = -EBUSY;
+ 		goto end_rmdir;
+ 	}
+ 	if (inode->i_nlink != 2)
+ 		printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
+ 	de->inode = 0;
+ 	bh->b_dirt = 1;
+ 	inode->i_nlink=0;
+ 	inode->i_dirt=1;
+ 	dir->i_nlink--;
+ 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ 	dir->i_dirt=1;
+ 	retval = 0;
+ end_rmdir:
+ 	iput(dir);
+ 	iput(inode);
+ 	brelse(bh);
+ 	return retval;
+ }
+ 
+ int linux_unlink(struct inode * dir, const char * name, int len)
+ {
+ 	int retval;
+ 	struct inode * inode;
+ 	struct buffer_head * bh;
+ 	struct linux_dir_entry * de;
+ 
+ repeat:
+ 	retval = -ENOENT;
+ 	inode = NULL;
+ 	bh = linux_find_entry(dir,name,len,&de);
+ 	if (!bh)
+ 		goto end_unlink;
+ 	if (!(inode = iget(dir->i_sb, de->inode)))
+ 		goto end_unlink;
+ 	if (de->inode != inode->i_ino) {
+ 		iput(inode);
+ 		brelse(bh);
+ 		current->counter = 0;
+ 		schedule();
+ 		goto repeat;
+ 	}
+ 	retval = -EPERM;
+ 	if ((dir->i_mode & S_ISVTX) && !suser() &&
+ 	    current->euid != inode->i_uid &&
+ 	    current->euid != dir->i_uid)
+ 		goto end_unlink;
+ 	if (S_ISDIR(inode->i_mode))
+ 		goto end_unlink;
+ 	if (!inode->i_nlink) {
+ 		printk("Deleting nonexistent file (%04x:%d), %d\n",
+ 			inode->i_dev,inode->i_ino,inode->i_nlink);
+ 		inode->i_nlink=1;
+ 	}
+ 	de->inode = 0;
+ 	bh->b_dirt = 1;
+ 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ 	dir->i_dirt = 1;
+ 	inode->i_nlink--;
+ 	inode->i_ctime = CURRENT_TIME;
+ 	inode->i_dirt = 1;
+ 	retval = 0;
+ end_unlink:
+ 	brelse(bh);
+ 	iput(inode);
+ 	iput(dir);
+ 	return retval;
+ }
+ 
+ int linux_symlink(struct inode * dir, const char * name, int len, const char * symname)
+ {
+ 	struct linux_dir_entry * de;
+ 	struct inode * inode = NULL;
+ 	struct buffer_head * bh = NULL, * name_block = NULL;
+ 	int i;
+ 	char c;
+ 
+ 	if (!(inode = linux_new_inode(dir))) {
+ 		iput(dir);
+ 		return -ENOSPC;
+ 	}
+ 	inode->i_mode = S_IFLNK | 0777;
+ 	inode->i_op = &linux_symlink_inode_operations;
+ 	name_block = linux_bread(inode,0,1);
+ 	if (!name_block) {
+ 		iput(dir);
+ 		inode->i_nlink--;
+ 		inode->i_dirt = 1;
+ 		iput(inode);
+ 		return -ENOSPC;
+ 	}
+ 	i = 0;
+ 	while (i < 1023 && (c=get_fs_byte(symname++)))
+ 		name_block->b_data[i++] = c;
+ 	name_block->b_data[i] = 0;
+ 	name_block->b_dirt = 1;
+ 	brelse(name_block);
+ 	inode->i_size = i;
+ 	inode->i_dirt = 1;
+ 	bh = linux_find_entry(dir,name,len,&de);
+ 	if (bh) {
+ 		inode->i_nlink--;
+ 		inode->i_dirt = 1;
+ 		iput(inode);
+ 		brelse(bh);
+ 		iput(dir);
+ 		return -EEXIST;
+ 	}
+ 	bh = linux_add_entry(dir,name,len,&de);
+ 	if (!bh) {
+ 		inode->i_nlink--;
+ 		inode->i_dirt = 1;
+ 		iput(inode);
+ 		iput(dir);
+ 		return -ENOSPC;
+ 	}
+ 	de->inode = inode->i_ino;
+ 	bh->b_dirt = 1;
+ 	brelse(bh);
+ 	iput(dir);
+ 	iput(inode);
+ 	return 0;
+ }
+ 
+ int linux_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
+ {
+ 	struct linux_dir_entry * de;
+ 	struct buffer_head * bh;
+ 
+ 	if (S_ISDIR(oldinode->i_mode)) {
+ 		iput(oldinode);
+ 		iput(dir);
+ 		return -EPERM;
+ 	}
+ 	if (oldinode->i_nlink > 126) {
+ 		iput(oldinode);
+ 		iput(dir);
+ 		return -EMLINK;
+ 	}
+ 	bh = linux_find_entry(dir,name,len,&de);
+ 	if (bh) {
+ 		brelse(bh);
+ 		iput(dir);
+ 		iput(oldinode);
+ 		return -EEXIST;
+ 	}
+ 	bh = linux_add_entry(dir,name,len,&de);
+ 	if (!bh) {
+ 		iput(dir);
+ 		iput(oldinode);
+ 		return -ENOSPC;
+ 	}
+ 	de->inode = oldinode->i_ino;
+ 	bh->b_dirt = 1;
+ 	brelse(bh);
+ 	iput(dir);
+ 	oldinode->i_nlink++;
+ 	oldinode->i_ctime = CURRENT_TIME;
+ 	oldinode->i_dirt = 1;
+ 	iput(oldinode);
+ 	return 0;
+ }
+ 
+ static int subdir(struct inode * new, struct inode * old)
+ {
+ 	unsigned short fs;
+ 	int ino;
+ 	int result;
+ 
+ 	__asm__("mov %%fs,%0":"=r" (fs));
+ 	__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
+ 	new->i_count++;
+ 	result = 0;
+ 	for (;;) {
+ 		if (new == old) {
+ 			result = 1;
+ 			break;
+ 		}
+ 		if (new->i_dev != old->i_dev)
+ 			break;
+ 		ino = new->i_ino;
+ 		if (linux_lookup(new,"..",2,&new))
+ 			break;
+ 		if (new->i_ino == ino)
+ 			break;
+ 	}
+ 	iput(new);
+ 	__asm__("mov %0,%%fs"::"r" (fs));
+ 	return result;
+ }
+ 
+ #define PARENT_INO(buffer) \
+ (((struct linux_dir_entry *) (buffer))[1].inode)
+ 
+ #define PARENT_NAME(buffer) \
+ (((struct linux_dir_entry *) (buffer))[1].name)
+ 
+ /*
+  * rename uses retrying to avoid race-conditions: at least they should be minimal.
+  * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
+  * checks fail, it tries to restart itself again. Very practical - no changes
+  * are done until we know everything works ok.. and then all the changes can be
+  * done in one fell swoop when we have claimed all the buffers needed.
+  *
+  * Anybody can rename anything with this: the permission checks are left to the
+  * higher-level routines.
+  */
+ static int do_linux_rename(struct inode * old_dir, const char * old_name, int old_len,
+ 	struct inode * new_dir, const char * new_name, int new_len)
+ {
+ 	struct inode * old_inode, * new_inode;
+ 	struct buffer_head * old_bh, * new_bh, * dir_bh;
+ 	struct linux_dir_entry * old_de, * new_de;
+ 	int retval;
+ 
+ 	goto start_up;
+ try_again:
+ 	brelse(old_bh);
+ 	brelse(new_bh);
+ 	brelse(dir_bh);
+ 	iput(old_inode);
+ 	iput(new_inode);
+ 	current->counter = 0;
+ 	schedule();
+ start_up:
+ 	old_inode = new_inode = NULL;
+ 	old_bh = new_bh = dir_bh = NULL;
+ 	old_bh = linux_find_entry(old_dir,old_name,old_len,&old_de);
+ 	retval = -ENOENT;
+ 	if (!old_bh)
+ 		goto end_rename;
+ 	old_inode = iget(old_dir->i_sb, old_de->inode);
+ 	if (!old_inode)
+ 		goto end_rename;
+ 	retval = -EPERM;
+ 	if ((old_dir->i_mode & S_ISVTX) && 
+ 	    current->euid != old_inode->i_uid &&
+ 	    current->euid != old_dir->i_uid && !suser())
+ 		goto end_rename;
+ 	new_bh = linux_find_entry(new_dir,new_name,new_len,&new_de);
+ 	if (new_bh) {
+ 		new_inode = iget(new_dir->i_sb, new_de->inode);
+ 		if (!new_inode) {
+ 			brelse(new_bh);
+ 			new_bh = NULL;
+ 		}
+ 	}
+ 	if (new_inode == old_inode) {
+ 		retval = 0;
+ 		goto end_rename;
+ 	}
+ 	if (new_inode && S_ISDIR(new_inode->i_mode)) {
+ 		retval = -EEXIST;
+ 		goto end_rename;
+ 	}
+ 	retval = -EPERM;
+ 	if (new_inode && (new_dir->i_mode & S_ISVTX) && 
+ 	    current->euid != new_inode->i_uid &&
+ 	    current->euid != new_dir->i_uid && !suser())
+ 		goto end_rename;
+ 	if (S_ISDIR(old_inode->i_mode)) {
+ 		retval = -EEXIST;
+ 		if (new_bh)
+ 			goto end_rename;
+ 		retval = -EACCES;
+ 		if (!permission(old_inode, MAY_WRITE))
+ 			goto end_rename;
+ 		retval = -EINVAL;
+ 		if (subdir(new_dir, old_inode))
+ 			goto end_rename;
+ 		retval = -EIO;
+ 		dir_bh = linux_bread(old_inode,0,0);
+ 		if (!dir_bh)
+ 			goto end_rename;
+ 		if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
+ 			goto end_rename;
+ 		retval = -EMLINK;
+ 		if (new_dir->i_nlink > 250)
+ 			goto end_rename;
+ 	}
+ 	if (!new_bh)
+ 		new_bh = linux_add_entry(new_dir,new_name,new_len,&new_de);
+ 	retval = -ENOSPC;
+ 	if (!new_bh)
+ 		goto end_rename;
+ /* sanity checking before doing the rename - avoid races */
+ 	if (new_inode && (new_de->inode != new_inode->i_ino))
+ 		goto try_again;
+ 	if (new_de->inode && !new_inode)
+ 		goto try_again;
+ 	if (old_de->inode != old_inode->i_ino)
+ 		goto try_again;
+ /* ok, that's it */
+ 	old_de->inode = 0;
+ 	new_de->inode = old_inode->i_ino;
+ 	if (new_inode) {
+ 		new_inode->i_nlink--;
+ 		new_inode->i_dirt = 1;
+ 	}
+ 	old_bh->b_dirt = 1;
+ 	new_bh->b_dirt = 1;
+ 	if (dir_bh) {
+ 		PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
+ 		dir_bh->b_dirt = 1;
+ 		old_dir->i_nlink--;
+ 		new_dir->i_nlink++;
+ 		old_dir->i_dirt = 1;
+ 		new_dir->i_dirt = 1;
+ 	}
+ 	retval = 0;
+ end_rename:
+ 	brelse(dir_bh);
+ 	brelse(old_bh);
+ 	brelse(new_bh);
+ 	iput(old_inode);
+ 	iput(new_inode);
+ 	iput(old_dir);
+ 	iput(new_dir);
+ 	return retval;
+ }
+ 
+ /*
+  * Ok, rename also locks out other renames, as they can change the parent of
+  * a directory, and we don't want any races. Other races are checked for by
+  * "do_rename()", which restarts if there are inconsistencies.
+  *
+  * Note that there is no race between different filesystems: it's only within
+  * the same device that races occur: many renames can happen at once, as long
+  * as they are on different partitions.
+  */
+ int linux_rename(struct inode * old_dir, const char * old_name, int old_len,
+ 	struct inode * new_dir, const char * new_name, int new_len)
+ {
+ 	static struct wait_queue * wait = NULL;
+ 	static int lock = 0;
+ 	int result;
+ 
+ 	while (lock)
+ 		sleep_on(&wait);
+ 	lock = 1;
+ 	result = do_linux_rename(old_dir, old_name, old_len,
+ 		new_dir, new_name, new_len);
+ 	lock = 0;
+ 	wake_up(&wait);
+ 	return result;
+ }
diff -r -c -N linux/fs/linux/symlink.c linux993l/fs/linux/symlink.c
*** linux/fs/linux/symlink.c
--- linux993l/fs/linux/symlink.c	Mon Jan 11 10:47:11 1993
***************
*** 0 ****
--- 1,105 ----
+ /*
+  *  linux/fs/linux/symlink.c
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  *
+  *  linux symlink handling code
+  */
+ 
+ #include <asm/segment.h>
+ 
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/fs.h>
+ #include <linux/linux_fs.h>
+ #include <linux/stat.h>
+ 
+ static int linux_readlink(struct inode *, char *, int);
+ static int linux_follow_link(struct inode *, struct inode *, int, int, struct inode **);
+ 
+ /*
+  * symlinks can't do much...
+  */
+ struct inode_operations linux_symlink_inode_operations = {
+ 	NULL,			/* no file-operations */
+ 	NULL,			/* create */
+ 	NULL,			/* lookup */
+ 	NULL,			/* link */
+ 	NULL,			/* unlink */
+ 	NULL,			/* symlink */
+ 	NULL,			/* mkdir */
+ 	NULL,			/* rmdir */
+ 	NULL,			/* mknod */
+ 	NULL,			/* rename */
+ 	linux_readlink,		/* readlink */
+ 	linux_follow_link,	/* follow_link */
+ 	NULL,			/* bmap */
+ 	NULL			/* truncate */
+ };
+ 
+ static int linux_follow_link(struct inode * dir, struct inode * inode,
+ 	int flag, int mode, struct inode ** res_inode)
+ {
+ 	int error;
+ 	unsigned short fs;
+ 	struct buffer_head * bh;
+ 
+ 	*res_inode = NULL;
+ 	if (!dir) {
+ 		dir = current->root;
+ 		dir->i_count++;
+ 	}
+ 	if (!inode) {
+ 		iput(dir);
+ 		return -ENOENT;
+ 	}
+ 	if (!S_ISLNK(inode->i_mode)) {
+ 		iput(dir);
+ 		*res_inode = inode;
+ 		return 0;
+ 	}
+ 	if (current->link_count > 5) {
+ 		iput(inode);
+ 		iput(dir);
+ 		return -ELOOP;
+ 	}
+ 	if (!(bh = linux_bread(inode, 0, 0))) {
+ 		iput(inode);
+ 		iput(dir);
+ 		return -EIO;
+ 	}
+ 	iput(inode);
+ 	__asm__("mov %%fs,%0":"=r" (fs));
+ 	__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
+ 	current->link_count++;
+ 	error = open_namei(bh->b_data,flag,mode,res_inode,dir);
+ 	current->link_count--;
+ 	__asm__("mov %0,%%fs"::"r" (fs));
+ 	brelse(bh);
+ 	return error;
+ }
+ 
+ static int linux_readlink(struct inode * inode, char * buffer, int buflen)
+ {
+ 	struct buffer_head * bh;
+ 	int i;
+ 	char c;
+ 
+ 	if (!S_ISLNK(inode->i_mode)) {
+ 		iput(inode);
+ 		return -EINVAL;
+ 	}
+ 	if (buflen > 1023)
+ 		buflen = 1023;
+ 	bh = linux_bread(inode, 0, 0);
+ 	iput(inode);
+ 	if (!bh)
+ 		return 0;
+ 	i = 0;
+ 	while (i<buflen && (c = bh->b_data[i])) {
+ 		i++;
+ 		put_fs_byte(c,buffer++);
+ 	}
+ 	brelse(bh);
+ 	return i;
+ }
diff -r -c -N linux/fs/linux/truncate.c linux993l/fs/linux/truncate.c
*** linux/fs/linux/truncate.c
--- linux993l/fs/linux/truncate.c	Mon Jan 11 10:47:11 1993
***************
*** 0 ****
--- 1,185 ----
+ /*
+  *  linux/fs/truncate.c
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  */
+ 
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/linux_fs.h>
+ #include <linux/tty.h>
+ #include <linux/stat.h>
+ #include <linux/fcntl.h>
+ 
+ /*
+  * Truncate has the most races in the whole filesystem: coding it is
+  * a pain in the a**. Especially as I don't do any locking...
+  *
+  * The code may look a bit weird, but that's just because I've tried to
+  * handle things like file-size changes in a somewhat graceful manner.
+  * Anyway, truncating a file at the same time somebody else writes to it
+  * is likely to result in pretty weird behaviour...
+  *
+  * The new code handles normal truncates (size = 0) as well as the more
+  * general case (size = XXX). I hope.
+  */
+ 
+ static int trunc_direct(struct inode * inode)
+ {
+ 	unsigned short * p;
+ 	struct buffer_head * bh;
+ 	int i, tmp;
+ 	int retry = 0;
+ #define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
+ 
+ repeat:
+ 	for (i = DIRECT_BLOCK ; i < 7 ; i++) {
+ 		p = i + inode->u.linux_i.i_data;
+ 		if (!(tmp = *p))
+ 			continue;
+ 		bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
+ 		if (i < DIRECT_BLOCK) {
+ 			brelse(bh);
+ 			goto repeat;
+ 		}
+ 		if ((bh && bh->b_count != 1) || tmp != *p) {
+ 			retry = 1;
+ 			brelse(bh);
+ 			continue;
+ 		}
+ 		*p = 0;
+ 		inode->i_dirt = 1;
+ 		brelse(bh);
+ 		linux_free_block(inode->i_sb,tmp);
+ 	}
+ 	return retry;
+ }
+ 
+ static int trunc_indirect(struct inode * inode, int offset, unsigned short * p)
+ {
+ 	struct buffer_head * bh;
+ 	int i, tmp;
+ 	struct buffer_head * ind_bh;
+ 	unsigned short * ind;
+ 	int retry = 0;
+ #define INDIRECT_BLOCK (DIRECT_BLOCK-offset)
+ 
+ 	tmp = *p;
+ 	if (!tmp)
+ 		return 0;
+ 	ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
+ 	if (tmp != *p) {
+ 		brelse(ind_bh);
+ 		return 1;
+ 	}
+ 	if (!ind_bh) {
+ 		*p = 0;
+ 		return 0;
+ 	}
+ repeat:
+ 	for (i = INDIRECT_BLOCK ; i < 512 ; i++) {
+ 		if (i < 0)
+ 			i = 0;
+ 		if (i < INDIRECT_BLOCK)
+ 			goto repeat;
+ 		ind = i+(unsigned short *) ind_bh->b_data;
+ 		tmp = *ind;
+ 		if (!tmp)
+ 			continue;
+ 		bh = getblk(inode->i_dev,tmp,BLOCK_SIZE);
+ 		if (i < INDIRECT_BLOCK) {
+ 			brelse(bh);
+ 			goto repeat;
+ 		}
+ 		if ((bh && bh->b_count != 1) || tmp != *ind) {
+ 			retry = 1;
+ 			brelse(bh);
+ 			continue;
+ 		}
+ 		*ind = 0;
+ 		ind_bh->b_dirt = 1;
+ 		brelse(bh);
+ 		linux_free_block(inode->i_sb,tmp);
+ 	}
+ 	ind = (unsigned short *) ind_bh->b_data;
+ 	for (i = 0; i < 512; i++)
+ 		if (*(ind++))
+ 			break;
+ 	if (i >= 512)
+ 		if (ind_bh->b_count != 1)
+ 			retry = 1;
+ 		else {
+ 			tmp = *p;
+ 			*p = 0;
+ 			linux_free_block(inode->i_sb,tmp);
+ 		}
+ 	brelse(ind_bh);
+ 	return retry;
+ }
+ 		
+ static int trunc_dindirect(struct inode * inode)
+ {
+ 	int i, tmp;
+ 	struct buffer_head * dind_bh;
+ 	unsigned short * dind, * p;
+ 	int retry = 0;
+ #define DINDIRECT_BLOCK ((DIRECT_BLOCK-(512+7))>>9)
+ 
+ 	p = 8 + inode->u.linux_i.i_data;
+ 	if (!(tmp = *p))
+ 		return 0;
+ 	dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
+ 	if (tmp != *p) {
+ 		brelse(dind_bh);
+ 		return 1;
+ 	}
+ 	if (!dind_bh) {
+ 		*p = 0;
+ 		return 0;
+ 	}
+ repeat:
+ 	for (i = DINDIRECT_BLOCK ; i < 512 ; i ++) {
+ 		if (i < 0)
+ 			i = 0;
+ 		if (i < DINDIRECT_BLOCK)
+ 			goto repeat;
+ 		dind = i+(unsigned short *) dind_bh->b_data;
+ 		retry |= trunc_indirect(inode,7+512+(i<<9),dind);
+ 		dind_bh->b_dirt = 1;
+ 	}
+ 	dind = (unsigned short *) dind_bh->b_data;
+ 	for (i = 0; i < 512; i++)
+ 		if (*(dind++))
+ 			break;
+ 	if (i >= 512)
+ 		if (dind_bh->b_count != 1)
+ 			retry = 1;
+ 		else {
+ 			tmp = *p;
+ 			*p = 0;
+ 			inode->i_dirt = 1;
+ 			linux_free_block(inode->i_sb,tmp);
+ 		}
+ 	brelse(dind_bh);
+ 	return retry;
+ }
+ 		
+ void linux_truncate(struct inode * inode)
+ {
+ 	int retry;
+ 
+ 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ 	     S_ISLNK(inode->i_mode)))
+ 		return;
+ 	while (1) {
+ 		retry = trunc_direct(inode);
+ 		retry |= trunc_indirect(inode,7,inode->u.linux_i.i_data+7);
+ 		retry |= trunc_dindirect(inode);
+ 		if (!retry)
+ 			break;
+ 		current->counter = 0;
+ 		schedule();
+ 	}
+ 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ 	inode->i_dirt = 1;
+ }
diff -r -c -N linux/include/linux/autoconf.h linux993l/include/linux/autoconf.h
*** linux/include/linux/autoconf.h
--- linux993l/include/linux/autoconf.h	Fri Jan 15 13:43:56 1993
***************
*** 0 ****
--- 1,37 ----
+ /*
+  * Automatically generated C config: don't edit
+  */
+ 
+ /*
+  * General setup
+  */
+ #define CONFIG_BLK_DEV_HD 1
+ #define CONFIG_TCPIP 1
+ #define CONFIG_MAX_16M 1
+ #define CONFIG_M486 1
+ 
+ /*
+  * SCSI support
+  */
+ 
+ /*
+  * SCSI support type (disk, tape, CDrom)
+  */
+ 
+ /*
+  * SCSI low-level drivers
+  */
+ 
+ /*
+  * Filesystems
+  */
+ #define CONFIG_MINIX_FS 1
+ #define CONFIG_LINUX_FS 1
+ #define CONFIG_EXT_FS 1
+ #define CONFIG_MSDOS_FS 1
+ #define CONFIG_PROC_FS 1
+ 
+ /*
+  * Various character device drivers..
+  */
+ #define CONFIG_MS_BUSMOUSE 1
diff -r -c -N linux/include/linux/fs.h linux993l/include/linux/fs.h
*** linux/include/linux/fs.h	Sun Dec 20 02:14:53 1992
--- linux993l/include/linux/fs.h	Fri Jan 15 12:59:56 1993
***************
*** 135,140 ****
--- 135,141 ----
  
  #include <linux/pipe_fs_i.h>
  #include <linux/minix_fs_i.h>
+ #include <linux/linux_fs_i.h>
  #include <linux/ext_fs_i.h>
  #include <linux/msdos_fs_i.h>
  #include <linux/iso_fs_i.h>
***************
*** 173,178 ****
--- 174,180 ----
  	union {
  		struct pipe_inode_info pipe_i;
  		struct minix_inode_info minix_i;
+ 		struct linux_inode_info linux_i;
  		struct ext_inode_info ext_i;
  		struct msdos_inode_info msdos_i;
  		struct iso_inode_info isofs_i;
***************
*** 202,207 ****
--- 204,210 ----
  };
  
  #include <linux/minix_fs_sb.h>
+ #include <linux/linux_fs_sb.h>
  #include <linux/ext_fs_sb.h>
  #include <linux/msdos_fs_sb.h>
  #include <linux/iso_fs_sb.h>
***************
*** 222,227 ****
--- 225,231 ----
  	struct wait_queue * s_wait;
  	union {
  		struct minix_sb_info minix_sb;
+ 		struct linux_sb_info linux_sb;
  		struct ext_sb_info ext_sb;
  		struct msdos_sb_info msdos_sb;
  		struct isofs_sb_info isofs_sb;
diff -r -c -N linux/include/linux/linux_fs.h linux993l/include/linux/linux_fs.h
*** linux/include/linux/linux_fs.h
--- linux993l/include/linux/linux_fs.h	Fri Jan 15 12:57:18 1993
***************
*** 0 ****
--- 1,116 ----
+ #ifndef _LINUX_LINUX_FS_H
+ #define _LINUX_LINUX_FS_H
+ 
+ /*
+  * The linux filesystem constants/structures
+  */
+ 
+ /*
+  * Thanks to Kees J Bot for sending me the definitions of the new
+  * linux filesystem (aka V2) with bigger inodes and 32-bit block
+  * pointers. It's not actually implemented yet, but I'll look into
+  * it.
+  */
+ 
+ #define LINUX_NAME_LEN 30
+ #define LINUX_ROOT_INO 1
+ 
+ #define LINUX_I_MAP_SLOTS	8
+ #define LINUX_Z_MAP_SLOTS	8
+ #define LINUX_SUPER_MAGIC	0x138F
+ #define NEW_LINUX_SUPER_MAGIC	0x2469
+ 
+ #define LINUX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct linux_inode)))
+ #define LINUX_DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct linux_dir_entry)))
+ 
+ struct linux_inode {
+ 	unsigned short i_mode;
+ 	unsigned short i_uid;
+ 	unsigned long i_size;
+ 	unsigned long i_time;
+ 	unsigned char i_gid;
+ 	unsigned char i_nlinks;
+ 	unsigned short i_zone[9];
+ };
+ 
+ /*
+  * The new linux inode has all the time entries, as well as
+  * long block numbers and a third indirect block (7+1+1+1
+  * instead of 7+1+1). Also, some previously 8-bit values are
+  * now 16-bit. The inode is now 64 bytes instead of 32.
+  */
+ struct new_linux_inode {
+ 	unsigned short i_mode;
+ 	unsigned short i_nlinks;
+ 	unsigned short i_uid;
+ 	unsigned short i_gid;
+ 	unsigned long i_size;
+ 	unsigned long i_atime;
+ 	unsigned long i_mtime;
+ 	unsigned long i_ctime;
+ 	unsigned long i_zone[10];
+ };
+ 
+ /*
+  * linux super-block data on disk
+  */
+ struct linux_super_block {
+ 	unsigned short s_ninodes;
+ 	unsigned short s_nzones;
+ 	unsigned short s_imap_blocks;
+ 	unsigned short s_zmap_blocks;
+ 	unsigned short s_firstdatazone;
+ 	unsigned short s_log_zone_size;
+ 	unsigned long s_max_size;
+ 	unsigned short s_magic;
+ };
+ 
+ struct linux_dir_entry {
+ 	unsigned short inode;
+ 	char name[LINUX_NAME_LEN];
+ };
+ 
+ extern int linux_lookup(struct inode * dir,const char * name, int len,
+ 	struct inode ** result);
+ extern int linux_create(struct inode * dir,const char * name, int len, int mode,
+ 	struct inode ** result);
+ extern int linux_mkdir(struct inode * dir, const char * name, int len, int mode);
+ extern int linux_rmdir(struct inode * dir, const char * name, int len);
+ extern int linux_unlink(struct inode * dir, const char * name, int len);
+ extern int linux_symlink(struct inode * inode, const char * name, int len,
+ 	const char * symname);
+ extern int linux_link(struct inode * oldinode, struct inode * dir, const char * name, int len);
+ extern int linux_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
+ extern int linux_rename(struct inode * old_dir, const char * old_name, int old_len,
+ 	struct inode * new_dir, const char * new_name, int new_len);
+ extern struct inode * linux_new_inode(const struct inode * dir);
+ extern void linux_free_inode(struct inode * inode);
+ extern unsigned long linux_count_free_inodes(struct super_block *sb);
+ extern int linux_new_block(struct super_block * sb);
+ extern void linux_free_block(struct super_block * sb, int block);
+ extern unsigned long linux_count_free_blocks(struct super_block *sb);
+ 
+ extern int linux_bmap(struct inode *,int);
+ 
+ extern struct buffer_head * linux_getblk(struct inode *, int, int);
+ extern struct buffer_head * linux_bread(struct inode *, int, int);
+ 
+ extern void linux_truncate(struct inode *);
+ extern void linux_put_super(struct super_block *);
+ extern struct super_block *linux_read_super(struct super_block *,void *);
+ extern void linux_read_inode(struct inode *);
+ extern void linux_write_inode(struct inode *);
+ extern void linux_put_inode(struct inode *);
+ extern void linux_statfs(struct super_block *, struct statfs *);
+ 
+ extern struct inode_operations linux_file_inode_operations;
+ extern struct inode_operations linux_dir_inode_operations;
+ extern struct inode_operations linux_symlink_inode_operations;
+ extern struct inode_operations linux_chrdev_inode_operations;
+ extern struct inode_operations linux_blkdev_inode_operations;
+ extern struct inode_operations linux_fifo_inode_operations;
+ 
+ extern struct file_operations linux_file_operations;
+ extern struct file_operations linux_dir_operations;
+ 
+ #endif
diff -r -c -N linux/include/linux/linux_fs_i.h linux993l/include/linux/linux_fs_i.h
*** linux/include/linux/linux_fs_i.h
--- linux993l/include/linux/linux_fs_i.h	Fri Jan 15 12:57:18 1993
***************
*** 0 ****
--- 1,11 ----
+ #ifndef _LINUX_FS_I
+ #define _LINUX_FS_I
+ 
+ /*
+  * linux fs inode data in memory
+  */
+ struct linux_inode_info {
+ 	unsigned short i_data[16];
+ };
+ 
+ #endif
diff -r -c -N linux/include/linux/linux_fs_sb.h linux993l/include/linux/linux_fs_sb.h
*** linux/include/linux/linux_fs_sb.h
--- linux993l/include/linux/linux_fs_sb.h	Fri Jan 15 12:57:18 1993
***************
*** 0 ****
--- 1,19 ----
+ #ifndef _LINUX_FS_SB
+ #define _LINUX_FS_SB
+ 
+ /*
+  * linux super-block data in memory
+  */
+ struct linux_sb_info {
+ 			unsigned long s_ninodes;
+ 			unsigned long s_nzones;
+ 			unsigned long s_imap_blocks;
+ 			unsigned long s_zmap_blocks;
+ 			unsigned long s_firstdatazone;
+ 			unsigned long s_log_zone_size;
+ 			unsigned long s_max_size;
+ 			struct buffer_head * s_imap[8];
+ 			struct buffer_head * s_zmap[8];
+ };
+ 
+ #endif
diff -r -c -N linux/tools/version.h linux993l/tools/version.h
*** linux/tools/version.h	Sun Dec 20 14:31:20 1992
--- linux993l/tools/version.h	Fri Jan 15 14:16:47 1993
***************
*** 1,5 ****
! #define UTS_RELEASE "0.99.pl1-46"
! #define UTS_VERSION "12/20/92"
! #define LINUX_COMPILE_TIME "14:31:20"
  #define LINUX_COMPILE_BY "root"
! #define LINUX_COMPILE_HOST "home"
--- 1,5 ----
! #define UTS_RELEASE "0.99.pl3-51"
! #define UTS_VERSION "01/15/93"
! #define LINUX_COMPILE_TIME "14:16:47"
  #define LINUX_COMPILE_BY "root"
! #define LINUX_COMPILE_HOST "linux"
