diff -u --recursive --new-file v2.2.6/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.2.6/linux/Documentation/Configure.help	Fri Apr 16 14:47:30 1999
+++ linux/Documentation/Configure.help	Tue Apr 20 15:17:20 1999
@@ -7443,6 +7443,26 @@
   case insensitive, and case in names is preserved. Say Y. You can
   disable it at mount time with the -N os2 parameter of ncpmount.
 
+Lowercase DOS filenames on LONG namespace volume
+CONFIG_NCPFS_SMALLDOS
+  Saying Y here will convert every filename with creator/owner DOS
+  namespace on NetWare servers to lowercase characters as silently
+  kernel does when you mount  NetWare file server volumes with DOS
+  namespace without OS2/LONG namespace support. Saying N here will
+  give you these filenames with uppercase characters.
+  
+  This is  only cosmetic option  because of OS2/LONG  namespace is
+  case  insensitive.  The  only major  reason for  this option  is
+  backward  compatibility when  you want  to do  step from  DOS to
+  OS2/LONG  namespace support.  Long filenames  (created by Win95)
+  will not be affected.
+
+  This  option  does not  solve a  problem that  filenames  appear
+  differently  in Linux box  and in MS  environment because  of MS
+  does an additional  conversions on client side.  You can achieve
+  simillar effects  enabling ncpfs  option "Allow  using of Native
+  Language Support" below.
+
 Allow mounting of volume subdirectories
 CONFIG_NCPFS_MOUNT_SUBDIR
   Allows you to mount not only whole servers or whole volumes, but
@@ -7461,6 +7481,25 @@
   servers. Do not say Y if security is primary for you because root
   can read your session key (from /proc/kcore).
 
+Allow using of Native Language Support
+CONFIG_NCPFS_NLS
+  Allows you to use codepages and I/O charsets for file name translation
+  between file system on server and input/output. This may be useful,
+  if you want to access to the server with other operating systems,
+  e.g. Windows 95. See also NLS for more Information.
+
+  To select codepages and I/O charsets use ncpfs-2.2.0.13 or newer.
+
+Symbolic links and mode permission bits
+CONFIG_NCPFS_EXTRAS
+  This enables the use of symbolic links and an execute permission
+  bit on NCPFS. The file server need not have long name space or NFS
+  name space loaded for these to work, they are stored using rarely
+  found combinations of Hidden, System and Shared flags.
+
+  To use the new attributes, you are recommended to use the flags
+  '-f 600 -d 755' on the ncpmount commandline.
+  
 nls codepage 437
 CONFIG_NLS_CODEPAGE_437
   The Microsoft fat filesystem family can deal with filenames in
diff -u --recursive --new-file v2.2.6/linux/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt
--- v2.2.6/linux/Documentation/fb/matroxfb.txt	Tue Jan 19 11:32:50 1999
+++ linux/Documentation/fb/matroxfb.txt	Tue Apr 20 15:13:00 1999
@@ -1,6 +1,6 @@
 [This file is cloned from VesaFB. Thanks go to Gerd Knorr]
 
-what is matroxfb?
+What is matroxfb?
 =================
 
 This is a driver for a graphic framebuffer for Matrox devices on
@@ -221,6 +221,8 @@
 sync:X   - sync. pulse - bit 0 inverts HSYNC polarity, bit 1 VSYNC polarity.
            If bit 3 (value 0x08) is set, composite sync instead of HSYNC is
 	   generated. If bit 5 (value 0x20) is set, sync on green is turned on.
+	   Do not forget that if you want sync on green, you also probably
+	   want composite sync.
 	   Default depends on `vesa'.
 depth:X  - Bits per pixel: 0=text, 4,8,15,16,24 or 32. Default depends on
            `vesa'.
@@ -284,8 +286,6 @@
  + current fbset is not able to set 15bpp videomode: you must specify
    depth==16 and green.length==5. fbset does not allow you to set 
    green.length.
- + hardware cursor is available only in accelerated videomodes. Maybe that
-   this is misfeature and not feature.
  + text mode uses 6 bit VGA palette instead of 8 bit (one of 262144 colors
    instead of one of 16M colors). It is due to hardware limitation of 
    MilleniumI/II and SVGALib compatibility.
diff -u --recursive --new-file v2.2.6/linux/Makefile linux/Makefile
--- v2.2.6/linux/Makefile	Fri Apr 16 14:47:30 1999
+++ linux/Makefile	Fri Apr 16 14:47:55 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 2
-SUBLEVEL = 6
+SUBLEVEL = 7
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
diff -u --recursive --new-file v2.2.6/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
--- v2.2.6/linux/arch/alpha/kernel/time.c	Tue Mar 23 14:35:46 1999
+++ linux/arch/alpha/kernel/time.c	Wed Apr 21 10:04:31 1999
@@ -18,6 +18,9 @@
  *      fixed tick loss calculation in timer_interrupt
  *      (round system clock to nearest tick instead of truncating)
  *      fixed algorithm in time_init for getting time from CMOS clock
+ * 1999-04-16	Thorsten Kranzkowski (dl8bcu@gmx.net)
+ *	fixed algorithm in do_gettimeofday() for calculating the precise time
+ *	from processor cycle counter (now taking lost_ticks into account)
  */
 #include <linux/config.h>
 #include <linux/errno.h>
@@ -314,8 +317,10 @@
 void
 do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags, now, delta_cycles, delta_usec;
+	unsigned long flags, delta_cycles, delta_usec;
 	unsigned long sec, usec;
+	__u32 now;
+	extern volatile unsigned long lost_ticks;	/*kernel/sched.c*/
 
 	now = rpcc();
 	save_and_cli(flags);
@@ -337,8 +342,14 @@
 	 * with no clear gain.
 	 */
 
-	delta_usec = delta_cycles * state.scaled_ticks_per_cycle * 15625;
+	delta_usec = (delta_cycles * state.scaled_ticks_per_cycle 
+			+ state.partial_tick
+			+ (lost_ticks << FIX_SHIFT) ) * 15625;
 	delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
+
+	/* the 'lost_tics' term above implements this:	
+	 * delta_usec += lost_ticks * (1000000 / HZ);
+	 */
 
 	usec += delta_usec;
 	if (usec >= 1000000) {
diff -u --recursive --new-file v2.2.6/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- v2.2.6/linux/drivers/pci/oldproc.c	Fri Apr 16 14:47:30 1999
+++ linux/drivers/pci/oldproc.c	Wed Apr 21 09:28:49 1999
@@ -445,6 +445,7 @@
 	DEVICE( 3DFX,		3DFX_VOODOO2,	"Voodoo2"),
 	DEVICE( 3DFX,           3DFX_BANSHEE,   "Banshee"),
 	DEVICE( SIGMADES,	SIGMADES_6425,	"REALmagic64/GX"),
+	DEVICE( AVM,		AVM_A1,		"A1 (Fritz)"),
 	DEVICE( STALLION,	STALLION_ECHPCI832,"EasyConnection 8/32"),
 	DEVICE( STALLION,	STALLION_ECHPCI864,"EasyConnection 8/64"),
 	DEVICE( STALLION,	STALLION_EIOPCI,"EasyIO"),
@@ -784,6 +785,7 @@
 	      case PCI_VENDOR_ID_O2:		return "O2 Micro";
 	      case PCI_VENDOR_ID_3DFX:		return "3Dfx";
 	      case PCI_VENDOR_ID_SIGMADES:	return "Sigma Designs";
+	      case PCI_VENDOR_ID_AVM:		return "AVM";
 	      case PCI_VENDOR_ID_CCUBE:		return "C-Cube";
 	      case PCI_VENDOR_ID_DIPIX:		return "Dipix";
 	      case PCI_VENDOR_ID_STALLION:	return "Stallion Technologies";
diff -u --recursive --new-file v2.2.6/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c
--- v2.2.6/linux/drivers/video/matroxfb.c	Wed Mar 10 15:29:48 1999
+++ linux/drivers/video/matroxfb.c	Tue Apr 20 15:13:00 1999
@@ -4,7 +4,7 @@
  *
  * (c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.9 1999/01/04
+ * Version: 1.15 1999/04/19
  *
  * MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net>
  *
@@ -24,6 +24,9 @@
  *               "Daniel Haun" <haund@usa.net>
  *                     Testing, hardware cursor fixes
  *
+ *               "Scott Wood" <sawst46+@pitt.edu>
+ *                     Fixes
+ *
  *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
  *                     Betatesting
  *
@@ -452,7 +455,7 @@
 #define CPMINFO	const struct matrox_fb_info* minfo,
 #define PMINFO  minfo,
 
-static inline struct matrox_fb_info* mxinfo(struct display* p) {
+static inline struct matrox_fb_info* mxinfo(const struct display* p) {
 	return (struct matrox_fb_info*)p->fb_info;
 }
 
@@ -474,7 +477,7 @@
 #define PMINFO
 
 #if 0
-static inline struct matrox_fb_info* mxinfo(struct display* p) {
+static inline struct matrox_fb_info* mxinfo(const struct display* p) {
 	return &global_mxinfo;
 }
 #endif
@@ -2191,7 +2194,7 @@
 
 	step = ACCESS_FBINFO(devflags.textstep);
 	offs = yy * p->next_line + xx * step;
-	attr = attr_fgcol(p,scr_readw(s)) | (attr_bgcol(p,scr_readw(s)) << 4);
+	attr = attr_fgcol(p, scr_readw(s)) | (attr_bgcol(p, scr_readw(s)) << 4);
 	while (count-- > 0) {
 		unsigned int chr = ((scr_readw(s++)) & p->charmask) << 8;
 		if (chr & 0x10000) chr ^= 0x10008;
@@ -2395,6 +2398,10 @@
 
 	DBG("initMatrox")
 	
+	if (ACCESS_FBINFO(currcon_display) != p)
+		return;
+	if (p->dispsw && p->conp)
+		fb_con.con_cursor(p->conp, CM_ERASE);
 	p->dispsw_data = NULL;
 	if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
 		if (p->type == FB_TYPE_TEXT) {
@@ -4274,6 +4281,17 @@
 	for (i = 0; i < 21; i++) {
 		outTi3026(PMINFO DACseq[i], hw->DACreg[i]);
 	}
+	if (oldhw) {
+		outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
+		oldhw->DACclk[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+		oldhw->DACclk[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+		outTi3026(PMINFO TVP3026_XPLLADDR, 0x15);
+		oldhw->DACclk[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+		oldhw->DACclk[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+		outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
+		oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+		oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+	}
 	if (!oldhw || memcmp(hw->DACclk, oldhw->DACclk, 6)) {
 		/* agrhh... setting up PLL is very slow on Millenium... */
 		/* Mystique PLL is locked in few ms, but Millenium PLL lock takes about 0.15 s... */
@@ -5296,7 +5314,7 @@
 		"MGA-G200 (AGP)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
 		0,			0,
-		DEVF_VIDEO64BIT | DEVF_SWAPS,
+		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
 		230000,
 		&vbG200,
 		"unknown G200 (AGP)"},
@@ -5743,20 +5761,26 @@
 }
 
 #ifndef MODULE
+static int __init initialized = 0;
+
 __initfunc(void matroxfb_init(void))
 {
 	DBG("matroxfb_init")
-#if defined(CONFIG_FB_OF)
-/* Nothing to do, must be called from offb */
-#else	
-	matrox_init();
-#endif
+	
+	if (!initialized) {
+		initialized = 1;
+		matrox_init();
+	}
 }
 
 #if defined(CONFIG_FB_OF)
 __initfunc(int matrox_of_init(struct device_node *dp)) {
 	DBG("matrox_of_init");
-	matrox_init();
+	
+	if (!initialized) {
+		initialized = 1;
+		matrox_init();
+	}
 	if (!fb_list) return -ENXIO;
 	return 0;
 }
diff -u --recursive --new-file v2.2.6/linux/fs/buffer.c linux/fs/buffer.c
--- v2.2.6/linux/fs/buffer.c	Mon Mar 29 11:09:11 1999
+++ linux/fs/buffer.c	Wed Apr 21 11:10:00 1999
@@ -486,33 +486,6 @@
 	remove_from_lru_list(bh);
 }
 
-static inline void put_last_lru(struct buffer_head * bh)
-{
-	if (bh) {
-		struct buffer_head **bhp = &lru_list[bh->b_list];
-
-		if (bh == *bhp) {
-			*bhp = bh->b_next_free;
-			return;
-		}
-
-		if(bh->b_dev == B_FREE)
-			panic("Wrong block for lru list");
-
-		/* Add to back of free list. */
-		remove_from_lru_list(bh);
-		if(!*bhp) {
-			*bhp = bh;
-			(*bhp)->b_prev_free = bh;
-		}
-
-		bh->b_next_free = *bhp;
-		bh->b_prev_free = (*bhp)->b_prev_free;
-		(*bhp)->b_prev_free->b_next_free = bh;
-		(*bhp)->b_prev_free = bh;
-	}
-}
-
 static inline void put_last_free(struct buffer_head * bh)
 {
 	if (bh) {
@@ -726,8 +699,6 @@
 	bh = get_hash_table(dev, block, size);
 	if (bh) {
 		if (!buffer_dirty(bh)) {
-			if (buffer_uptodate(bh))
-				 put_last_lru(bh);
 			bh->b_flushtime = 0;
 		}
 		return bh;
@@ -854,6 +825,7 @@
 		return;
 	}
 	buf->b_count = 0;
+	buf->b_state = 0;
 	remove_from_queues(buf);
 	put_last_free(buf);
 }
@@ -1525,13 +1497,27 @@
  * Use gfp() for the hash table to decrease TLB misses, use
  * SLAB cache for buffer heads.
  */
-void __init buffer_init(void)
+void __init buffer_init(unsigned long memory_size)
 {
-	int order = 5;		/* Currently maximum order.. */
+	int order;
 	unsigned int nr_hash;
 
-	nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct buffer_head *);
-	hash_table = (struct buffer_head **) __get_free_pages(GFP_ATOMIC, order);
+	/* we need to guess at the right sort of size for a buffer cache.
+	   the heuristic from working with large databases and getting
+	   fsync times (ext2) manageable, is the following */
+
+	memory_size >>= 20;
+	for (order = 5; (1UL << order) < memory_size; order++);
+
+	/* try to allocate something until we get it or we're asking
+           for something that is really too small */
+
+	do {
+		nr_hash = (1UL << order) * PAGE_SIZE /
+		    sizeof(struct buffer_head *);
+		hash_table = (struct buffer_head **)
+		    __get_free_pages(GFP_ATOMIC, order);
+	} while (hash_table == NULL && --order > 4);
 	
 	if (!hash_table)
 		panic("Failed to allocate buffer hash table\n");
diff -u --recursive --new-file v2.2.6/linux/fs/fat/fatfs_syms.c linux/fs/fat/fatfs_syms.c
--- v2.2.6/linux/fs/fat/fatfs_syms.c	Wed May 20 19:10:40 1998
+++ linux/fs/fat/fatfs_syms.c	Tue Apr 20 14:37:10 1999
@@ -54,6 +54,7 @@
 EXPORT_SYMBOL(unlock_fat);
 EXPORT_SYMBOL(fat_dir_ioctl);
 EXPORT_SYMBOL(fat_readpage);
+EXPORT_SYMBOL(fat_is_binary);
 
 int init_fat_fs(void)
 {
diff -u --recursive --new-file v2.2.6/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.2.6/linux/fs/fat/inode.c	Fri Apr 16 14:47:31 1999
+++ linux/fs/fat/inode.c	Tue Apr 20 14:37:10 1999
@@ -703,8 +703,8 @@
 	if(raw_entry->attr & ATTR_SYS)
 		if (MSDOS_SB(sb)->options.sys_immutable)
 			inode->i_flags |= S_IMMUTABLE;
-	MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(sb)->options.conversion,
-	    raw_entry->ext);
+	MSDOS_I(inode)->i_binary =
+	    fat_is_binary(MSDOS_SB(sb)->options.conversion, raw_entry->ext);
 	MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
 	/* this is as close to the truth as we can get ... */
 	inode->i_blksize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
diff -u --recursive --new-file v2.2.6/linux/fs/fat/misc.c linux/fs/fat/misc.c
--- v2.2.6/linux/fs/fat/misc.c	Fri Jan 23 18:10:32 1998
+++ linux/fs/fat/misc.c	Tue Apr 20 14:37:10 1999
@@ -51,11 +51,11 @@
 
 
 /*
- * is_binary selects optional text conversion based on the conversion mode and
- * the extension part of the file name.
+ * fat_is_binary selects optional text conversion based on the conversion mode
+ * and the extension part of the file name.
  */
 
-int is_binary(char conversion,char *extension)
+int fat_is_binary(char conversion,char *extension)
 {
 	char *walk;
 
diff -u --recursive --new-file v2.2.6/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v2.2.6/linux/fs/msdos/namei.c	Fri Apr 16 14:47:31 1999
+++ linux/fs/msdos/namei.c	Tue Apr 20 14:37:10 1999
@@ -713,7 +713,7 @@
 	fat_cache_inval_inode(old_inode);
 	old_inode->i_version = ++event;
 	MSDOS_I(old_inode)->i_binary =
-		is_binary(MSDOS_SB(sb)->options.conversion, free_de->ext);
+		fat_is_binary(MSDOS_SB(sb)->options.conversion, free_de->ext);
 	old_inode->i_ino = free_ino;
 	fat_mark_buffer_dirty(sb, free_bh, 1);
 	old_de->name[0] = DELETED_FLAG;
diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/Config.in linux/fs/ncpfs/Config.in
--- v2.2.6/linux/fs/ncpfs/Config.in	Sun Jul 26 11:57:18 1998
+++ linux/fs/ncpfs/Config.in	Tue Apr 20 15:17:20 1999
@@ -6,5 +6,10 @@
 bool     '   Clear remove/delete inhibit when needed' CONFIG_NCPFS_STRONG
 bool     '   Use NFS namespace if available' CONFIG_NCPFS_NFS_NS
 bool     '   Use LONG (OS/2) namespace if available' CONFIG_NCPFS_OS2_NS
+if [ "$CONFIG_NCPFS_OS2_NS" = "y" ]; then
+  bool   '      Lowercase DOS filenames' CONFIG_NCPFS_SMALLDOS
+fi
 bool     '   Allow mounting of volume subdirectories' CONFIG_NCPFS_MOUNT_SUBDIR
 # bool     '   NDS interserver authentication support' CONFIG_NCPFS_NDS_DOMAINS
+bool     '   Use Native Language Support' CONFIG_NCPFS_NLS
+bool     '   Enable symbolic links and execute flags' CONFIG_NCPFS_EXTRAS
diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/Makefile linux/fs/ncpfs/Makefile
--- v2.2.6/linux/fs/ncpfs/Makefile	Thu Jul 16 18:09:28 1998
+++ linux/fs/ncpfs/Makefile	Tue Apr 20 15:17:20 1999
@@ -9,7 +9,7 @@
 
 O_TARGET := ncpfs.o
 O_OBJS   := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \
-		ncpsign_kernel.o
+		symlink.o ncpsign_kernel.o
 M_OBJS   := $(O_TARGET)
 
 # If you want debugging output, please uncomment the following line
diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.2.6/linux/fs/ncpfs/dir.c	Fri Apr 16 14:47:31 1999
+++ linux/fs/ncpfs/dir.c	Tue Apr 20 15:17:20 1999
@@ -4,6 +4,7 @@
  *  Copyright (C) 1995, 1996 by Volker Lendecke
  *  Modified for big endian by J.F. Chadima and David S. Miller
  *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *  Modified 1998 Wolfram Pienkoss for NLS
  *
  */
 
@@ -22,6 +23,7 @@
 #include <linux/locks.h>
 
 #include <linux/ncp_fs.h>
+
 #include "ncplib_kernel.h"
 
 struct ncp_dirent {
@@ -54,7 +56,10 @@
 static int ncp_rmdir(struct inode *, struct dentry *);
 static int ncp_rename(struct inode *, struct dentry *,
 	  	      struct inode *, struct dentry *);
-
+#ifdef CONFIG_NCPFS_EXTRAS
+extern int ncp_symlink(struct inode *, struct dentry *, const char *);
+#endif
+		      
 static struct file_operations ncp_dir_operations =
 {
 	NULL,			/* lseek - default */
@@ -77,7 +82,11 @@
 	ncp_lookup,		/* lookup */
 	NULL,			/* link */
 	ncp_unlink,		/* unlink */
+#ifdef CONFIG_NCPFS_EXTRAS
+	ncp_symlink,		/* symlink */
+#else
 	NULL,			/* symlink */
+#endif
 	ncp_mkdir,		/* mkdir */
 	ncp_rmdir,		/* rmdir */
 	NULL,			/* mknod */
@@ -191,14 +200,6 @@
 	}
 }
 
-/* Here we encapsulate the inode number handling that depends upon the
- * mount mode: When we mount a complete server, the memory address of
- * the ncp_inode_info is used as the inode number. When only a single
- * volume is mounted, then the dirEntNum is used as the inode
- * number. As this is unique for the complete volume, this should
- * enable the NFS exportability of a ncpfs-mounted volume.
- */
-
 /*
  * Generate a unique inode number.
  */
@@ -253,37 +254,30 @@
 ncp_force_unlink(struct inode *dir, struct dentry* dentry)
 {
         int res=0x9c,res2;
-        struct iattr ia;
+	struct nw_modify_dos_info info;
+	__u32 old_nwattr;
+	struct inode *inode;
 
+	memset(&info, 0, sizeof(info));
+	
         /* remove the Read-Only flag on the NW server */
+	inode = dentry->d_inode;
 
-        memset(&ia,0,sizeof(struct iattr));
-        ia.ia_mode = dentry->d_inode->i_mode;
-        ia.ia_mode |= NCP_SERVER(dir)->m.file_mode & 0222;  /* set write bits */
-        ia.ia_valid = ATTR_MODE;
-
-        res2=ncp_notify_change(dentry, &ia);
-        if (res2)
-        {
-                goto leave_me;
-        }
+	old_nwattr = NCP_FINFO(inode)->nwattr;
+	info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
+	res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
+	if (res2)
+		goto leave_me;
 
         /* now try again the delete operation */
-
         res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
 
         if (res)  /* delete failed, set R bit again */
         {
-                memset(&ia,0,sizeof(struct iattr));
-                ia.ia_mode = dentry->d_inode->i_mode;
-                ia.ia_mode &= ~(NCP_SERVER(dir)->m.file_mode & 0222);  /* clear write bits */
-                ia.ia_valid = ATTR_MODE;
-
-                res2=ncp_notify_change(dentry, &ia);
-                if (res2)
-                {
+		info.attributes = old_nwattr;
+		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
+		if (res2)
                         goto leave_me;
-                }
         }
 leave_me:
         return(res);
@@ -293,63 +287,58 @@
 #ifdef CONFIG_NCPFS_STRONG
 static int
 ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
-                 struct inode *new_dir, struct dentry* new_dentry, char *_new_name,
-                 int *done_flag)
+                 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
 {
+	struct nw_modify_dos_info info;
         int res=0x90,res2;
-        struct iattr ia;
+	struct inode *old_inode = old_dentry->d_inode;
+	__u32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
+	__u32 new_nwattr = 0; /* shut compiler warning */
+	int old_nwattr_changed = 0;
+	int new_nwattr_changed = 0;
 
+	memset(&info, 0, sizeof(info));
+	
         /* remove the Read-Only flag on the NW server */
 
-        memset(&ia,0,sizeof(struct iattr));
-        ia.ia_mode = old_dentry->d_inode->i_mode;
-	if (S_ISDIR(ia.ia_mode))
-		goto leave_me;
-        ia.ia_mode |= NCP_SERVER(old_dir)->m.file_mode & 0222;  /* set write bits */
-        ia.ia_valid = ATTR_MODE;
-
-        res2=ncp_notify_change(old_dentry, &ia);
-        if (res2)
-        {
-                goto leave_me;
-        }
-
+	info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+	res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
+	if (!res2)
+		old_nwattr_changed = 1;
+	if (new_dentry && new_dentry->d_inode) {
+		new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
+		info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
+		if (!res2)
+			new_nwattr_changed = 1;
+	}
         /* now try again the rename operation */
-        res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
-                                            old_dir, _old_name,
-                                            new_dir, _new_name);
-
-        if (!res) {
-                ncp_invalid_dir_cache(old_dir);
-                ncp_invalid_dir_cache(new_dir);
-                d_move(old_dentry,new_dentry);
-                *done_flag=1;
-
-                if (!old_dentry->d_inode) {
-                        DPRINTK(KERN_INFO "ncpfs: no inode -- file remains rw\n");
-                        goto leave_me;
-                }
-                if ((res2=ncp_lookup_validate(old_dentry))) {
-                        DPRINTK(KERN_DEBUG "ncpfs: ncp_lookup_validate returned %d\n",res2);
-                }
-        }
-
-        memset(&ia,0,sizeof(struct iattr));
-        ia.ia_mode = old_dentry->d_inode->i_mode;
-        ia.ia_mode &= ~(NCP_SERVER(old_dentry->d_inode)->m.file_mode & 0222);  /* clear write bits */
-        ia.ia_valid = ATTR_MODE;
-
-        DPRINTK(KERN_INFO "calling ncp_notify_change() with %s/%s\n",
-               old_dentry->d_parent->d_name.name,old_dentry->d_name.name);
-
-        res2=ncp_notify_change(old_dentry, &ia);
-        if (res2)
-        {
-                printk(KERN_INFO "ncpfs: ncp_notify_change (2) failed: %08x\n",res2);
-                /* goto leave_me; */
-        }
-
- leave_me:
+	/* but only if something really happened */
+	if (new_nwattr_changed || old_nwattr_changed) {
+	        res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
+        	                                    old_dir, _old_name,
+                	                            new_dir, _new_name);
+	} 
+	if (res)
+		goto leave_me;
+	/* file was successfully renamed, so:
+	   do not set attributes on old file - it no longer exists
+	   copy attributes from old file to new */
+	new_nwattr_changed = old_nwattr_changed;
+	new_nwattr = old_nwattr;
+	old_nwattr_changed = 0;
+	
+leave_me:;
+	if (old_nwattr_changed) {
+		info.attributes = old_nwattr;
+		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
+		/* ignore errors */
+	}
+	if (new_nwattr_changed)	{
+		info.attributes = new_nwattr;
+		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
+		/* ignore errors */
+	}
         return(res);
 }
 #endif	/* CONFIG_NCPFS_STRONG */
@@ -386,11 +375,6 @@
 printk(KERN_DEBUG "ncp_lookup_validate: %s, len %d\n", __name, len);
 #endif
 
-	if (!ncp_preserve_case(dir)) { 
-	  str_lower(__name);
-          down_case = 1;
-	}
-	
 	/* If the file is in the dir cache, we do not have to ask the
 	   server. */
 
@@ -400,17 +384,14 @@
 #endif
 		if (ncp_is_server_root(dir))
 		{
-			str_upper(__name);
+			io2vol(server, __name, 1);
 			down_case = 1;
 			res = ncp_lookup_volume(server, __name,
 						&(finfo.nw_info.i));
 		} else
 	    	{
-			if (!ncp_preserve_case(dir))
-			{
-				str_upper(__name);
-				down_case = 1;
-			}
+			down_case = !ncp_preserve_case(dir);
+			io2vol(server, __name, down_case);
 			res = ncp_obtain_info(server, dir, __name,
 						&(finfo.nw_info.i));
 		}
@@ -429,6 +410,9 @@
 		  else
 		    printk(KERN_DEBUG "ncp_lookup_validate: found, but dirEntNum changed\n");
 #endif
+		  vol2io(server, finfo.nw_info.i.entryName,
+			 !ncp_preserve_entry_case(dir,
+			 finfo.nw_info.i.NSCreator));
  		  ncp_update_inode2(dentry->d_inode, &finfo.nw_info);
 		}
 		if (!val) ncp_invalid_dir_cache(dir);
@@ -535,10 +519,11 @@
 			c_last_returned_index = 0;
 			index = 0;
 
-			if (!ncp_preserve_case(inode)) {
-				for (i = 0; i < c_size; i++) {
-					str_lower(c_entry[i].i.entryName);
-				}
+			for (i = 0; i < c_size; i++)
+			{
+				vol2io(server, c_entry[i].i.entryName,
+					!ncp_preserve_entry_case(inode,
+					c_entry[i].i.NSCreator));
 			}
 		}
 	}
@@ -730,7 +715,7 @@
 		struct dentry* dent;
 
 		result = -ENOENT;
-		str_upper(server->m.mounted_vol);
+		io2vol(server, server->m.mounted_vol, 1);
 		if (ncp_lookup_volume(server, server->m.mounted_vol,
 				      &(server->root.finfo.i)) != 0) {
 #ifdef NCPFS_PARANOIA
@@ -738,7 +723,7 @@
 #endif
 			goto out;
 		}
-		str_lower(server->root.finfo.i.entryName);
+		vol2io(server, server->root.finfo.i.entryName, 1);
 		dent = server->root_dentry;
 		if (dent) {
 			struct inode* ino = dent->d_inode;
@@ -786,11 +771,6 @@
 printk(KERN_DEBUG "ncp_lookup: %s, len %d\n", __name, len);
 #endif
 
-	if (!ncp_preserve_case(dir)) { 
-	  str_lower(__name);
-          down_case = 1;
-	}
-	
 	/* If the file is in the dir cache, we do not have to ask the
 	   server. */
 
@@ -830,17 +810,14 @@
 #endif
 		if (ncp_is_server_root(dir))
 		{
-			str_upper(__name);
+			io2vol(server, __name, 1);
 			down_case = 1;
 			res = ncp_lookup_volume(server, __name,
 						&(finfo.nw_info.i));
 		} else
 	    	{
-			if (!ncp_preserve_case(dir))
-			{
-				str_upper(__name);
-				down_case = 1;
-			}
+			down_case = !ncp_preserve_case(dir);
+			io2vol(server, __name, down_case);
 			res = ncp_obtain_info(server, dir, __name,
 						&(finfo.nw_info.i));
 		}
@@ -851,8 +828,11 @@
 		/*
 		 * If we didn't find an entry, make a negative dentry.
 		 */
-	   	if (res != 0)
+	   	if (res != 0) {
 			goto add_entry;
+		} else vol2io(server, finfo.nw_info.i.entryName,
+			      ncp_preserve_entry_case(dir,
+			      finfo.nw_info.i.NSCreator));
 	}
 
 	/*
@@ -906,18 +886,19 @@
 	goto out;
 }
 
-static int ncp_create(struct inode *dir, struct dentry *dentry, int mode)
+int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
+		int attributes)
 {
 	int error, result;
 	struct ncpfs_inode_info finfo;
 	__u8 _name[dentry->d_name.len + 1];
-
+	
 #ifdef NCPFS_PARANOIA
-printk(KERN_DEBUG "ncp_create: creating %s/%s, mode=%x\n",
+printk(KERN_DEBUG "ncp_create_new: creating %s/%s, mode=%x\n",
 dentry->d_parent->d_name.name, dentry->d_name.name, mode);
 #endif
 	if (!dir || !S_ISDIR(dir->i_mode)) {
-		printk(KERN_WARNING "ncp_create: inode is NULL or not a directory\n");
+		printk(KERN_WARNING "ncp_create_new: inode is NULL or not a directory\n");
 		return -ENOENT;
 	}
 	error = -EIO;
@@ -927,14 +908,12 @@
 	strncpy(_name, dentry->d_name.name, dentry->d_name.len);
 	_name[dentry->d_name.len] = '\0';
 
-	if (!ncp_preserve_case(dir)) {
-		str_upper(_name);
-	}
+	io2vol(NCP_SERVER(dir), _name, !ncp_preserve_case(dir));
 
 	error = -EACCES;
 	result = ncp_open_create_file_or_subdir(NCP_SERVER(dir), dir, _name,
 			   OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
-			   0, AR_READ | AR_WRITE, &finfo.nw_info);
+			   attributes, AR_READ | AR_WRITE, &finfo.nw_info);
 	if (!result) {
 		finfo.nw_info.access = O_RDWR;
 		error = ncp_instantiate(dir, dentry, &finfo);
@@ -948,6 +927,11 @@
 	return error;
 }
 
+static int ncp_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+	return ncp_create_new(dir, dentry, mode, 0);
+}
+
 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	int error;
@@ -967,9 +951,7 @@
 
 	strncpy(_name, dentry->d_name.name, dentry->d_name.len);
 	_name[dentry->d_name.len] = '\0';
-	if (!ncp_preserve_case(dir)) {
-		str_upper(_name);
-	}
+	io2vol(NCP_SERVER(dir), _name, !ncp_preserve_case(dir));
 
 	error = -EACCES;
 	if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), dir, _name,
@@ -1008,17 +990,34 @@
 	strncpy(_name, dentry->d_name.name, dentry->d_name.len);
 	_name[dentry->d_name.len] = '\0';
 	    
-	if (!ncp_preserve_case(dir))
-	{
-		str_upper(_name);
-	}
-	error = -EACCES;
+	io2vol(NCP_SERVER(dir), _name, !ncp_preserve_case(dir));
 	result = ncp_del_file_or_subdir(NCP_SERVER(dir), dir, _name);
-	if (!result)
-	{
-		ncp_invalid_dir_cache(dir);
-		error = 0;
-    	}
+	switch (result) {
+		case 0x00:
+   			ncp_invalid_dir_cache(dir);
+			error = 0;
+			break;
+		case 0x85:	/* unauthorized to delete file */
+		case 0x8A:	/* unauthorized to delete file */
+			error = -EACCES;
+			break;
+		case 0x8F:
+		case 0x90:	/* read only */
+			error = -EPERM;
+			break;
+		case 0x9F:	/* in use by another client */
+			error = -EBUSY;
+			break;
+		case 0xA0:	/* directory not empty */
+			error = -ENOTEMPTY;
+			break;
+		case 0xFF:	/* someone deleted file */
+			error = -ENOENT;
+			break;
+		default:
+			error = -EACCES;
+			break;
+       	}
 out:
 	return error;
 }
@@ -1052,19 +1051,38 @@
 
 	error = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
 #ifdef CONFIG_NCPFS_STRONG
+	/* 9C is Invalid path.. It should be 8F, 90 - read only, but
+	   it is not :-( */
 	if (error == 0x9C && NCP_SERVER(dir)->m.flags & NCP_MOUNT_STRONG) { /* R/O */
 		error = ncp_force_unlink(dir, dentry);
 	}
 #endif
-	if (!error) {
-		DPRINTK(KERN_DEBUG "ncp: removed %s/%s\n",
-			dentry->d_parent->d_name.name, dentry->d_name.name);
-		ncp_invalid_dir_cache(dir);
-		d_delete(dentry);
-	} else if (error == 0xFF) {
-		error = -ENOENT;
-	} else {
-		error = -EACCES;
+	switch (error) {
+		case 0x00:
+			DPRINTK(KERN_DEBUG "ncp: removed %s/%s\n",
+				dentry->d_parent->d_name.name, dentry->d_name.name);
+			ncp_invalid_dir_cache(dir);
+			d_delete(dentry);
+			break;
+		case 0x85:
+		case 0x8A:
+			error = -EACCES;
+			break;
+		case 0x8D:	/* some files in use */
+		case 0x8E:	/* all files in use */
+			error = -EBUSY;
+			break;
+		case 0x8F:	/* some read only */
+		case 0x90:	/* all read only */
+		case 0x9C:	/* !!! returned when in-use or read-only by NW4 */
+			error = -EPERM;
+			break;
+		case 0xFF:
+			error = -ENOENT;
+			break;
+		default:
+			error = -EACCES;
+			break;
 	}
 		
 out:
@@ -1076,7 +1094,7 @@
 {
 	int old_len = old_dentry->d_name.len;
 	int new_len = new_dentry->d_name.len;
-	int error, done_flag=0;
+	int error;
 	char _old_name[old_dentry->d_name.len + 1];
 	char _new_name[new_dentry->d_name.len + 1];
 
@@ -1099,44 +1117,38 @@
 
 	strncpy(_old_name, old_dentry->d_name.name, old_len);
 	_old_name[old_len] = '\0';
-	if (!ncp_preserve_case(old_dir)) {
-		str_upper(_old_name);
-	}
+	io2vol(NCP_SERVER(old_dir), _old_name, !ncp_preserve_case(old_dir));
 
 	strncpy(_new_name, new_dentry->d_name.name, new_len);
 	_new_name[new_len] = '\0';
-	if (!ncp_preserve_case(new_dir)) {
-		str_upper(_new_name);
-	}
+	io2vol(NCP_SERVER(new_dir), _new_name, !ncp_preserve_case(new_dir));
 
 	error = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
 					    old_dir, _old_name,
 					    new_dir, _new_name);
 #ifdef CONFIG_NCPFS_STRONG
-	if (error == 0x90 && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) {	/* RO */
+	if ((error == 0x90 || error == -EACCES) && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) {	/* RO */
 		error = ncp_force_rename(old_dir, old_dentry, _old_name,
-                                         new_dir, new_dentry, _new_name,
-                                         &done_flag);
+                                         new_dir, new_dentry, _new_name);
 	}
 #endif
-	if (error == 0)
-	{
-                if (done_flag == 0)  /* if 1, the following already happened */
-                {                    /* in ncp_force_rename() */
-                        DPRINTK(KERN_DEBUG "ncp renamed %s -> %s.\n",
+	switch (error) {
+		case 0x00:
+               	        DPRINTK(KERN_DEBUG "ncp renamed %s -> %s.\n",
                                 old_dentry->d_name.name,new_dentry->d_name.name);
-                        ncp_invalid_dir_cache(old_dir);
-                        ncp_invalid_dir_cache(new_dir);
-			if (!S_ISDIR(old_dentry->d_inode->i_mode))
-				d_move(old_dentry,new_dentry);
-                }
-	} else {
-		if (error == 0x9E)
+       	                ncp_invalid_dir_cache(old_dir);
+               	        ncp_invalid_dir_cache(new_dir);
+			/* d_move(old_dentry, new_dentry); */
+			break;
+		case 0x9E:
 			error = -ENAMETOOLONG;
-		else if (error == 0xFF)
+			break;
+		case 0xFF:
 			error = -ENOENT;
-		else
+			break;
+		default:
 			error = -EACCES;
+			break;
 	}
 out:
 	return error;
@@ -1155,14 +1167,12 @@
 
 static int utc2local(int time)
 {
-	return time - sys_tz.tz_minuteswest * 60 +
-	    (sys_tz.tz_dsttime ? 3600 : 0);
+	return time - sys_tz.tz_minuteswest * 60;
 }
 
 static int local2utc(int time)
 {
-	return time + sys_tz.tz_minuteswest * 60 -
-	    (sys_tz.tz_dsttime ? 3600 : 0);
+	return time + sys_tz.tz_minuteswest * 60;
 }
 
 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
@@ -1171,7 +1181,9 @@
 {
 	int month, year, secs;
 
-	month = ((date >> 5) & 15) - 1;
+	/* first subtract and mask after that... Otherwise, if
+	   date == 0, bad things happen */
+	month = ((date >> 5) - 1) & 15;
 	year = date >> 9;
 	secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
 		86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 
diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.2.6/linux/fs/ncpfs/inode.c	Fri Apr 16 14:47:31 1999
+++ linux/fs/ncpfs/inode.c	Tue Apr 20 15:17:20 1999
@@ -4,6 +4,7 @@
  *  Copyright (C) 1995, 1996 by Volker Lendecke
  *  Modified for big endian by J.F. Chadima and David S. Miller
  *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *  Modified 1998 Wolfram Pienkoss for NLS
  *
  */
 
@@ -27,6 +28,7 @@
 #include <linux/init.h>
 
 #include <linux/ncp_fs.h>
+
 #include "ncplib_kernel.h"
 
 static void ncp_read_inode(struct inode *);
@@ -49,6 +51,10 @@
 };
 
 extern struct dentry_operations ncp_dentry_operations;
+#ifdef CONFIG_NCPFS_EXTRAS
+extern struct inode_operations ncp_symlink_inode_operations;
+extern int ncp_symlink(struct inode*, struct dentry*, const char*);
+#endif
 
 static struct nw_file_info *read_nwinfo = NULL;
 static struct semaphore read_sem = MUTEX;
@@ -62,6 +68,12 @@
 	NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
 	NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
 
+#ifdef CONFIG_NCPFS_SMALLDOS
+	NCP_FINFO(inode)->origNS = nwinfo->i.NSCreator;
+#endif
+#ifdef CONFIG_NCPFS_STRONG
+	NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
+#endif
 	NCP_FINFO(inode)->opened = nwinfo->opened;
 	NCP_FINFO(inode)->access = nwinfo->access;
 	NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
@@ -79,12 +91,42 @@
 	struct ncp_server *server = NCP_SERVER(inode);
 
 	if (!NCP_FINFO(inode)->opened) {
+#ifdef CONFIG_NCPFS_STRONG
+		NCP_FINFO(inode)->nwattr = nwi->attributes;
+#endif
 		if (nwi->attributes & aDIR) {
 			inode->i_mode = server->m.dir_mode;
 			inode->i_size = 512;
 		} else {
 			inode->i_mode = server->m.file_mode;
 			inode->i_size = le32_to_cpu(nwi->dataStreamSize);
+#ifdef CONFIG_NCPFS_EXTRAS
+			if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) && (nwi->attributes & aSHARED)) {
+				switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
+					case aHIDDEN:
+						if (server->m.flags & NCP_MOUNT_SYMLINKS) {
+							if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
+							 && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+								inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
+								break;
+							}
+						}
+						/* FALLTHROUGH */
+					case 0:
+						if (server->m.flags & NCP_MOUNT_EXTRAS)
+							inode->i_mode |= 0444;
+						break;
+					case aSYSTEM:
+						if (server->m.flags & NCP_MOUNT_EXTRAS)
+							inode->i_mode |= (inode->i_mode >> 2) & 0111;
+						break;
+					/* case aSYSTEM|aHIDDEN: */
+					default:
+						/* reserved combination */
+						break;
+				}
+			}
+#endif
 		}
 		if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
 	}
@@ -114,6 +156,34 @@
 	} else {
 		inode->i_mode = server->m.file_mode;
 		inode->i_size = le32_to_cpu(nwi->dataStreamSize);
+#ifdef CONFIG_NCPFS_EXTRAS
+		if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
+		 && (nwi->attributes & aSHARED)) {
+			switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
+				case aHIDDEN:
+					if (server->m.flags & NCP_MOUNT_SYMLINKS) {
+						if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
+						 && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+							inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
+							break;
+						}
+					}
+					/* FALLTHROUGH */
+				case 0:
+					if (server->m.flags & NCP_MOUNT_EXTRAS)
+						inode->i_mode |= 0444;
+					break;
+				case aSYSTEM:
+					if (server->m.flags & NCP_MOUNT_EXTRAS)
+						inode->i_mode |= (inode->i_mode >> 2) & 0111;
+					break;
+				/* case aSYSTEM|aHIDDEN: */
+				default:
+					/* reserved combination */
+					break;
+			}
+		}
+#endif
 	}
 	if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
 
@@ -157,6 +227,10 @@
 		inode->i_op = &ncp_file_inode_operations;
 	} else if (S_ISDIR(inode->i_mode)) {
 		inode->i_op = &ncp_dir_inode_operations;
+#ifdef CONFIG_NCPFS_EXTRAS
+	} else if (S_ISLNK(inode->i_mode)) {
+		inode->i_op = &ncp_symlink_inode_operations;
+#endif
 	} else {
 		inode->i_op = NULL;
 	}
@@ -211,7 +285,6 @@
 {
 	struct ncp_inode_info *root = &(server->root);
 	struct nw_info_struct *i = &(root->finfo.i);
-	unsigned short dummy;
 
 	DPRINTK(KERN_DEBUG "ncp_init_root: i = %x\n", (int) i);
 
@@ -219,15 +292,13 @@
 	i->dataStreamSize= 1024;
 	i->dirEntNum	 = 0;
 	i->DosDirNum	 = 0;
+#ifdef CONFIG_NCPFS_SMALLDOS
+	i->NSCreator	 = NW_NS_DOS;
+#endif
 	i->volNumber	 = NCP_NUMBER_OF_VOLUMES + 1;	/* illegal volnum */
-	ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
-	ncp_date_unix2dos(0, &(i->modifyTime  ), &(i->modifyDate));
-	ncp_date_unix2dos(0, &(dummy          ), &(i->lastAccessDate));
-	i->creationTime	 = le16_to_cpu(i->creationTime);
-	i->creationDate	 = le16_to_cpu(i->creationDate);
-	i->modifyTime	 = le16_to_cpu(i->modifyTime);
-	i->modifyDate	 = le16_to_cpu(i->modifyDate);
-	i->lastAccessDate= le16_to_cpu(i->lastAccessDate);
+	/* set dates of mountpoint to Jan 1, 1986; 00:00 */
+	i->creationTime = i->modifyTime = cpu_to_le16(0x0000);
+	i->creationDate = i->modifyDate = i->lastAccessDate = cpu_to_le16(0x0C21);
 	i->nameLen	 = 0;
 	i->entryName[0]  = '\0';
 
@@ -264,8 +335,6 @@
 
 	lock_super(sb);
 
-	sb->s_flags |= MS_ODD_RENAME; /* This should go away */
-
 	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
 	sb->s_blocksize_bits = 10;
 	sb->s_magic = NCP_SUPER_MAGIC;
@@ -310,6 +379,14 @@
 	server->m.dir_mode = (server->m.dir_mode &
 			      (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
 
+#ifdef CONFIG_NCPFS_NLS
+	/* load the default NLS charsets */
+	server->nls_charsets.codepage[0] = 0;
+	server->nls_charsets.iocharset[0] = 0;
+	server->nls_vol = load_nls_default();
+	server->nls_io = load_nls_default();
+#endif /* CONFIG_NCPFS_NLS */
+
 	server->packet_size = NCP_PACKET_SIZE;
 	server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
 	if (server->packet == NULL)
@@ -379,6 +456,10 @@
 out_no_packet:
 	printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
 out_free_server:
+#ifdef CONFIG_NCPFS_NLS
+	unload_nls(server->nls_io);
+	unload_nls(server->nls_vol);
+#endif
 	ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
 	goto out_unlock;
 out_no_server:
@@ -418,6 +499,20 @@
 	ncp_disconnect(server);
 	ncp_unlock_server(server);
 
+#ifdef CONFIG_NCPFS_NLS
+	/* unload the NLS charsets */
+	if (server->nls_vol)
+	{
+		unload_nls(server->nls_vol);
+		server->nls_vol = NULL;
+	}
+	if (server->nls_io)
+	{
+		unload_nls(server->nls_io);
+		server->nls_io = NULL;
+	}
+#endif /* CONFIG_NCPFS_NLS */
+
 	fput(server->ncp_filp);
 	kill_proc(server->m.wdog_pid, SIGTERM, 1);
 
@@ -459,9 +554,12 @@
 	int result = 0;
 	int info_mask;
 	struct nw_modify_dos_info info;
+	struct ncp_server *server;
 
 	result = -EIO;
-	if (!ncp_conn_valid(NCP_SERVER(inode)))
+
+	server = NCP_SERVER(inode);
+	if ((!server) || !ncp_conn_valid(server))
 		goto out;
 
 	result = inode_change_ok(inode, attr);
@@ -470,11 +568,11 @@
 
 	result = -EPERM;
 	if (((attr->ia_valid & ATTR_UID) &&
-	     (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
+	     (attr->ia_uid != server->m.uid)))
 		goto out;
 
 	if (((attr->ia_valid & ATTR_GID) &&
-	     (attr->ia_gid != NCP_SERVER(inode)->m.gid)))
+	     (attr->ia_gid != server->m.gid)))
 		goto out;
 
 	if (((attr->ia_valid & ATTR_MODE) &&
@@ -488,26 +586,53 @@
 #if 1 
         if ((attr->ia_valid & ATTR_MODE) != 0)
         {
-                if (!S_ISREG(inode->i_mode))
+                if (S_ISDIR(inode->i_mode)) {
+                	umode_t newmode;
+
+                	info_mask |= DM_ATTRIBUTES;
+                	newmode = attr->ia_mode;
+                	newmode &= NCP_SERVER(inode)->m.dir_mode;
+
+                	if (newmode & 0222)
+                		info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+                	else
+				info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
+                } else if (!S_ISREG(inode->i_mode))
                 {
                         return -EPERM;
                 }
                 else
                 {
 			umode_t newmode;
-
+#ifdef CONFIG_NCPFS_EXTRAS			
+			int extras;
+			
+			extras = server->m.flags & NCP_MOUNT_EXTRAS;
+#endif
                         info_mask |= DM_ATTRIBUTES;
                         newmode=attr->ia_mode;
-                        newmode &= NCP_SERVER(inode)->m.file_mode;
+#ifdef CONFIG_NCPFS_EXTRAS
+			if (!extras)
+#endif
+	                        newmode &= server->m.file_mode;
 
                         if (newmode & 0222) /* any write bit set */
                         {
-                                info.attributes &= ~0x60001;
+                                info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
                         }
                         else
                         {
-                                info.attributes |= 0x60001;
+                                info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
                         }
+#ifdef CONFIG_NCPFS_EXTRAS
+			if (extras) {
+				if (newmode & 0111) /* any execute bit set */
+					info.attributes |= aSHARED | aSYSTEM;
+				/* read for group/world and not in default file_mode */
+				else if (newmode & ~server->m.file_mode & 0444)
+					info.attributes |= aSHARED;
+			}
+#endif
                 }
         }
 #endif
@@ -548,6 +673,10 @@
 				result = 0;
 			}
 		}
+#ifdef CONFIG_NCPFS_STRONG		
+		if ((!result) && (info_mask & DM_ATTRIBUTES))
+			NCP_FINFO(inode)->nwattr = info.attributes;
+#endif
 	}
 	if ((attr->ia_valid & ATTR_SIZE) != 0) {
 		int written;
diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c
--- v2.2.6/linux/fs/ncpfs/ioctl.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/ncpfs/ioctl.c	Tue Apr 20 15:17:20 1999
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 1995, 1996 by Volker Lendecke
  *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *  Modified 1998 Wolfram Pienkoss for NLS
  *
  */
 
@@ -17,6 +18,7 @@
 
 #include <linux/ncp.h>
 #include <linux/ncp_fs.h>
+
 #include "ncplib_kernel.h"
 
 /* maximum limit for ncp_objectname_ioctl */
@@ -485,6 +487,69 @@
 			return 0;
 		}
 #endif	/* CONFIG_NCPFS_NDS_DOMAINS */
+
+#ifdef CONFIG_NCPFS_NLS
+/* Here we are select the iocharset and the codepage for NLS.
+ * Thanks Petr Vandrovec for idea and many hints.
+ */
+	case NCP_IOC_SETCHARSETS:
+		if (   (permission(inode, MAY_WRITE) != 0)
+		    && (current->uid != server->m.mounted_uid))
+		{
+			return -EACCES;
+		}
+		if (server->root_setuped) return -EBUSY;
+		{
+			struct ncp_nls_ioctl user;
+			struct nls_table *codepage;
+			struct nls_table *iocharset;
+			struct nls_table *oldset_io;
+			struct nls_table *oldset_cp;
+			
+			if (copy_from_user(&user, 
+					   (struct ncp_nls_ioctl*)arg,
+					    sizeof(user))) return -EFAULT;
+
+			codepage = NULL;
+			if (!user.codepage[0]) {
+				codepage = load_nls_default();
+			}
+			else {
+				codepage = load_nls(user.codepage);
+				if (! codepage) {
+					return -EBADRQC;
+				}
+			}
+
+			iocharset = NULL;
+			if (user.iocharset[0] == 0) {
+				iocharset = load_nls_default();
+			}
+			else {
+				iocharset = load_nls(user.iocharset);
+				if (! iocharset) {
+					unload_nls(codepage);
+					return -EBADRQC;
+				}
+			}
+
+			oldset_cp = server->nls_vol;
+			server->nls_vol = codepage;
+			oldset_io = server->nls_io;
+			server->nls_io = iocharset;
+			server->nls_charsets = user;
+			if (oldset_cp) unload_nls(oldset_cp);
+			if (oldset_io) unload_nls(oldset_io);
+			return 0;
+		}
+		
+	case NCP_IOC_GETCHARSETS: /* not tested */
+		if (copy_to_user((struct ncp_nls_ioctl*)arg,
+				&(server->nls_charsets),
+				sizeof(server->nls_charsets))) return -EFAULT;
+		return 0;
+#endif /* CONFIG_NCPFS_NLS */
+
 	default:
 		return -EINVAL;
 	}
diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c
--- v2.2.6/linux/fs/ncpfs/ncplib_kernel.c	Fri Oct  9 13:27:15 1998
+++ linux/fs/ncpfs/ncplib_kernel.c	Tue Apr 20 15:17:20 1999
@@ -238,7 +238,8 @@
 }
 
 static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
-				__u32 dir_base, int have_dir_base, char *path)
+				__u32 dir_base, int have_dir_base, 
+				const char *path)
 {
 	ncp_add_byte(server, vol_num);
 	ncp_add_dword(server, dir_base);
@@ -468,12 +469,17 @@
 	target->nameLen = strlen(volname);
 	strcpy(target->entryName, volname);
 	target->attributes = aDIR;
+	/* set dates to Jan 1, 1986  00:00 */
+	target->creationTime = target->modifyTime = cpu_to_le16(0x0000);
+	target->creationDate = target->modifyDate = target->lastAccessDate = cpu_to_le16(0x0C21);
 	return 0;
 }
 
-int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
-					struct inode *dir, __u32 info_mask,
-				       struct nw_modify_dos_info *info)
+int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server,
+					    struct inode *dir,
+					    const char *path,
+					    __u32 info_mask,
+					    const struct nw_modify_dos_info *info)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
 	__u32 dirent = NCP_FINFO(dir)->dirEntNum;
@@ -487,13 +493,22 @@
 
 	ncp_add_dword(server, info_mask);
 	ncp_add_mem(server, info, sizeof(*info));
-	ncp_add_handle_path(server, volnum, dirent, 1, NULL);
+	ncp_add_handle_path(server, volnum, dirent, 1, path);
 
 	result = ncp_request(server, 87);
 	ncp_unlock_server(server);
 	return result;
 }
 
+int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
+				       struct inode *dir,
+				       __u32 info_mask,
+				       const struct nw_modify_dos_info *info)
+{
+	return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL,
+		info_mask, info);
+}
+
 static int
 ncp_DeleteNSEntry(struct ncp_server *server,
 		  __u8 have_dir_base, __u8 volnum, __u32 dirent,
@@ -787,6 +802,35 @@
 	ncp_unlock_server(server);
 	return result;
 }
+
+#ifdef CONFIG_NCPFS_EXTRAS
+int
+ncp_read_kernel(struct ncp_server *server, const char *file_id,
+		__u32 offset, __u16 to_read, char *target, int *bytes_read) {
+	int error;
+	mm_segment_t old_fs;
+	
+	old_fs = get_fs();
+	set_fs(get_ds());
+	error = ncp_read(server, file_id, offset, to_read, target, bytes_read);
+	set_fs(old_fs);
+	return error;
+}
+
+int
+ncp_write_kernel(struct ncp_server *server, const char *file_id,
+		 __u32 offset, __u16 to_write,
+		 const char *source, int *bytes_written) {
+	int error;
+	mm_segment_t old_fs;
+	
+	old_fs = get_fs();
+	set_fs(get_ds());
+	error = ncp_write(server, file_id, offset, to_write, source, bytes_written);
+	set_fs(old_fs);
+	return error;
+}
+#endif
 
 #ifdef CONFIG_NCPFS_IOCTL_LOCKING
 int
diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/ncplib_kernel.h linux/fs/ncpfs/ncplib_kernel.h
--- v2.2.6/linux/fs/ncpfs/ncplib_kernel.h	Tue Mar 10 10:03:34 1998
+++ linux/fs/ncpfs/ncplib_kernel.h	Tue Apr 20 15:17:20 1999
@@ -4,6 +4,7 @@
  *  Copyright (C) 1995, 1996 by Volker Lendecke
  *  Modified for big endian by J.F. Chadima and David S. Miller
  *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ *  Modified 1998 Wolfram Pienkoss for NLS
  *
  */
 
@@ -23,6 +24,10 @@
 #include <asm/unaligned.h>
 #include <asm/string.h>
 
+#ifdef CONFIG_NCPFS_NLS
+#include <linux/nls.h>
+#endif
+
 #include <linux/ncp.h>
 #include <linux/ncp_fs.h>
 #include <linux/ncp_fs_sb.h>
@@ -36,12 +41,19 @@
 int ncp_read(struct ncp_server *, const char *, __u32, __u16, char *, int *);
 int ncp_write(struct ncp_server *, const char *, __u32, __u16,
 		const char *, int *);
+#ifdef CONFIG_NCPFS_EXTRAS
+int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16, char *, int *);
+int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16,
+		const char *, int *);
+#endif
 
 int ncp_obtain_info(struct ncp_server *server, struct inode *, char *,
 		struct nw_info_struct *target);
 int ncp_lookup_volume(struct ncp_server *, char *, struct nw_info_struct *);
 int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *,
-			 __u32, struct nw_modify_dos_info *info);
+	 __u32, const struct nw_modify_dos_info *info);
+int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *,
+	 const char* path, __u32, const struct nw_modify_dos_info *info);
 
 int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
 int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *);
@@ -75,4 +87,83 @@
 ncp_mount_subdir(struct ncp_server* server, __u8 volNumber, 
 		 __u8 srcNS, __u32 srcDirEntNum);
 #endif	/* CONFIG_NCPFS_MOUNT_SUBDIR */
+
+#ifdef CONFIG_NCPFS_NLS
+/* This are the NLS conversion routines with inspirations and code parts
+ * from the vfat file system and hints from Petr Vandrovec.
+ */
+
+/*
+ * It should be replaced by charset specifc conversion. Gordon Chaffee
+ * has prepared some things, but I don't know, what he thinks about it.
+ * The conversion tables for the io charsets should be generatable by
+ * Unicode table, shouldn't it? I have written so generation code for it.
+ * The tables for the vendor specific codepages...? Hmm. The Samba sources
+ * contains also any hints.
+ */
+
+#define toupperif(c, u) ((((u) != 0) && ((c) >= 'a') && ((c) <= 'z')) \
+			? (c)-('a'-'A') : (c))
+#define tolowerif(c, u) ((((u) != 0) && ((c) >= 'A') && ((c) <= 'Z')) \
+			? (c)-('A'-'a') : (c))
+
+static inline void
+io2vol(struct ncp_server *server, char *name, int case_trans)
+{
+	unsigned char nc;
+	unsigned char *np;
+	unsigned char *up;
+	struct nls_unicode uc;
+	struct nls_table *nls_in;
+	struct nls_table *nls_out;
+
+	nls_in = server->nls_io;
+	nls_out = server->nls_vol;
+	np = name;
+
+	while (*np)
+	{
+		nc = 0;
+		uc = nls_in->charset2uni[toupperif(*np, case_trans)];
+		up = nls_out->page_uni2charset[uc.uni2];
+		if (up != NULL)	nc = up[uc.uni1];
+		if (nc != 0) *np = nc;
+		np++;
+	}
+}
+
+static inline void
+vol2io(struct ncp_server *server, char *name, int case_trans)
+{
+	unsigned char nc;
+	unsigned char *np;
+	unsigned char *up;
+	struct nls_unicode uc;
+	struct nls_table *nls_in;
+	struct nls_table *nls_out;
+
+	nls_in = server->nls_vol;
+	nls_out = server->nls_io;
+	np = name;
+
+	while (*np)
+	{
+		nc = 0;
+		uc = nls_in->charset2uni[*np];
+		up = nls_out->page_uni2charset[uc.uni2];
+		if (up != NULL)	nc = up[uc.uni1];
+		if (nc == 0) nc = *np;
+		*np = tolowerif(nc, case_trans);
+		np++;
+	}
+}
+
+#else
+
+#define io2vol(S,N,U) if (U) str_upper(N)
+#define vol2io(S,N,U) if (U) str_lower(N)
+
+#endif /* CONFIG_NCPFS_NLS */
+
 #endif /* _NCPLIB_H */
+
diff -u --recursive --new-file v2.2.6/linux/fs/ncpfs/symlink.c linux/fs/ncpfs/symlink.c
--- v2.2.6/linux/fs/ncpfs/symlink.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/ncpfs/symlink.c	Tue Apr 20 15:17:20 1999
@@ -0,0 +1,212 @@
+/*
+ *  linux/fs/ncpfs/symlink.c
+ *
+ *  Code for allowing symbolic links on NCPFS (i.e. NetWare)
+ *  Symbolic links are not supported on native NetWare, so we use an
+ *  infrequently-used flag (Sh) and store a two-word magic header in
+ *  the file to make sure we don't accidentally use a non-link file
+ *  as a link.
+ *
+ *  from linux/fs/ext2/symlink.c
+ *
+ *  Copyright (C) 1998-99, Frank A. Vorstenbosch
+ *
+ *  ncpfs symlink handling code
+ *  NLS support (c) 1999 Petr Vandrovec
+ *
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_NCPFS_EXTRAS
+
+#include <asm/uaccess.h>
+#include <asm/segment.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ncp_fs.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/stat.h>
+#include "ncplib_kernel.h"
+
+
+/* these magic numbers must appear in the symlink file -- this makes it a bit
+   more resilient against the magic attributes being set on random files. */
+
+#define NCP_SYMLINK_MAGIC0	le32_to_cpu(0x6c6d7973)     /* "symlnk->" */
+#define NCP_SYMLINK_MAGIC1	le32_to_cpu(0x3e2d6b6e)
+
+static int ncp_readlink(struct dentry *, char *, int);
+static struct dentry *ncp_follow_link(struct dentry *, struct dentry *, unsigned int);
+int ncp_create_new(struct inode *dir, struct dentry *dentry,
+                          int mode,int attributes);
+
+/*
+ * symlinks can't do much...
+ */
+struct inode_operations ncp_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 */
+	ncp_readlink,		/* readlink */
+	ncp_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* bmap */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL			/* smap */
+};
+
+/* ----- follow a symbolic link ------------------------------------------ */
+
+static struct dentry *ncp_follow_link(struct dentry *dentry,
+				      struct dentry *base,
+				      unsigned int follow)
+{
+	struct inode *inode=dentry->d_inode;
+	int error, length, cnt;
+	char *link;
+
+#ifdef DEBUG
+	printk("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow);
+#endif
+
+	if(!S_ISLNK(inode->i_mode)) {
+		dput(base);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if(ncp_make_open(inode,O_RDONLY)) {
+		dput(base);
+		return ERR_PTR(-EIO);
+	}
+
+	for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1, GFP_NFS))==NULL; cnt++) {
+		if (cnt > 10) {
+			dput(base);
+			return ERR_PTR(-EAGAIN); /* -ENOMEM? */
+		}
+		schedule();
+	}
+
+	error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
+                         0,NCP_MAX_SYMLINK_SIZE,link,&length);
+
+	if (error!=0 || length<NCP_MIN_SYMLINK_SIZE || 
+	   ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 || ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
+		dput(base);
+		kfree(link);
+		return ERR_PTR(-EIO);
+	}
+ 
+	link[length]=0;
+
+	vol2io(NCP_SERVER(inode), link+8, 0);
+	
+	/* UPDATE_ATIME(inode); */
+	base=lookup_dentry(link+8, base, follow);
+	kfree(link);
+
+	return base;
+}
+
+/* ----- read symbolic link ---------------------------------------------- */
+
+static int ncp_readlink(struct dentry * dentry, char * buffer, int buflen)
+{
+	struct inode *inode=dentry->d_inode;
+	char *link;
+	int length,error;
+
+#ifdef DEBUG
+	printk("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen);
+#endif
+
+	if(!S_ISLNK(inode->i_mode))
+		return -EINVAL;
+
+	if(ncp_make_open(inode,O_RDONLY))
+		return -EIO;
+
+	if((link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1,GFP_NFS))==NULL)
+		return -ENOMEM;
+
+	error = ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
+		0,NCP_MAX_SYMLINK_SIZE,link,&length);
+
+	if (error!=0 || length < NCP_MIN_SYMLINK_SIZE || buflen < (length-8) ||
+	   ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
+	   	error = -EIO;
+		goto out;
+	}
+
+	link[length] = 0;
+
+	vol2io(NCP_SERVER(inode), link+8, 0);
+	
+	error = length - 8;
+	if(copy_to_user(buffer, link+8, error))
+		error = -EFAULT;
+      
+out:;
+	kfree(link);
+	return error;
+}
+
+/* ----- create a new symbolic link -------------------------------------- */
+ 
+int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
+	int i,length;
+	struct inode *inode;
+	char *link;
+
+#ifdef DEBUG
+	printk("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
+#endif
+
+	if (!(NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS))
+		return -EPERM;	/* EPERM is returned by VFS if symlink procedure does not exist */
+
+	if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE)
+		return -EINVAL;
+
+	if ((link=(char *)kmalloc(length+9,GFP_NFS))==NULL)
+		return -ENOMEM;
+
+	if (ncp_create_new(dir,dentry,0,aSHARED|aHIDDEN)) {
+		kfree(link);
+		return -EIO;
+	}
+
+	inode=dentry->d_inode;
+
+	((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0;
+	((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1;
+	memcpy(link+8, symname, length+1); /* including last zero for io2vol */
+
+	/* map to/from server charset, do not touch upper/lower case as
+	   symlink can point out of ncp filesystem */
+	io2vol(NCP_SERVER(inode), link+8, 0);
+	
+	if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 
+	    		    0, length+8, link, &i) || i!=length+8) {
+		kfree(link);
+		return -EIO;
+	}
+
+	kfree(link);
+	return 0;
+}
+#endif
+
+/* ----- EOF ----- */
diff -u --recursive --new-file v2.2.6/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.2.6/linux/fs/nfs/dir.c	Fri Apr 16 14:47:31 1999
+++ linux/fs/nfs/dir.c	Wed Apr 21 09:22:23 1999
@@ -109,7 +109,7 @@
 
 	dfprintk(VFS, "NFS: nfs_dir_open(%s/%s)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
-	return nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+	return _nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
 }
 
 static ssize_t
@@ -439,8 +439,10 @@
 		goto out_bad;
 
 	/* Filehandle matches? */
-	if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh)))
-		goto out_bad;
+	if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) {
+		if (dentry->d_count < 2 || nfs_revalidate(dentry))
+			goto out_bad;
+	}
 
 	/* Ok, remeber that we successfully checked it.. */
 	nfs_renew_times(dentry);
diff -u --recursive --new-file v2.2.6/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.2.6/linux/fs/nfs/file.c	Tue Mar 23 14:35:48 1999
+++ linux/fs/nfs/file.c	Wed Apr 21 10:32:57 1999
@@ -37,6 +37,7 @@
 static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *);
 static int  nfs_file_flush(struct file *);
 static int  nfs_fsync(struct file *, struct dentry *dentry);
+static int  nfs_file_open(struct inode *inode, struct file *filp);
 
 static struct file_operations nfs_file_operations = {
 	NULL,			/* lseek - default */
@@ -46,7 +47,7 @@
 	NULL,			/* select - default */
 	NULL,			/* ioctl - default */
 	nfs_file_mmap,		/* mmap */
-	NULL,			/* no special open is needed */
+	nfs_file_open,		/* open */
 	nfs_file_flush,		/* flush */
 	NULL,			/* release */
 	nfs_fsync,		/* fsync */
@@ -103,6 +104,19 @@
 	}
 	return status;
 }
+
+/*
+ * Open the file.
+ * Just checks the cache is synchronized.
+ */
+static int
+nfs_file_open(struct inode *inode, struct file *filp)
+{
+	struct dentry *dentry = filp->f_dentry;
+
+	return _nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+}
+
 
 static ssize_t
 nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
diff -u --recursive --new-file v2.2.6/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.2.6/linux/fs/nfs/inode.c	Fri Apr 16 14:47:31 1999
+++ linux/fs/nfs/inode.c	Wed Apr 21 09:22:23 1999
@@ -234,6 +234,11 @@
 	server->rsize    = nfs_block_size(data->rsize, NULL);
 	server->wsize    = nfs_block_size(data->wsize, NULL);
 	server->flags    = data->flags;
+
+	if (data->flags & NFS_MOUNT_NOAC) {
+		data->acregmin = data->acregmax = 0;
+		data->acdirmin = data->acdirmax = 0;
+	}
 	server->acregmin = data->acregmin*HZ;
 	server->acregmax = data->acregmax*HZ;
 	server->acdirmin = data->acdirmin*HZ;
@@ -659,10 +664,6 @@
 	struct inode	*inode = dentry->d_inode;
 	int		 status = 0;
 	struct nfs_fattr fattr;
-
-	/* Don't bother revalidating if we've done it recently */
-	if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
-		goto out;
 
 	dfprintk(PAGECACHE, "NFS: revalidating %s/%s, ino=%ld\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
diff -u --recursive --new-file v2.2.6/linux/fs/nls/Config.in linux/fs/nls/Config.in
--- v2.2.6/linux/fs/nls/Config.in	Wed Jan 13 15:00:43 1999
+++ linux/fs/nls/Config.in	Tue Apr 20 15:17:20 1999
@@ -4,7 +4,7 @@
 
 # msdos and Joliet want NLS
 if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
-	-o "$CONFIG_NTFS_FS" != "n" ]; then
+	-o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" ]; then
   define_bool CONFIG_NLS y
 else
   define_bool CONFIG_NLS n
diff -u --recursive --new-file v2.2.6/linux/include/asm-i386/bitops.h linux/include/asm-i386/bitops.h
--- v2.2.6/linux/include/asm-i386/bitops.h	Mon Dec 28 15:00:53 1998
+++ linux/include/asm-i386/bitops.h	Wed Apr 21 13:04:34 1999
@@ -46,7 +46,7 @@
 	__asm__ __volatile__( LOCK_PREFIX
 		"btsl %1,%0"
 		:"=m" (ADDR)
-		:"ir" (nr));
+		:"Ir" (nr));
 }
 
 extern __inline__ void clear_bit(int nr, volatile void * addr)
@@ -54,7 +54,7 @@
 	__asm__ __volatile__( LOCK_PREFIX
 		"btrl %1,%0"
 		:"=m" (ADDR)
-		:"ir" (nr));
+		:"Ir" (nr));
 }
 
 extern __inline__ void change_bit(int nr, volatile void * addr)
@@ -62,7 +62,7 @@
 	__asm__ __volatile__( LOCK_PREFIX
 		"btcl %1,%0"
 		:"=m" (ADDR)
-		:"ir" (nr));
+		:"Ir" (nr));
 }
 
 extern __inline__ int test_and_set_bit(int nr, volatile void * addr)
@@ -72,7 +72,7 @@
 	__asm__ __volatile__( LOCK_PREFIX
 		"btsl %2,%1\n\tsbbl %0,%0"
 		:"=r" (oldbit),"=m" (ADDR)
-		:"ir" (nr));
+		:"Ir" (nr));
 	return oldbit;
 }
 
@@ -83,7 +83,7 @@
 	__asm__ __volatile__( LOCK_PREFIX
 		"btrl %2,%1\n\tsbbl %0,%0"
 		:"=r" (oldbit),"=m" (ADDR)
-		:"ir" (nr));
+		:"Ir" (nr));
 	return oldbit;
 }
 
@@ -94,7 +94,7 @@
 	__asm__ __volatile__( LOCK_PREFIX
 		"btcl %2,%1\n\tsbbl %0,%0"
 		:"=r" (oldbit),"=m" (ADDR)
-		:"ir" (nr));
+		:"Ir" (nr));
 	return oldbit;
 }
 
@@ -113,7 +113,7 @@
 	__asm__ __volatile__(
 		"btl %2,%1\n\tsbbl %0,%0"
 		:"=r" (oldbit)
-		:"m" (ADDR),"ir" (nr));
+		:"m" (ADDR),"Ir" (nr));
 	return oldbit;
 }
 
diff -u --recursive --new-file v2.2.6/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.2.6/linux/include/linux/fs.h	Fri Apr 16 14:47:31 1999
+++ linux/include/linux/fs.h	Wed Apr 21 13:04:36 1999
@@ -169,7 +169,7 @@
 extern void update_atime (struct inode *inode);
 #define UPDATE_ATIME(inode) update_atime (inode)
 
-extern void buffer_init(void);
+extern void buffer_init(unsigned long);
 extern void inode_init(void);
 extern void file_table_init(void);
 extern void dcache_init(void);
diff -u --recursive --new-file v2.2.6/linux/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h
--- v2.2.6/linux/include/linux/msdos_fs.h	Fri Jul 31 17:10:57 1998
+++ linux/include/linux/msdos_fs.h	Wed Apr 21 13:06:02 1999
@@ -195,7 +195,7 @@
 };
 
 /* misc.c */
-extern int is_binary(char conversion,char *extension);
+extern int fat_is_binary(char conversion,char *extension);
 extern void lock_fat(struct super_block *sb);
 extern void unlock_fat(struct super_block *sb);
 extern int fat_add_cluster(struct inode *inode);
diff -u --recursive --new-file v2.2.6/linux/include/linux/ncp.h linux/include/linux/ncp.h
--- v2.2.6/linux/include/linux/ncp.h	Fri Jul 31 17:10:57 1998
+++ linux/include/linux/ncp.h	Wed Apr 21 13:06:05 1999
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 1995 by Volker Lendecke
  *  Modified for sparc by J.F. Chadima
+ *  Modified for __constant_ntoh by Frank A. Vorstenbosch
  *
  */
 
@@ -58,11 +59,21 @@
 
 /* these define the attribute byte as seen by NCP */
 #define aRONLY     (ntohl(0x01000000))
-#define aHIDDEN    (ntohl(0x02000000))
-#define aSYSTEM    (ntohl(0x04000000))
+#define aHIDDEN    (__constant_ntohl(0x02000000))
+#define aSYSTEM    (__constant_ntohl(0x04000000))
 #define aEXECUTE   (ntohl(0x08000000))
 #define aDIR       (ntohl(0x10000000))
 #define aARCH      (ntohl(0x20000000))
+#define aSHARED	   (ntohl(0x80000000))
+#define aDONTSUBALLOCATE (ntohl(1L<<(11+8)))
+#define aTRANSACTIONAL   (ntohl(1L<<(12+8)))
+#define aPURGE		 (ntohl(1L<<(16-8)))
+#define aRENAMEINHIBIT	 (ntohl(1L<<(17-8)))
+#define aDELETEINHIBIT	 (ntohl(1L<<(18-8)))
+#define aDONTCOMPRESS	 (nothl(1L<<(27-24)))
+
+#define NCP_MIN_SYMLINK_SIZE	8
+#define NCP_MAX_SYMLINK_SIZE	512
 
 #define AR_READ      (ntohs(0x0100))
 #define AR_WRITE     (ntohs(0x0200))
diff -u --recursive --new-file v2.2.6/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h
--- v2.2.6/linux/include/linux/ncp_fs.h	Fri Jul 31 17:11:03 1998
+++ linux/include/linux/ncp_fs.h	Wed Apr 21 13:06:18 1999
@@ -13,6 +13,15 @@
 #include <linux/types.h>
 
 #include <linux/ncp_mount.h>
+
+/* NLS charsets by ioctl */
+#define NCP_IOCSNAME_LEN 20
+struct ncp_nls_ioctl
+{
+	unsigned char codepage[NCP_IOCSNAME_LEN+1];
+	unsigned char iocharset[NCP_IOCSNAME_LEN+1];
+};
+                
 #include <linux/ncp_fs_sb.h>
 #include <linux/ncp_fs_i.h>
 
@@ -111,6 +120,9 @@
 #define NCP_IOC_GETPRIVATEDATA		_IOWR('n', 10, struct ncp_privatedata_ioctl)
 #define NCP_IOC_SETPRIVATEDATA		_IOR('n', 10, struct ncp_privatedata_ioctl)
 
+#define NCP_IOC_GETCHARSETS		_IOWR('n', 11, struct ncp_nls_ioctl)
+#define NCP_IOC_SETCHARSETS		_IOR('n', 11, struct ncp_nls_ioctl)
+
 /*
  * The packet size to allocate. One page should be enough.
  */
@@ -155,6 +167,12 @@
 	__u32	dirEntNum __attribute__((packed));
 	__u32	DosDirNum __attribute__((packed));
 	__u32	volNumber __attribute__((packed));
+#ifdef CONFIG_NCPFS_SMALLDOS
+	__u32	origNS;
+#endif
+#ifdef CONFIG_NCPFS_STRONG
+	__u32	nwattr;
+#endif
 	int	opened;
 	int	access;
 	__u32	server_file_handle __attribute__((packed));
@@ -272,11 +290,14 @@
 	return server->name_space[NCP_FINFO(inode)->volNumber];
 }
 
-static inline int ncp_preserve_case(struct inode *i)
-{
+static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) {
 #if defined(CONFIG_NCPFS_NFS_NS) || defined(CONFIG_NCPFS_OS2_NS)
 	int ns = ncp_namespace(i);
 #endif
+#if defined(CONFIG_NCPFS_SMALLDOS) && defined(CONFIG_NCPFS_OS2_NS)
+	if ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
+		return 0;
+#endif
 	return
 #ifdef CONFIG_NCPFS_OS2_NS
 	(ns == NW_NS_OS2) ||
@@ -285,6 +306,11 @@
 	(ns == NW_NS_NFS) ||
 #endif	/* CONFIG_NCPFS_NFS_NS */
 	0;
+}
+
+static inline int ncp_preserve_case(struct inode *i)
+{
+	return ncp_preserve_entry_case(i, NW_NS_OS2);
 }
 
 static inline int ncp_case_sensitive(struct inode *i)
diff -u --recursive --new-file v2.2.6/linux/include/linux/ncp_fs_sb.h linux/include/linux/ncp_fs_sb.h
--- v2.2.6/linux/include/linux/ncp_fs_sb.h	Fri Jul 31 17:11:03 1998
+++ linux/include/linux/ncp_fs_sb.h	Wed Apr 21 13:06:18 1999
@@ -73,6 +73,10 @@
 		size_t len;
 		void*  data;
 	} priv;
+
+	struct ncp_nls_ioctl nls_charsets;	/* NLS user data */
+	struct nls_table *nls_vol;    /* codepage used on volume */
+	struct nls_table *nls_io;     /* charset used for input and display */
 };
 
 static inline int ncp_conn_valid(struct ncp_server *server)
diff -u --recursive --new-file v2.2.6/linux/include/linux/ncp_mount.h linux/include/linux/ncp_mount.h
--- v2.2.6/linux/include/linux/ncp_mount.h	Fri Jul 31 17:11:03 1998
+++ linux/include/linux/ncp_mount.h	Wed Apr 21 13:06:18 1999
@@ -16,11 +16,13 @@
 #define NCP_MOUNT_VERSION 3
 
 /* Values for flags */
-#define NCP_MOUNT_SOFT 0x0001
-#define NCP_MOUNT_INTR 0x0002
-#define NCP_MOUNT_STRONG 0x0004   /* enable delete/rename of r/o files */
-#define NCP_MOUNT_NO_OS2 0x0008
-#define NCP_MOUNT_NO_NFS 0x0010
+#define NCP_MOUNT_SOFT		0x0001
+#define NCP_MOUNT_INTR		0x0002
+#define NCP_MOUNT_STRONG	0x0004	/* enable delete/rename of r/o files */
+#define NCP_MOUNT_NO_OS2	0x0008	/* do not use OS/2 (LONG) namespace */
+#define NCP_MOUNT_NO_NFS	0x0010	/* do not use NFS namespace */
+#define NCP_MOUNT_EXTRAS	0x0020
+#define NCP_MOUNT_SYMLINKS	0x0040	/* enable symlinks */
 
 struct ncp_mount_data {
 	int version;
diff -u --recursive --new-file v2.2.6/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v2.2.6/linux/include/linux/pagemap.h	Fri Apr 16 14:47:31 1999
+++ linux/include/linux/pagemap.h	Wed Apr 21 13:04:48 1999
@@ -20,8 +20,6 @@
 #define PAGE_HASH_BITS 12
 #define PAGE_HASH_SIZE (1 << PAGE_HASH_BITS)
 
-#define PAGE_AGE_VALUE 16
-
 extern unsigned long page_cache_size; /* # of pages currently in the hash table */
 extern struct page * page_hash_table[PAGE_HASH_SIZE];
 
diff -u --recursive --new-file v2.2.6/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.2.6/linux/include/linux/pci.h	Fri Apr 16 14:47:31 1999
+++ linux/include/linux/pci.h	Wed Apr 21 13:04:36 1999
@@ -927,6 +927,9 @@
 
 #define PCI_VENDOR_ID_CCUBE		0x123f
 
+#define PCI_VENDOR_ID_AVM		0x1244
+#define PCI_DEVICE_ID_AVM_A1		0x0a00
+
 #define PCI_VENDOR_ID_DIPIX		0x1246
 
 #define PCI_VENDOR_ID_STALLION		0x124d
diff -u --recursive --new-file v2.2.6/linux/init/main.c linux/init/main.c
--- v2.2.6/linux/init/main.c	Fri Apr 16 14:47:31 1999
+++ linux/init/main.c	Wed Apr 21 11:10:00 1999
@@ -1166,7 +1166,7 @@
 	filescache_init();
 	dcache_init();
 	vma_init();
-	buffer_init();
+	buffer_init(memory_end-memory_start);
 	signals_init();
 	inode_init();
 	file_table_init();
diff -u --recursive --new-file v2.2.6/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.2.6/linux/mm/page_alloc.c	Mon Jan 25 17:44:34 1999
+++ linux/mm/page_alloc.c	Wed Apr 21 13:03:48 1999
@@ -33,7 +33,7 @@
    for the ring buffers */
 #define NR_MEM_LISTS 12
 #else
-#define NR_MEM_LISTS 6
+#define NR_MEM_LISTS 10
 #endif
 
 /* The start of this MUST match the start of "struct page" */
