NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/10715 (msdosfs LFN problems)
The following reply was made to PR kern/10715; it has been noted by GNATS.
From: Thomas Klausner <wiz%NetBSD.org@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: jdolecek%NetBSD.org@localhost, pooka%NetBSD.org@localhost
Subject: Re: kern/10715 (msdosfs LFN problems)
Date: Sat, 26 Jan 2008 15:46:43 +0100
--K8nIJk4ghYZn606h
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Sat, Jan 19, 2008 at 04:51:48PM +0000, Antti Kantee wrote:
> Synopsis: msdosfs LFN problems
>
> State-Changed-From-To: analyzed->feedback
> State-Changed-By: pooka%narn.netbsd.org@localhost
> State-Changed-When: Sat, 19 Jan 2008 18:51:47 +0200
> State-Changed-Why:
> does the patch in the PR work? it's high time we solve this as 7 years of
> discussing the problem has not produced a result
The patch didn't apply cleanly, I changed it to match the comment
above the list of characters.
The attached (perhaps wrongly updated) patch makes access to SFN files
on msdosfs fail, with:
ls: IMG_3098.JPG: Invalid argument
So either I updated it incorrectly, the rest of the code has changed
incompatibly in the meantime, or it is wrong :(
Thomas
--K8nIJk4ghYZn606h
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="lfnconv-updated.diff"
Index: msdosfs_conv.c
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfs_conv.c,v
retrieving revision 1.5
diff -u -r1.5 msdosfs_conv.c
--- msdosfs_conv.c 11 Dec 2005 12:24:25 -0000 1.5
+++ msdosfs_conv.c 25 Jan 2008 16:28:53 -0000
@@ -233,6 +233,12 @@
tsp->tv_nsec = (dh % 100) * 10000000;
}
+/*
+ * Characters allowed in short file names:
+ * letters, digits, characters with code value > 127 and
+ * $ % ' - _ @ ~ ` ! ( ) { } ^ # &
+ * All other characters are not allowed.
+ */
static const u_char
unix2dos[256] = {
0, 0, 0, 0, 0, 0, 0, 0, /* 00-07 */
@@ -240,7 +246,7 @@
0, 0, 0, 0, 0, 0, 0, 0, /* 10-17 */
0, 0, 0, 0, 0, 0, 0, 0, /* 18-1f */
0, '!', 0, '#', '$', '%', '&', '\'', /* 20-27 */
- '(', ')', 0, '+', 0, '-', 0, 0, /* 28-2f */
+ '(', ')', 0, 0, 0, '-', 0, 0, /* 28-2f */
'0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */
'8', '9', 0, 0, 0, 0, 0, 0, /* 38-3f */
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40-47 */
@@ -429,8 +435,7 @@
int i, j, l;
int conv = 1;
const u_char *cp, *dp, *dp1;
- u_char gentext[6], *wcp;
- int shortlen;
+ u_char gentext[6], *wcp, ch;
/*
* Fill the dos filename string with blanks. These are DOS's pad
@@ -464,13 +469,38 @@
return 0;
/*
+ * Skip leading blanks.
+ */
+ if (un[0] == ' ') {
+ conv = 3;
+ while(un[0] == ' ') {
+ un++;
+ unlen--;
+ }
+ }
+
+ /*
+ * Check that name contains only valid characters. If using
+ * long file names, couple additional characters are
+ * supported for them; handle them appropriately.
+ */
+ for(i=0; i < unlen; i++) {
+ ch = unix2dos[un[i]];
+ if (ch == 0) {
+ if (!strchr("+,;=[]", un[i]))
+ return (0);
+ conv = 3;
+ }
+ }
+
+ /*
* Now find the extension
* Note: dot as first char doesn't start extension
* and trailing dots and blanks are ignored
*/
- dp = dp1 = 0;
- for (cp = un + 1, i = unlen - 1; --i >= 0;) {
- switch (*cp++) {
+ dp = dp1 = NULL;
+ for (cp = un + 1, i = unlen - 1; --i >= 0; cp++) {
+ switch (*cp) {
case '.':
if (!dp1)
dp1 = cp;
@@ -478,9 +508,10 @@
case ' ':
break;
default:
- if (dp1)
+ if (dp1) {
dp = dp1;
- dp1 = 0;
+ dp1 = NULL;
+ }
break;
}
}
@@ -493,40 +524,35 @@
l = dp1 - dp;
else
l = unlen - (dp - un);
- for (i = 0, j = 8; i < l && j < 11; i++, j++) {
- if (dp[i] != (dn[j] = unix2dos[dp[i]])
- && conv != 3)
- conv = 2;
- if (!dn[j]) {
+ for (i = 0, j = 8; i < l && j < 11; i++) {
+ ch = unix2dos[dp[i]];
+ if (!ch) {
conv = 3;
- dn[j--] = ' ';
- }
+ continue;
+ } else if (dp[i] != ch && conv != 3)
+ conv = 2;
+
+ dn[j++] = ch;
}
if (i < l)
conv = 3;
- dp--;
} else {
for (dp = cp; *--dp == ' ' || *dp == '.';);
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 == ' ') && shortlen)
- dn[j] = ' ';
- else
- dn[j] = unix2dos[*un];
- if ((*un != dn[j])
- && conv != 3)
- conv = 2;
- if (!dn[j]) {
+ for (i = j = 0; un < dp && j < 8; i++, un++) {
+ ch = unix2dos[*un];
+ if (!ch) {
conv = 3;
- dn[j--] = ' ';
- }
+ continue;
+ } else if ((*un != ch) && conv != 3)
+ conv = 2;
+
+ dn[j++] = ch;
}
if (un < dp)
conv = 3;
--K8nIJk4ghYZn606h--
Home |
Main Index |
Thread Index |
Old Index