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: