diff -ur linux-my/fs/Config.in linux-mynew/fs/Config.in
--- linux-my/fs/Config.in	Tue Oct 30 13:23:54 2001
+++ linux-mynew/fs/Config.in	Tue Oct 30 13:55:09 2001
@@ -31,8 +31,8 @@
 # msdos file systems
 tristate 'DOS FAT fs support' CONFIG_FAT_FS
 dep_tristate '  MSDOS fs support' CONFIG_MSDOS_FS $CONFIG_FAT_FS
-dep_tristate '    UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
 dep_tristate '  VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS
+dep_tristate '    UMSDOS/VFAT: Unix-like file system on top of standard VFAT fs' CONFIG_UMSDOS_FS $CONFIG_VFAT_FS
 dep_tristate 'EFS file system support (read only) (EXPERIMENTAL)' CONFIG_EFS_FS $CONFIG_EXPERIMENTAL
 dep_tristate 'Journalling Flash File System (JFFS) support' CONFIG_JFFS_FS $CONFIG_MTD
 if [ "$CONFIG_JFFS_FS" = "y" -o "$CONFIG_JFFS_FS" = "m" ] ; then
diff -ur linux-my/fs/fat/inode.c linux-mynew/fs/fat/inode.c
--- linux-my/fs/fat/inode.c	Tue Oct 30 13:21:05 2001
+++ linux-mynew/fs/fat/inode.c	Tue Oct 30 13:51:38 2001
@@ -32,7 +32,7 @@
 
 extern struct cvf_format default_cvf;
 
-/* #define FAT_PARANOIA 1 */
+#define FAT_PARANOIA 1
 #define DEBUG_LEVEL 0
 #ifdef FAT_DEBUG
 #  define PRINTK(x) printk x
diff -ur linux-my/fs/umsdos/README-WIP.txt linux-mynew/fs/umsdos/README-WIP.txt
--- linux-my/fs/umsdos/README-WIP.txt	Sat Oct 20 20:09:12 2001
+++ linux-mynew/fs/umsdos/README-WIP.txt	Tue Oct 30 13:50:10 2001
@@ -1,3 +1,31 @@
+UVFAT VERSION WIP -- this is not even alpha quality!!!! 2001-09-08
+
+usage:
+mount vfat partition as uvfat.
+create empty directory on vfat (for example, '/linux')
+run umssync on it ('umssync /linux')
+
+DO NOT USE UMSSYNC EVER AGAIN (until it is called uvfatsync, and umsdos
+compatibility version changes to 0.5 so umssync will refuse to run on it
+-- IT WILL DESTROY FILENAMES if you run it again.
+
+try making some long filenames in /linux, and when you remount as vfat (o
+reboot to windows) they should retain their names. 
+
+Renames and hardlinks are work in progress, please be gentle.
+Lookups and file/directory creation should work.
+
+NOTES:
+- there seems to be plenty of 
+  'umsdos_rlookup_x: xxx/yyyyy failed, ret=-852783680' on readdir(2)
+  calls, they appear not to be critical. I'm looking into them.
+
+E-mail me on mnalis-umsdos@voyager.hr with bug reports and patches.
+Please not that this is pre-alpha, and surely contains bugs, some of which
+may prove fatal. Backup often.
+
+---------- documentation below is obsolete !!! -----------------
+
 Changes by Matija Nalis (mnalis@jagor.srce.hr) on umsdos dentry fixing
 (started by Peter T. Waltenberg <peterw@karaka.chch.cri.nz>)
 (Final conversion to dentries Bill Hawes <whawes@star.net>)
diff -ur linux-my/fs/umsdos/dir.c linux-mynew/fs/umsdos/dir.c
--- linux-my/fs/umsdos/dir.c	Sat Oct 20 20:09:12 2001
+++ linux-mynew/fs/umsdos/dir.c	Sun Dec  2 13:03:56 2001
@@ -47,8 +47,8 @@
 
 struct dentry_operations umsdos_dentry_operations =
 {
-	d_revalidate:	umsdos_dentry_validate,
-	d_delete:	umsdos_dentry_dput,
+	d_revalidate:	NULL /* umsdos_dentry_validate */,
+	d_delete:	NULL /* umsdos_dentry_dput */,
 };
 
 struct UMSDOS_DIR_ONCE {
@@ -64,7 +64,8 @@
  * NOTE: filldir DOES NOT use a dentry
  */
 
-static int umsdos_dir_once (	void *buf,
+static int umsdos_dir_once (
+				void *buf,
 				const char *name,
 				int len,
 				loff_t offset,
@@ -100,7 +101,7 @@
 				filldir_t filldir)
 {
 	struct dentry *demd;
-	off_t start_fpos;
+	loff_t start_fpos;
 	int ret = 0;
 	loff_t pos;
 
@@ -169,7 +170,7 @@
 		pos = 0;
 	ret = 0;
 	while (pos < demd->d_inode->i_size) {
-		off_t cur_f_pos = pos;
+		loff_t cur_f_pos = pos;
 		struct dentry *dret;
 		struct inode *inode;
 		struct umsdos_dirent entry;
@@ -190,19 +191,20 @@
 		info.f_pos = cur_f_pos;
 		umsdos_manglename (&info);
 		/*
-		 * Do a real lookup on the short name.
+		 * Do a real lookup on the fake name or vfat long name.
 		 */
-		dret = umsdos_covered(filp->f_dentry, info.fake.fname,
-						 info.fake.len);
+		dret = umsdos_fake_or_lfn(filp->f_dentry, &info);
 		ret = PTR_ERR(dret);
 		if (IS_ERR(dret))
 			break;
 		/*
 		 * If the file wasn't found, remove it from the EMD.
 		 */
+	
 		inode = dret->d_inode;
 		if (!inode)
 			goto remove_name;
+	
 #ifdef UMSDOS_DEBUG_VERBOSE
 if (inode->u.umsdos_i.i_is_hlink)
 printk("umsdos_readdir_x: %s/%s already resolved, ino=%ld\n",
@@ -252,6 +254,8 @@
 		continue;
 
 	remove_name:
+		printk ("/mn/ FIXME: about to delete %s mode=%o\n", info.entry.name,info.entry.mode);
+		/* check_dentry_path (dret, "failed dentry"); */
 		/* #Specification:  umsdos / readdir / not in MSDOS
 		 * During a readdir operation, if the file is not
 		 * in the MS-DOS directory any more, the entry is
@@ -371,8 +375,8 @@
 	inode->i_atime = entry->atime;
 	inode->i_ctime = entry->ctime;
 	inode->i_mtime = entry->mtime;
-	inode->i_uid = entry->uid;
-	inode->i_gid = entry->gid;
+	inode->i_uid = (uid_t) entry->uid;
+	inode->i_gid = (gid_t) entry->gid;
 
 	/* #Specification: umsdos / i_nlink
 	 * The nlink field of an inode is maintained by the MSDOS file system
@@ -479,8 +483,8 @@
 Printk (("lookup %.*s pos %lu ret %d len %d ", 
 info.fake.len, info.fake.fname, info.f_pos, ret, info.fake.len));
 
-	/* do a real lookup to get the short name ... */
-	dret = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
+	/* do a real lookup to get the entry name ... */
+	dret = umsdos_fake_or_lfn(dentry->d_parent, &info);
 	ret = PTR_ERR(dret);
 	if (IS_ERR(dret)) {
 printk("umsdos_lookup_x: %s/%s real lookup failed, ret=%d\n", 
@@ -782,6 +786,35 @@
 	page_cache_release(page);
 	goto out;
 }	
+
+
+/*
+ * First try to lookup mangled name, it that fails, try entry name
+ * returns dentry of found file, which you need to dput() later 
+ * (eg. behaves same as umsdos_covered())
+ */
+struct dentry *umsdos_fake_or_lfn (struct dentry *parent, struct umsdos_info *info)
+{
+	struct dentry *dret;
+
+	dret = umsdos_covered(parent, info->fake.fname,
+				        info->fake.len);
+
+	if (IS_ERR(dret))	/* should not happen - ENOMEM, etc */
+		goto out;
+
+	if (dret->d_inode)	/* we've found mangled name, prefer that ! */
+		goto out;
+
+	/* negative cache, dput() it and try LFN */
+	dput (dret);
+
+	dret = umsdos_covered(parent, info->entry.name,
+				 info->entry.name_len);
+
+out:
+	return dret;
+}
 
 
 struct file_operations umsdos_dir_operations =
diff -ur linux-my/fs/umsdos/emd.c linux-mynew/fs/umsdos/emd.c
--- linux-my/fs/umsdos/emd.c	Sat Oct 20 20:09:12 2001
+++ linux-mynew/fs/umsdos/emd.c	Sun Dec  2 13:07:23 2001
@@ -23,8 +23,8 @@
 	p->name_len = q->name_len;
 	p->flags = q->flags;
 	p->nlink = cpu_to_le16(q->nlink);
-	p->uid = cpu_to_le16(q->uid);
-	p->gid = cpu_to_le16(q->gid);
+	p->uid = cpu_to_le32(q->uid);
+	p->gid = cpu_to_le32(q->gid);
 	p->atime = cpu_to_le32(q->atime);
 	p->mtime = cpu_to_le32(q->mtime);
 	p->ctime = cpu_to_le32(q->ctime);
@@ -38,9 +38,8 @@
 	p->name[p->name_len]='\0';
 	p->flags = q->flags;
 	p->nlink = le16_to_cpu (q->nlink);
-	/* FIXME -- 32bit UID/GID issues */
-	p->uid = le16_to_cpu (q->uid);
-	p->gid = le16_to_cpu (q->gid);
+	p->uid = le32_to_cpu (q->uid);
+	p->gid = le32_to_cpu (q->gid);
 	p->atime = le32_to_cpu (q->atime);
 	p->mtime = le32_to_cpu (q->mtime);
 	p->ctime = le32_to_cpu (q->ctime);
@@ -105,7 +104,7 @@
 Printk(("umsdos_make_emd: creating EMD %s/%s\n",
 parent->d_name.name, demd->d_name.name));
 
-	err = msdos_create(parent->d_inode, demd, S_IFREG | 0777);
+	err = vfat_create(parent->d_inode, demd, S_IFREG | 0777);
 	if (err) {
 		printk (KERN_WARNING
 			"umsdos_make_emd: create %s/%s failed, err=%d\n",
@@ -350,8 +349,8 @@
 	struct inode *emd_dir;
 	int ret = -ENOENT;
 	struct {
-		off_t posok;	/* Position available to store the entry */
-		off_t one;	/* One empty position -> maybe <- large enough */
+		loff_t posok;	/* Position available to store the entry */
+		loff_t one;	/* One empty position -> maybe <- large enough */
 	} empty;
 	int found = 0;
 	int empty_size = 0;
@@ -656,5 +655,92 @@
 
 out:
 	Printk (("umsdos_findentry: returning %d\n", ret));
+	return ret;
+}
+
+/*
+ * Must be called with the parent lock held.
+ */
+int umsdos_notify_change_locked(struct dentry *dentry, struct iattr *attr)
+{
+	struct inode *inode = dentry->d_inode;
+	struct dentry *demd;
+	struct address_space *mapping;
+	struct page *page;
+	int ret = 0;
+	struct umsdos_dirent *entry;
+	int offs;
+
+Printk(("UMSDOS_notify_change: entering for %s/%s (%d)\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, inode->u.umsdos_i.i_patched));
+
+	if (inode->i_nlink == 0)
+		goto out;
+	if (inode->i_ino == UMSDOS_ROOT_INO)
+		goto out;
+
+	/* get the EMD file dentry */
+	demd = umsdos_get_emd_dentry(dentry->d_parent);
+	ret = PTR_ERR(demd);
+	if (IS_ERR(demd))
+		goto out;
+	ret = 0;
+	/* don't do anything if directory is not promoted to umsdos yet */
+	if (!demd->d_inode) { 
+		Printk((KERN_DEBUG
+			"UMSDOS_notify_change: no EMD file %s/%s\n",
+			demd->d_parent->d_name.name, demd->d_name.name));
+		goto out_dput;
+	}
+
+	/* don't do anything if this is the EMD itself */
+	if (inode == demd->d_inode)
+		goto out_dput;
+
+	/* This inode is not a EMD file nor an inode used internally
+	 * by MSDOS, so we can update its status.
+	 * See emd.c
+	 */
+
+	/* Read only the start of the entry since we don't touch the name */
+	mapping = demd->d_inode->i_mapping;
+	offs = inode->u.umsdos_i.pos & ~PAGE_CACHE_MASK;
+	ret = -ENOMEM;
+	page=grab_cache_page(mapping,inode->u.umsdos_i.pos>>PAGE_CACHE_SHIFT);
+	if (!page)
+		goto out_dput;
+	ret=mapping->a_ops->prepare_write(NULL,page,offs,offs+UMSDOS_REC_SIZE);
+	if (ret)
+		goto out_unlock;
+	entry = (struct umsdos_dirent *) (page_address(page) + offs);
+	if (attr->ia_valid & ATTR_UID)
+		entry->uid = cpu_to_le32(attr->ia_uid);
+	if (attr->ia_valid & ATTR_GID)
+		entry->gid = cpu_to_le32(attr->ia_gid);
+	if (attr->ia_valid & ATTR_MODE)
+		entry->mode = cpu_to_le16(attr->ia_mode);
+	if (attr->ia_valid & ATTR_ATIME)
+		entry->atime = cpu_to_le32(attr->ia_atime);
+	if (attr->ia_valid & ATTR_MTIME)
+		entry->mtime = cpu_to_le32(attr->ia_mtime);
+	if (attr->ia_valid & ATTR_CTIME)
+		entry->ctime = cpu_to_le32(attr->ia_ctime);
+	entry->nlink = cpu_to_le16(inode->i_nlink);
+	ret=mapping->a_ops->commit_write(NULL,page,offs,offs+UMSDOS_REC_SIZE);
+	if (ret)
+		printk(KERN_WARNING
+			"umsdos_notify_change: %s/%s EMD write error, ret=%d\n",
+			dentry->d_parent->d_name.name, dentry->d_name.name,ret);
+
+	/* #Specification: notify_change / msdos fs
+	 * notify_change operation are done only on the
+	 * EMD file. The msdos fs is not even called.
+	 */
+out_unlock:
+	UnlockPage(page);
+	page_cache_release(page);
+out_dput:
+	dput(demd);
+out:
 	return ret;
 }
diff -ur linux-my/fs/umsdos/inode.c linux-mynew/fs/umsdos/inode.c
--- linux-my/fs/umsdos/inode.c	Sat Oct 20 20:10:46 2001
+++ linux-mynew/fs/umsdos/inode.c	Sun Dec  2 13:06:37 2001
@@ -24,7 +24,7 @@
 
 struct dentry *saved_root;	/* Original root if changed */
 struct inode *pseudo_root;	/* Useful to simulate the pseudo DOS */
-					/* directory. See UMSDOS_readdir_x() */
+				/* directory. See UMSDOS_readdir_x() */
 
 static struct dentry *check_pseudo_root(struct super_block *);
 
@@ -37,7 +37,7 @@
 		 ,inode->u.umsdos_i.pos
 		 ,atomic_read(&inode->i_count)));
 
-	if (inode == pseudo_root) {
+	if (pseudo_root && inode == pseudo_root) {
 		Printk ((KERN_ERR "Umsdos: debug: releasing pseudo_root - ino=%lu count=%d\n", inode->i_ino, atomic_read(&inode->i_count)));
 	}
 
@@ -55,7 +55,7 @@
 		saved_root = NULL;
 		pseudo_root = NULL;
 	}
-	msdos_put_super (sb);
+	fat_put_super (sb);
 }
 
 
@@ -91,7 +91,7 @@
 /*
  * Add some info into an inode so it can find its owner quickly
  */
-void umsdos_set_dirinfo_new (struct dentry *dentry, off_t f_pos)
+void umsdos_set_dirinfo_new (struct dentry *dentry, loff_t f_pos)
 {
 	struct inode *inode = dentry->d_inode;
 	struct dentry *demd;
@@ -126,7 +126,7 @@
  * is tagged to this inode. It allows operations such as
  * notify_change to be handled.
  */
-void umsdos_patch_dentry_inode(struct dentry *dentry, off_t f_pos)
+void umsdos_patch_dentry_inode(struct dentry *dentry, loff_t f_pos)
 {
 	struct inode *inode = dentry->d_inode;
 
@@ -170,6 +170,9 @@
 		goto out;
 	ret = umsdos_findentry (dentry->d_parent, &info, 0);
 	if (ret) {
+		if (ret == -ENOENT)
+			ret = fat_notify_change (dentry, attr);
+		else
 printk("UMSDOS_notify_change: %s/%s not in EMD, ret=%d\n",
 dentry->d_parent->d_name.name, dentry->d_name.name, ret);
 		goto out;
@@ -185,8 +188,7 @@
 dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname));
 	
 		/* Do a real lookup to get the short name dentry */
-		temp = umsdos_covered(dentry->d_parent, info.fake.fname,
-						info.fake.len);
+		temp = umsdos_fake_or_lfn(dentry->d_parent, &info);
 		ret = PTR_ERR(temp);
 		if (IS_ERR(temp))
 			goto out;
@@ -211,7 +213,7 @@
 	ret = umsdos_notify_change_locked(dentry, attr);
 	up(&dir->i_sem);
 	if (ret == 0)
-		ret = inode_setattr (inode, attr);
+		inode_setattr (inode, attr);
 out:
 	if (old_dentry)
 		dput (dentry);	/* if we had to use fake dentry for hardlinks, dput() it now */
@@ -219,92 +221,6 @@
 }
 
 
-/*
- * Must be called with the parent lock held.
- */
-int umsdos_notify_change_locked(struct dentry *dentry, struct iattr *attr)
-{
-	struct inode *inode = dentry->d_inode;
-	struct dentry *demd;
-	struct address_space *mapping;
-	struct page *page;
-	int ret = 0;
-	struct umsdos_dirent *entry;
-	int offs;
-
-Printk(("UMSDOS_notify_change: entering for %s/%s (%d)\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, inode->u.umsdos_i.i_patched));
-
-	if (inode->i_nlink == 0)
-		goto out;
-	if (inode->i_ino == UMSDOS_ROOT_INO)
-		goto out;
-
-	/* get the EMD file dentry */
-	demd = umsdos_get_emd_dentry(dentry->d_parent);
-	ret = PTR_ERR(demd);
-	if (IS_ERR(demd))
-		goto out;
-	ret = 0;
-	/* don't do anything if directory is not promoted to umsdos yet */
-	if (!demd->d_inode) { 
-		Printk((KERN_DEBUG
-			"UMSDOS_notify_change: no EMD file %s/%s\n",
-			demd->d_parent->d_name.name, demd->d_name.name));
-		goto out_dput;
-	}
-
-	/* don't do anything if this is the EMD itself */
-	if (inode == demd->d_inode)
-		goto out_dput;
-
-	/* This inode is not a EMD file nor an inode used internally
-	 * by MSDOS, so we can update its status.
-	 * See emd.c
-	 */
-
-	/* Read only the start of the entry since we don't touch the name */
-	mapping = demd->d_inode->i_mapping;
-	offs = inode->u.umsdos_i.pos & ~PAGE_CACHE_MASK;
-	ret = -ENOMEM;
-	page=grab_cache_page(mapping,inode->u.umsdos_i.pos>>PAGE_CACHE_SHIFT);
-	if (!page)
-		goto out_dput;
-	ret=mapping->a_ops->prepare_write(NULL,page,offs,offs+UMSDOS_REC_SIZE);
-	if (ret)
-		goto out_unlock;
-	entry = (struct umsdos_dirent *) (page_address(page) + offs);
-	if (attr->ia_valid & ATTR_UID)
-		entry->uid = cpu_to_le16(attr->ia_uid);
-	if (attr->ia_valid & ATTR_GID)
-		entry->gid = cpu_to_le16(attr->ia_gid);
-	if (attr->ia_valid & ATTR_MODE)
-		entry->mode = cpu_to_le16(attr->ia_mode);
-	if (attr->ia_valid & ATTR_ATIME)
-		entry->atime = cpu_to_le32(attr->ia_atime);
-	if (attr->ia_valid & ATTR_MTIME)
-		entry->mtime = cpu_to_le32(attr->ia_mtime);
-	if (attr->ia_valid & ATTR_CTIME)
-		entry->ctime = cpu_to_le32(attr->ia_ctime);
-	entry->nlink = cpu_to_le16(inode->i_nlink);
-	ret=mapping->a_ops->commit_write(NULL,page,offs,offs+UMSDOS_REC_SIZE);
-	if (ret)
-		printk(KERN_WARNING
-			"umsdos_notify_change: %s/%s EMD write error, ret=%d\n",
-			dentry->d_parent->d_name.name, dentry->d_name.name,ret);
-
-	/* #Specification: notify_change / msdos fs
-	 * notify_change operation are done only on the
-	 * EMD file. The msdos fs is not even called.
-	 */
-out_unlock:
-	UnlockPage(page);
-	page_cache_release(page);
-out_dput:
-	dput(demd);
-out:
-	return ret;
-}
 
 
 /*
@@ -363,17 +279,16 @@
 	 * Call msdos-fs to mount the disk.
 	 * Note: this returns res == sb or NULL
 	 */
-	res = msdos_read_super (sb, data, silent);
+	res = vfat_read_super (sb, data, silent);
 
 	if (!res)
 		goto out_fail;
 
-	printk (KERN_INFO "UMSDOS 0.86k "
+	printk (KERN_INFO "UMSDOS/UVFAT Alpha 0.90 "
 		"(compatibility level %d.%d, fast msdos)\n", 
 		UMSDOS_VERSION, UMSDOS_RELEASE);
 
 	sb->s_op = &umsdos_sops;
-	MSDOS_SB(sb)->options.dotsOK = 0;	/* disable hidden==dotfile */
 
 	/* install our dentry operations ... */
 	sb->s_root->d_op = &umsdos_dentry_operations;
@@ -396,7 +311,7 @@
 	return sb;
 
 out_fail:
-	printk(KERN_INFO "UMSDOS: msdos_read_super failed, mount aborted.\n");
+	printk(KERN_INFO "UMSDOS: vfat_read_super failed, mount aborted.\n");
 	return NULL;
 }
 
diff -ur linux-my/fs/umsdos/ioctl.c linux-mynew/fs/umsdos/ioctl.c
--- linux-my/fs/umsdos/ioctl.c	Sat Oct 20 20:09:12 2001
+++ linux-mynew/fs/umsdos/ioctl.c	Sun Dec  2 11:39:36 2001
@@ -173,7 +173,7 @@
 			goto read_dput;
 
 		while (pos < demd->d_inode->i_size) {
-			off_t f_pos = pos;
+			loff_t f_pos = pos;
 			struct umsdos_dirent entry;
 			struct umsdos_info info;
 
@@ -260,7 +260,7 @@
 		goto out;
 	}
 	else if (cmd == UMSDOS_RENAME_DOS) {
-		struct dentry *old_dentry, *new_dentry;		/* FIXME */
+		struct dentry *old_dentry, *new_dentry;		/* FIXME? */
 
 		/* #Specification: ioctl / UMSDOS_RENAME_DOS
 		 * A file or directory is renamed in a DOS directory
@@ -285,7 +285,7 @@
 printk("umsdos_ioctl: renaming %s/%s to %s/%s\n",
 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
-			ret = msdos_rename (dir, old_dentry, dir, new_dentry);
+			ret = vfat_rename (dir, old_dentry, dir, new_dentry);
 			d_drop(new_dentry);
 			d_drop(old_dentry);
 			dput(new_dentry);
@@ -325,7 +325,7 @@
 
 		/* #Specification: ioctl / UMSDOS_UNLINK_DOS
 		 * The dos_dirent field of the struct umsdos_ioctl is used to
-		 * execute a msdos_unlink operation. The d_name and d_reclen
+		 * execute a vfat_unlink operation. The d_name and d_reclen
 		 * fields are used.
 		 * 
 		 * Return 0 if success.
@@ -339,7 +339,7 @@
 		if (temp->d_inode) {
 			ret = -EISDIR;
 			if (!S_ISDIR(temp->d_inode->i_mode))
-				ret = msdos_unlink (dir, temp);
+				ret = vfat_unlink (dir, temp);
 			if (!ret)
 				d_delete(temp);
 		}
@@ -351,7 +351,7 @@
 
 		/* #Specification: ioctl / UMSDOS_RMDIR_DOS
 		 * The dos_dirent field of the struct umsdos_ioctl is used to
-		 * execute a msdos_rmdir operation. The d_name and d_reclen
+		 * execute a vfat_rmdir operation. The d_name and d_reclen
 		 * fields are used.
 		 * 
 		 * Return 0 if success.
@@ -365,7 +365,7 @@
 		if (temp->d_inode) {
 			ret = -ENOTDIR;
 			if (S_ISDIR(temp->d_inode->i_mode))
-				ret = msdos_rmdir (dir, temp);
+				ret = vfat_rmdir (dir, temp);
 			if (!ret)
 				d_delete(temp);
 		}
diff -ur linux-my/fs/umsdos/mangle.c linux-mynew/fs/umsdos/mangle.c
--- linux-my/fs/umsdos/mangle.c	Mon Aug 27 12:43:56 2001
+++ linux-mynew/fs/umsdos/mangle.c	Tue Nov  6 15:04:26 2001
@@ -15,6 +15,7 @@
 /* (This file is used outside of the kernel) */
 #ifndef __KERNEL__
 #define KERN_WARNING
+#include <string.h>
 #endif
 
 /*
@@ -210,6 +211,7 @@
 		 * This speeds up handling of long names.
 		 * The position of the last point is no more necessary anyway.
 		 */
+		ivldchar = 2; /* mangle all short or long names */
 		if (len <= (8 + 1 + 3)) {
 			const char *pt = fname;
 			const char *endpt = fname + len;
@@ -273,8 +275,6 @@
 				}
 				pt++;
 			}
-		} else {
-			ivldchar = 1;
 		}
 		if (ivldchar
 		    || (firstpt == NULL && len > 8)
@@ -317,7 +317,7 @@
 			for (i = 0; i < msdos_len; i++, pt++)
 				*pt = lkp[(unsigned char) (*pt)];
 			*pt = '\0';	/* GLU  We force null termination. */
-			info->msdos_reject = 1;
+			info->msdos_reject = ivldchar;
 			/*
 			 * The numeric extension is added only when we know
 			 * the position in the EMD file, in umsdos_newentry(),
diff -ur linux-my/fs/umsdos/namei.c linux-mynew/fs/umsdos/namei.c
--- linux-my/fs/umsdos/namei.c	Sat Oct 20 20:09:12 2001
+++ linux-mynew/fs/umsdos/namei.c	Sun Dec  2 20:10:51 2001
@@ -242,6 +242,7 @@
 	struct dentry *fake;
 	struct inode *inode;
 	int ret;
+	int trymangle = 0;
 	struct umsdos_info info;
 
 	ret = umsdos_nevercreat (dir, dentry, -EEXIST);
@@ -263,18 +264,45 @@
 	if (ret)
 		goto out;
 
-	/* do a real lookup to get the short name dentry */
-	fake = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
+	/* do a real lookup to get the entry name dentry */
+	fake = umsdos_covered(dentry->d_parent, info.entry.name, info.entry.name_len);
 	ret = PTR_ERR(fake);
 	if (IS_ERR(fake))
 		goto out_remove;
+	
+	if (fake->d_inode) {	/* already used, we need to resort to mangling! */ 
+		trymangle = 1;	/* (probably filename only differs in case) */
+		Printk (("umsdos_create_any: filename %s/%s already used, trying to mangle\n",
+			fake->d_parent->d_name.name, fake->d_name.name));
+	}
+
+mangle:
+	if (trymangle) {
+		dput(fake);
+		fake = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
+		ret = PTR_ERR(fake);
+		if (IS_ERR(fake))
+			goto out_remove;
+		Printk (("umsdos_create_any: using mangle %s/%s\n",
+			fake->d_parent->d_name.name, fake->d_name.name));
+	}
 
 	/* should not exist yet ... */
 	ret = -EEXIST;
 	if (fake->d_inode)
 		goto out_remove_dput;
 
-	ret = msdos_create (dir, fake, S_IFREG | 0777);
+	ret = vfat_create (dir, fake, S_IFREG | 0777);
+
+	if (ret && !trymangle) {	/* failed to create file -- maybe illegal 
+					 * chars like ":" ? Try mangling.
+					 */
+		trymangle = 1;
+		Printk (("umsdos_create_any: failed to create %s/%s, trying to mangle\n",
+			fake->d_parent->d_name.name, fake->d_name.name));
+		goto mangle;
+	}
+
 	if (ret)
 		goto out_remove_dput;
 
@@ -295,11 +323,12 @@
 
 	/* Creation failed ... remove the EMD entry */
 out_remove_dput:
+	printk (KERN_WARNING "/mn/ fake is %s/%s\n", fake->d_parent->d_name.name, fake->d_name.name);
 	dput(fake);
 out_remove:
 	if (ret == -EEXIST)
-		printk(KERN_WARNING "UMSDOS: out of sync, deleting %s/%s\n",
-			dentry->d_parent->d_name.name, info.fake.fname);
+		printk(KERN_WARNING "UMSDOS: out of sync (%d), deleting %s/%s\n", ret,
+			dentry->d_parent->d_name.name, info.entry.name);
 	umsdos_delentry (dentry->d_parent, &info, S_ISDIR (info.entry.mode));
 	goto out;
 }
@@ -398,8 +427,7 @@
 		d_drop(old_dentry);
 	}
 
-	old = umsdos_covered(old_dentry->d_parent, old_info.fake.fname, 
-					old_info.fake.len);
+	old = umsdos_fake_or_lfn(old_dentry->d_parent, &old_info);
 	ret = PTR_ERR(old);
 	if (IS_ERR(old))
 		goto out_unlock;
@@ -415,14 +443,24 @@
  			goto out_dput;
 	}
 
-	new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname, 
-					new_info.fake.len);
+	new = umsdos_covered(new_dentry->d_parent, new_info.entry.name,
+					      new_info.entry.name_len);
 	ret = PTR_ERR(new);
 	if (IS_ERR(new))
 		goto out_dput;
 
 	/* Do the msdos-level rename */
-	ret = msdos_rename (old_dir, old, new_dir, new);
+	ret = vfat_rename (old_dir, old, new_dir, new);
+	if (ret != 0) {		/* rename failed, possibly invalid destination filename? try with mangled name */
+		dput(new);
+		new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname, new_info.fake.len);
+		ret = PTR_ERR(new);
+		if (IS_ERR(new))
+			goto out_dput;
+		Printk (("umsdos_rename_f: vfat_rename failed, using mangle %s/%s\n",
+			new->d_parent->d_name.name, new->d_name.name));
+		ret = vfat_rename (old_dir, old, new_dir, new);
+	}
 
 	dput(new);
 
@@ -678,11 +716,10 @@
 	 */ 
 	d_drop(olddentry);
 Printk(("UMSDOS_link: hard link %s/%s, fake=%s\n",
-olddentry->d_parent->d_name.name, olddentry->d_name.name, old_info.fake.fname));
+olddentry->d_parent->d_name.name, olddentry->d_name.name, old_info.entry.name));
 
 	/* Do a real lookup to get the short name dentry */
-	temp = umsdos_covered(olddentry->d_parent, old_info.fake.fname, 
-					old_info.fake.len);
+	temp = umsdos_fake_or_lfn(olddentry->d_parent, &old_info);
 	ret = PTR_ERR(temp);
 	if (IS_ERR(temp))
 		goto out_unlock;
@@ -706,9 +743,8 @@
 		struct iattr newattrs;
 
 		/* Do a real lookup to get the short name dentry */
-		temp = umsdos_covered(olddentry->d_parent,
-					old_info.fake.fname,
-					old_info.fake.len);
+		temp = umsdos_fake_or_lfn(olddentry->d_parent,
+					&old_info);
 		ret = PTR_ERR(temp);
 		if (IS_ERR(temp))
 			goto out_unlock2;
@@ -767,6 +803,7 @@
 	struct dentry *temp;
 	struct inode *inode;
 	int ret, err;
+	int trymangle = 0;
 	struct umsdos_info info;
 
 	ret = umsdos_nevercreat (dir, dentry, -EEXIST);
@@ -788,21 +825,46 @@
 	if (ret)
 		goto out;
 
-	/* lookup the short name dentry */
-	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
+	/* lookup the lfn entry name dentry */
+	temp = umsdos_covered(dentry->d_parent, info.entry.name, info.entry.name_len);
 	ret = PTR_ERR(temp);
 	if (IS_ERR(temp))
 		goto out_remove;
+	
+	if (temp->d_inode) {	/* already used, we need to resort to mangling! */ 
+		trymangle = 1;	/* (probably filename only differs in case) */
+		Printk(("umsdos_mkdir: dirname %s/%s already used, trying to mangle\n",
+			temp->d_parent->d_name.name, temp->d_name.name));
+	}
+
+mangle:
+	if (trymangle) {
+		dput(temp);
+		temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
+		ret = PTR_ERR(temp);
+		if (IS_ERR(temp))
+			goto out_remove;
+		printk (KERN_WARNING "umsdos_mkdir: using mangle %s/%s\n",
+			temp->d_parent->d_name.name, temp->d_name.name);
+	}
 
 	/* Make sure the short name doesn't exist */
 	ret = -EEXIST;
 	if (temp->d_inode) {
-printk("umsdos_mkdir: short name %s/%s exists\n",
-dentry->d_parent->d_name.name, info.fake.fname);
+printk("umsdos_mkdir: entry name %s/%s exists\n",
+dentry->d_parent->d_name.name, info.entry.name);
 		goto out_remove_dput;
 	}
 
-	ret = msdos_mkdir (dir, temp, mode);
+	ret = vfat_mkdir (dir, temp, mode);
+	if (ret && !trymangle) {	/* failed to create dir -- maybe illegal 
+					 * chars like ":" ? Try mangling.
+					 */
+		trymangle = 1;
+		printk (KERN_WARNING "umsdos_mkdir: failed to create dir %s/%s, trying to mangle\n",
+			temp->d_parent->d_name.name, temp->d_name.name);
+		goto mangle;
+	}
 	if (ret)
 		goto out_remove_dput;
 
@@ -895,7 +957,7 @@
 		if (!IS_ERR(demd)) {
 			err = -ENOENT;
 			if (demd->d_inode)
-				err = msdos_unlink (dentry->d_inode, demd);
+				err = vfat_unlink (dentry->d_inode, demd);
 Printk (("UMSDOS_rmdir: unlinking empty EMD err=%d", err));
 #ifdef UMSDOS_PARANOIA
 if (err)
@@ -916,14 +978,14 @@
 	umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
 	/* Call findentry to complete the mangling */
 	umsdos_findentry (dentry->d_parent, &info, 2);
-	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
+	temp = umsdos_fake_or_lfn(dentry->d_parent, &info);
 	ret = PTR_ERR(temp);
 	if (IS_ERR(temp))
 		goto out;
 	/*
 	 * Attempt to remove the msdos name.
 	 */
-	ret = msdos_rmdir (dir, temp);
+	ret = vfat_rmdir (dir, temp);
 	if (ret && ret != -ENOENT)
 		goto out_dput;
 
@@ -982,7 +1044,7 @@
 		goto out_unlock;
 	}
 
-Printk (("UMSDOS_unlink %.*s ", info.fake.len, info.fake.fname));
+Printk (("UMSDOS_unlink %.*s ", info.entry.name_len, info.entry.name));
 
 	/*
 	 * Note! If this is a hardlink and the names are aliased,
@@ -994,8 +1056,8 @@
 		d_drop(dentry);
 	}
 
-	/* Do a real lookup to get the short name dentry */
-	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
+	/* Do a real lookup to get the entry name dentry */
+	temp = umsdos_fake_or_lfn(dentry->d_parent, &info);
 	ret = PTR_ERR(temp);
 	if (IS_ERR(temp))
 		goto out_unlock;
@@ -1015,7 +1077,7 @@
 		goto out_dput;
 	}
 
-	ret = msdos_unlink(dir, temp);
+	ret = vfat_unlink(dir, temp);
 	if (!ret)
 		d_delete(temp);
 #ifdef UMSDOS_PARANOIA
diff -ur linux-my/fs/umsdos/rdir.c linux-mynew/fs/umsdos/rdir.c
--- linux-my/fs/umsdos/rdir.c	Sat Oct 20 20:09:12 2001
+++ linux-mynew/fs/umsdos/rdir.c	Mon Nov 12 14:05:19 2001
@@ -29,6 +29,7 @@
 	int real_root;
 };
 
