Subject: kern/7229: msdosfs gets confused about spaces in filenames
To: None <gnats-bugs@gnats.netbsd.org>
From: Bill Sommerfeld <sommerfeld@orchard.arlington.ma.us>
List: netbsd-bugs
Date: 03/25/1999 03:28:56
>Number:         7229
>Category:       kern
>Synopsis:       msdosfs gets confused about spaces in filenames
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Mar 24 19:35:00 1999
>Last-Modified:
>Originator:     Bill Sommerfeld
>Organization:
	
>Release:        19990324
>Environment:
	
System: NetBSD orchard.arlington.ma.us 1.3K NetBSD 1.3K (ORCHARDII) #43: Sat Mar 20 17:51:07 EST 1999 sommerfeld@orchard.arlington.ma.us:/usr/src/sys/arch/i386/compile/ORCHARDII i386


>Description:

My laptop (an IBM Thinkpad 701CS) does "safe suspend" memory
checkpoints into a file named (on the DOS side) `C:\TP 701.HIB'.

When mounted on /dosc, an ls -l reports an error stat'ing `tp.hib'.

There are two bugs here: 

First, the msdos-to-unix pathname conversion function doesn't deal
with filenames with spaces in the middle; it stops copying before the
first space, rather than at the last non-space.

Once this bug is fixed, the second bug emerges: the unix-to-msdos
pathname conversion function isn't an exact inverse of the
msdos-to-unix pathname conversion function.

>How-To-Repeat:

	mount dos partition using msdosfs on IBM 701 Thinkpad set up with a
	hibernate file.

	ls -l the root directory of the partition.

this behavior also causes `amanda' backups of the dos partition to
fail even with *.hib in the ignore list..

>Fix:

The following appears to fix the problem but may introduce other
incompatibilities.


Index: msdosfs_conv.c
===================================================================
RCS file: /cvsroot/src/sys/msdosfs/msdosfs_conv.c,v
retrieving revision 1.26
diff -u -r1.26 msdosfs_conv.c
--- msdosfs_conv.c	1999/01/07 15:03:36	1.26
+++ msdosfs_conv.c	1999/03/25 03:26:06
@@ -357,7 +357,7 @@
 	u_char *un;
 	int lower;
 {
-	int i;
+	int i, j;
 	int thislong = 1;
 	u_char c;
 
@@ -372,18 +372,22 @@
 	else
 		c = dos2unix[*dn];
 	*un++ = lower ? u2l[c] : c;
-	dn++;
 
 	/*
-	 * Copy the name portion into the unix filename string.
+	 * Copy the rest into the unix filename string, ignoring
+	 * trailing blanks.
 	 */
-	for (i = 1; i < 8 && *dn != ' '; i++) {
-		c = dos2unix[*dn++];
+
+	for (j=7; (j >= 0) && (dn[j] == ' '); j--)
+		;
+
+	for (i = 1; i <= j; i++) {
+		c = dos2unix[dn[i]];
 		*un++ = lower ? u2l[c] : c;
 		thislong++;
 	}
-	dn += 8 - i;
-
+	dn += 8;
+	
 	/*
 	 * Now, if there is an extension then put in a period and copy in
 	 * the extension.
@@ -424,6 +428,7 @@
 	int conv = 1;
 	const u_char *cp, *dp, *dp1;
 	u_char gentext[6], *wcp;
+	int shortlen;
 
 	/*
 	 * Fill the dos filename string with blanks. These are DOS's pad
@@ -503,11 +508,17 @@
 		dp++;
 	}
 
+	shortlen = (dp - un) <= 8;
+
 	/*
 	 * Now convert the rest of the name
 	 */
 	for (i = j = 0; un < dp && j < 8; i++, j++, un++) {
-		if (*un != (dn[j] = unix2dos[*un])
+		if ((*un == ' ') && shortlen)
+			dn[j] = ' ';
+		else
+			dn[j] = unix2dos[*un];
+		if ((*un != dn[j])
 		    && conv != 3)
 			conv = 2;
 		if (!dn[j]) {

>Audit-Trail:
>Unformatted: