A patch for FAT & VFAT

A. Wik (aw@mail1.bet1.puv.fi)
Mon, 16 Nov 1998 18:04:17 +0000


Linux (V)FAT has been using conventions that are incompatible with
other OSes for quite some time now, which has caused me a lot of
trouble (having to rename files). The patch below will fix it.

I've added a mount option - "case" - to the FAT file system. If
set to "asis", file names will be displayed the way NetBSD and the
Win95 DOS-prompt do.

Also, Win95 generates long file name entries for short lowercase
names, but Linux VFAT didn't. It seems the fact that uppercase
characters are below lowercase in ASCII (not the other way round)
may have been overlooked.

The patch will also be made available from:
ftp://mail1.bet1.puv.fi/incoming/

diff -ur linux-2.1.126/fs/fat/dir.c linux/fs/fat/dir.c
--- linux-2.1.126/fs/fat/dir.c Mon Aug 24 20:02:44 1998
+++ linux/fs/fat/dir.c Mon Nov 16 17:43:51 1998
@@ -9,6 +9,8 @@
*
* VFAT extensions by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu>
* Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk>
+ *
+ * Case-conversion made dependent on mount option / A. Wik, Nov 1998.
*/

#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
@@ -265,7 +267,8 @@
}
for (i = 0, last = 0; i < 8; i++) {
if (!(c = de->name[i])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
+ if (MSDOS_SB(sb)->options.lowercase &&
+ c >= 'A' && c <= 'Z') c += 32;
/* see namei.c, msdos_format_name */
if (c == 0x05) c = 0xE5;
if (c != ' ')
@@ -277,7 +280,8 @@
i++;
for (i2 = 0; i2 < 3; i2++) {
if (!(c = de->ext[i2])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
+ if (MSDOS_SB(sb)->options.lowercase &&
+ c >= 'A' && c <= 'Z') c += 32;
if (c != ' ')
last = i+1;
ptname[i] = c;
diff -ur linux-2.1.126/fs/fat/inode.c linux/fs/fat/inode.c
--- linux-2.1.126/fs/fat/inode.c Thu Sep 10 21:32:26 1998
+++ linux/fs/fat/inode.c Mon Nov 16 17:39:03 1998
@@ -3,6 +3,8 @@
*
* Written 1992,1993 by Werner Almesberger
* VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner
+ *
+ * A. Wik, 16 Nov 1998 Added "case=" mount option
*/

#include <linux/version.h>
@@ -113,6 +115,7 @@
int ret = 1, len;

opts->name_check = 'n';
+ opts->lowercase = 1;
opts->conversion = 'b';
opts->fs_uid = current->uid;
opts->fs_gid = current->gid;
@@ -143,6 +146,13 @@
opts->name_check = 'n';
else if (!strcmp(value,"strict"))
opts->name_check = 's';
+ else ret = 0;
+ }
+ else if (!strcmp(this_char,"case") && value) {
+ if (value[0]) if (!strcmp(value,"lower"))
+ opts->lowercase = 1;
+ else if (!strcmp(value,"asis"))
+ opts->lowercase = 0;
else ret = 0;
}
else if (!strcmp(this_char,"conv") && value) {
diff -ur linux-2.1.126/include/linux/msdos_fs_sb.h linux/include/linux/msdos_fs_sb.h
--- linux-2.1.126/include/linux/msdos_fs_sb.h Thu Jan 8 22:02:41 1998
+++ linux/include/linux/msdos_fs_sb.h Mon Nov 16 14:31:16 1998
@@ -24,7 +24,8 @@
posixfs:1, /* Allow names like makefile and Makefile to coexist */
numtail:1, /* Does first alias have a numeric '~1' type tail? */
atari:1, /* Use Atari GEMDOS variation of MS-DOS fs */
- fat32:1; /* Is this a FAT32 partition? */
+ fat32:1, /* Is this a FAT32 partition? */
+ lowercase:1; /* Convert file names to lowercase? */
};

struct vfat_unicode {
diff -ur linux-2.1.126/fs/vfat/namei.c linux/fs/vfat/namei.c
--- linux-2.1.126/fs/vfat/namei.c Wed Sep 9 05:26:29 1998
+++ linux/fs/vfat/namei.c Mon Nov 16 14:02:57 1998
@@ -465,7 +465,7 @@
if (utf8 && (c & 0x80)) return -EINVAL;
if (strchr(bad_chars,c)) return -EINVAL;
if (strchr(replace_chars,c)) return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
+ if (c >= 'a' && c <= 'z') return -EINVAL;
if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
if ((walk == name) && (c == 0xE5)) c = 0x05;
if (c == '.') break;
@@ -491,7 +491,7 @@
return -EINVAL;
if (c < ' ' || c == ':' || c == '\\' || c == '.')
return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
+ if (c >= 'a' && c <= 'z') return -EINVAL;
space = c == ' ';
}
if (space) return -EINVAL;
@@ -537,7 +537,7 @@
if (utf8 && (c & 0x80)) return -EINVAL;
if (strchr(bad_chars,c)) return -EINVAL;
if (strchr(replace_chars,c)) return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
+ if (c >= 'a' && c <= 'z') return -EINVAL;
if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
if (c == '.') break;
space = c == ' ';
@@ -561,7 +561,7 @@
return -EINVAL;
if (c < ' ' || c == ':' || c == '\\' || c == '.')
return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
+ if (c >= 'a' && c <= 'z') return -EINVAL;
space = c == ' ';
*walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
}
@@ -613,8 +613,8 @@
res = -1;
break;
}
- if (*ip >= 'A' && *ip <= 'Z') {
- *p = *ip + 32;
+ if (*ip >= 'a' && *ip <= 'z') {
+ *p = *ip - 32;
} else {
*p = *ip;
}
@@ -675,8 +675,8 @@
*p++ = '_';
baselen++;
} else if (!strchr(skip_chars, *ip)) {
- if (*ip >= 'A' && *ip <= 'Z') {
- *p = *ip + 32;
+ if (*ip >= 'a' && *ip <= 'z') {
+ *p = *ip - 32;
} else {
*p = *ip;
}
@@ -698,8 +698,8 @@
*p++ = '_';
extlen++;
} else if (!strchr(skip_chars, *ip)) {
- if (*ip >= 'A' && *ip <= 'Z') {
- *p = *ip + 32;
+ if (*ip >= 'a' && *ip <= 'z') {
+ *p = *ip - 32;
} else {
*p = *ip;
}
@@ -1167,7 +1167,7 @@
de->starthi = 0;
de->size = 0;
de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
- de->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
+ de->lcase = 0;


fat_mark_buffer_dirty(sb, bh, 1);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/