+
 static int rdir_filldir (	void *buf,
 				const char *name,
 				int name_len,
@@ -96,8 +97,9 @@
 		goto out;
 	}
 
-	ret = msdos_lookup (dir, dentry);
-	if (ret) {
+	ret = vfat_lookup (dir, dentry);
+
+	if (IS_ERR(ret)) {
 		printk(KERN_WARNING
 			"umsdos_rlookup_x: %s/%s failed, ret=%ld\n",
 			dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -164,7 +166,7 @@
 	if (!d_unhashed(dentry))
 		goto out;
 
-	ret = msdos_rmdir (dir, dentry);
+	ret = vfat_rmdir (dir, dentry);
 	if (ret != -ENOTEMPTY)
 		goto out;
 
@@ -177,7 +179,7 @@
 		if (!IS_ERR(demd)) {
 			ret = 0;
 			if (demd->d_inode)
-				ret = msdos_unlink (dentry->d_inode, demd);
+				ret = vfat_unlink (dentry->d_inode, demd);
 			if (!ret)
 				d_delete(demd);
 			dput(demd);
@@ -187,7 +189,7 @@
 		goto out;
 
 	/* now retry the original ... */
-	ret = msdos_rmdir (dir, dentry);
+	ret = vfat_rmdir (dir, dentry);
 
 out:
 	return ret;
@@ -233,11 +235,11 @@
 
 struct inode_operations umsdos_rdir_inode_operations =
 {
-	create:		msdos_create,
+	create:		vfat_create,
 	lookup:		UMSDOS_rlookup,
-	unlink:		msdos_unlink,
-	mkdir:		msdos_mkdir,
+	unlink:		vfat_unlink,
+	mkdir:		vfat_mkdir,
 	rmdir:		UMSDOS_rrmdir,
-	rename:		msdos_rename,
+	rename:		vfat_rename,
 	setattr:	UMSDOS_notify_change,
 };
diff -ur linux-my/include/linux/umsdos_fs.h linux-mynew/include/linux/umsdos_fs.h
--- linux-my/include/linux/umsdos_fs.h	Fri Nov  2 12:50:32 2001
+++ linux-mynew/include/linux/umsdos_fs.h	Sun Dec  2 20:09:58 2001
@@ -2,17 +2,17 @@
 #define LINUX_UMSDOS_FS_H
 
 
-/*#define UMS_DEBUG 1	// define for check_* functions */
-/*#define UMSDOS_DEBUG 1*/
+/* #define UMS_DEBUG 1	// define for check_* functions */
+/* #define UMSDOS_DEBUG 1 */
 #define UMSDOS_PARANOIA 1
 
 #define UMSDOS_VERSION	0
-#define UMSDOS_RELEASE	4
+#define UMSDOS_RELEASE	5
 
 #define UMSDOS_ROOT_INO 1
 
 /* This is the file acting as a directory extension */
-#define UMSDOS_EMD_FILE		"--linux-.---"
+#define UMSDOS_EMD_FILE		"--linux5.---"
 #define UMSDOS_EMD_NAMELEN	12
 #define UMSDOS_PSDROOT_NAME	"linux"
 #define UMSDOS_PSDROOT_LEN	5
@@ -57,23 +57,24 @@
 	int len;
 };
 
+
 #define UMSDOS_MAXNAME	220
 /* This structure is 256 bytes large, depending on the name, only part */
 /* of it is written to disk */
 /* nice though it would be, I can't change this and preserve backward compatibility */
 struct umsdos_dirent {
-	unsigned char name_len;	/* if == 0, then this entry is not used */
-	unsigned char flags;	/* UMSDOS_xxxx */
-	unsigned short nlink;	/* How many hard links point to this entry */
-	__kernel_uid_t uid;	/* Owner user id */
-	__kernel_gid_t gid;	/* Group id */
-	time_t atime;		/* Access time */
-	time_t mtime;		/* Last modification time */
-	time_t ctime;		/* Creation time */
-	dev_t rdev;		/* major and minor number of a device */
+	__u8 name_len;		/* if == 0, then this entry is not used */
+	__u8 flags;		/* UMSDOS_xxxx */
+	__u16 nlink;		/* How many hard links point to this entry */
+	__u32 uid;		/* Owner user id (in 0.4 was __u16!) */
+	__u32 gid;		/* Group id (in 0.4 was __u16!) */
+	__u32 atime;		/* Access time */
+	__u32 mtime;		/* Last modification time */
+	__u32 ctime;		/* Creation time */
+	__u16 rdev;		/* major and minor number of a device */
 				/* special file */
-	umode_t mode;		/* Standard UNIX permissions bits + type of */
-	char spare[12];		/* unused bytes for future extensions */
+	__u16 mode;		/* Standard UNIX permissions bits + type of */
+	char spare[8];		/* unused bytes for future extensions */
 				/* file, see linux/stat.h */
 	char name[UMSDOS_MAXNAME];	/* Not '\0' terminated */
 				/* but '\0' padded, so it will allow */
diff -ur linux-my/include/linux/umsdos_fs.p linux-mynew/include/linux/umsdos_fs.p
--- linux-my/include/linux/umsdos_fs.p	Thu Aug 30 00:01:23 2001
+++ linux-mynew/include/linux/umsdos_fs.p	Sun Dec  2 13:06:27 2001
@@ -2,10 +2,6 @@
 void check_page_tables (void);
 
 /* dir.c 22/06/95 00.22.12 */
-int  dummy_dir_read ( struct file *filp,
-	 char *buf,
-	 size_t size,
-	 loff_t *count);
 char * umsdos_d_path(struct dentry *, char *, int);
 void umsdos_lookup_patch_new(struct dentry *, struct umsdos_info *);
 int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry);
@@ -13,6 +9,8 @@
 struct dentry *UMSDOS_lookup(struct inode *, struct dentry *);
 struct dentry *umsdos_lookup_dentry(struct dentry *, char *, int, int);
 struct dentry *umsdos_covered(struct dentry *, char *, int);
+struct dentry *umsdos_fake_or_lfn (struct dentry *, struct umsdos_info *);
+
 
 struct dentry *umsdos_solve_hlink (struct dentry *hlink);
 
@@ -27,6 +25,7 @@
 int umsdos_findentry (struct dentry *, struct umsdos_info *, int);
 int umsdos_isempty (struct dentry *);
 int umsdos_writeentry (struct dentry *, struct umsdos_info *, int);
+int umsdos_notify_change_locked(struct dentry *, struct iattr *attr);
 
 /* file.c 25/01/95 02.25.38 */
 
@@ -35,15 +34,14 @@
 void UMSDOS_read_inode (struct inode *);
 void UMSDOS_write_inode (struct inode *, int);
 int UMSDOS_notify_change (struct dentry *, struct iattr *attr);
-int umsdos_notify_change_locked(struct dentry *, struct iattr *attr);
 void UMSDOS_put_inode (struct inode *);
 int UMSDOS_statfs (struct super_block *, struct statfs *);
 struct super_block *UMSDOS_read_super (struct super_block *, void *, int);
 void UMSDOS_put_super (struct super_block *);
 
 void umsdos_setup_dir(struct dentry *);
-void umsdos_set_dirinfo_new(struct dentry *, off_t);
-void umsdos_patch_dentry_inode (struct dentry *, off_t);
+void umsdos_set_dirinfo_new(struct dentry *, loff_t);
+void umsdos_patch_dentry_inode (struct dentry *, loff_t);
 int umsdos_get_dirowner (struct inode *inode, struct inode **result);
 
 /* ioctl.c 22/06/95 00.22.08 */

