This patch originated with "H. Kawaguchi" <HFB03210@nifty.ne.jp>,
but I've tweaked it somewhat. It's seen fairly heavy use since.
----------------------------------------------------------------------
Hi,
I think that a file name generation rule on VFAT is
different from Windows.
Long name is not generated when I make 8+3 file name
in capital letters on Windows. But Linux generates it.
This patch does the following revisions.
o It makes a file name generation rule same as Windows
o By default, it shows short name in capital letters
o By "small" option, it shows short name with small letters
o By "forcelong" option, it always generates long name
----------------------------------------------------------------------
Index: include/linux/msdos_fs_sb.h
--- include/linux/msdos_fs_sb.h.prev
+++ include/linux/msdos_fs_sb.h Sat Jun 17 17:48:32 2000
@@ -25,5 +25,7 @@
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? */
+ small_letter:1, /* Use small letters for short name */
+ force_long:1; /* Force create longname */
};
Index: fs/fat/dir.c
--- fs/fat/dir.c.prev
+++ fs/fat/dir.c Sat Jun 17 17:48:32 2000
@@ -140,4 +140,5 @@ int fat_search_long(
int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
int utf8 = MSDOS_SB(sb)->options.utf8;
+ int small_letter = MSDOS_SB(sb)->options.small_letter;
unsigned char *unicode = NULL;
struct nls_table *nls = MSDOS_SB(sb)->nls_io;
@@ -227,5 +228,5 @@ parse_long:
for (i = 0, last = 0; i < 8;) {
if (!(c = de->name[i])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
+ if (small_letter) c = tolower(c);
if (c == 0x05) c = 0xE5;
if ((bufname[i++] = c) != ' ')
@@ -236,5 +237,5 @@ parse_long:
for (i2 = 0; i2 < 3; i2++) {
if (!(c = de->ext[i2])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
+ if (small_letter) c = tolower(c);
if ((bufname[i++] = c) != ' ')
last = i;
@@ -302,4 +303,5 @@ static int fat_readdirx(
int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
int utf8 = MSDOS_SB(sb)->options.utf8;
+ int small_letter = MSDOS_SB(sb)->options.small_letter;
unsigned char *unicode = NULL;
struct nls_table *nls = MSDOS_SB(sb)->nls_io;
@@ -420,5 +422,5 @@ ParseLong:
for (i = 0, last = 0; i < 8;) {
if (!(c = de->name[i])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
+ if (small_letter) c = tolower(c);
/* see namei.c, msdos_format_name */
if (c == 0x05) c = 0xE5;
@@ -430,5 +432,5 @@ ParseLong:
for (i2 = 0; i2 < 3; i2++) {
if (!(c = de->ext[i2])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
+ if (small_letter) c = tolower(c);
if ((ptname[i++] = c) != ' ')
last = i;
Index: fs/fat/inode.c
--- fs/fat/inode.c.prev
+++ fs/fat/inode.c Sat Jun 17 17:48:32 2000
@@ -217,4 +217,5 @@ static int parse_options(char *options,i
opts->codepage = 0;
opts->utf8 = 0;
+ opts->small_letter = 0;
opts->iocharset = NULL;
*debug = *fat = 0;
@@ -261,4 +262,7 @@ static int parse_options(char *options,i
else if (!strcmp(this_char,"showexec")) {
opts->showexec = 1;
+ }
+ else if (!strcmp(this_char,"small")) {
+ opts->small_letter = 1;
}
else if (!strcmp(this_char,"dotsOK") && value) {
Index: fs/vfat/namei.c
--- fs/vfat/namei.c.prev
+++ fs/vfat/namei.c Sat Jun 17 17:48:32 2000
@@ -121,4 +121,5 @@ static int parse_options(char *options,
opts->numtail = 1;
opts->utf8 = 0;
+ opts->force_long = 0;
if (!options) return 1;
@@ -143,7 +144,8 @@ static int parse_options(char *options,
} else if (!strcmp(this_char,"nonumtail")) {
ret = simple_getbool(value, &val);
- if (ret) {
- opts->numtail = !val;
- }
+ if (ret) opts->numtail = !val;
+ } else if (!strcmp(this_char,"forcelong") ||
+ !strcmp(this_char,"force_long")) {
+ opts->force_long = 1;
}
if (this_char != options)
@@ -384,5 +386,5 @@ static int vfat_valid_shortname(const ch
if (utf8 && (c & 0x80)) return -EINVAL;
if (strchr(replace_chars,c)) return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
+ if (islower(c)) return -EINVAL;
if (c < ' '|| c==':') return -EINVAL;
if (c == '.') break;
@@ -407,5 +409,5 @@ static int vfat_valid_shortname(const ch
if (c < ' ' || c == '.'|| c==':')
return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
+ if (islower(c)) return -EINVAL;
space = c == ' ';
}
@@ -429,4 +431,14 @@ static int vfat_find_form(struct inode *
}
+static void vfat_format_name_fast(const char *name,int len,char *res)
+{
+ char *walk = res;
+
+ while (len-- && *name != '.') *walk++ = *name++;
+ while (walk-res < 8) *walk++ = ' ';
+ while (--len >= 0) *walk++ = *++name;
+ while (walk-res < MSDOS_NAME) *walk++ = ' ';
+}
+
static int vfat_format_name(const char *name,int len,char *res,int utf8)
{
@@ -440,8 +452,8 @@ static int vfat_format_name(const char *
if (utf8 && (c & 0x80)) return -EINVAL;
if (strchr(replace_chars,c)) return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
+ if (islower(c)) return -EINVAL;
if (c < ' '|| c==':') return -EINVAL;
space = c == ' ';
- *walk = c >= 'a' && c <= 'z' ? c-32 : c;
+ *walk = c;
}
if (space) return -EINVAL;
@@ -456,7 +468,7 @@ static int vfat_format_name(const char *
if (c < ' ' || c == '.'|| c==':')
return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
+ if (islower(c)) return -EINVAL;
space = c == ' ';
- *walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
+ *walk++ = c;
}
if (space) return -EINVAL;
@@ -506,9 +518,5 @@ static int vfat_create_shortname(struct
if (*ip == ' ')
break;
- if (*ip >= 'A' && *ip <= 'Z') {
- *p = *ip + 32;
- } else {
- *p = *ip;
- }
+ *p = toupper(*ip);
}
}
@@ -556,9 +564,5 @@ static int vfat_create_shortname(struct
baselen++;
} else if (!strchr(skip_chars, *ip)) {
- if (*ip >= 'a' && *ip <= 'z') {
- *p = *ip - 32;
- } else {
- *p = *ip;
- }
+ *p = toupper(*ip);
if (strchr(replace_chars, *p)) *p='_';
p++; baselen++;
@@ -577,9 +581,5 @@ static int vfat_create_shortname(struct
extlen++;
} else if (!strchr(skip_chars, *ip)) {
- if (*ip >= 'a' && *ip <= 'z') {
- *p = *ip - 32;
- } else {
- *p = *ip;
- }
+ *p = toupper(*ip);
if (strchr(replace_chars, *p)) *p='_';
extlen++;
@@ -775,5 +775,5 @@ static int vfat_build_slots(struct inode
struct msdos_dir_entry *de;
char msdos_name[MSDOS_NAME];
- int res, xlate, utf8;
+ int res, xlate, utf8, force_long;
struct nls_table *nls;
@@ -781,17 +781,22 @@ static int vfat_build_slots(struct inode
xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
+ force_long = MSDOS_SB(dir->i_sb)->options.force_long;
nls = MSDOS_SB(dir->i_sb)->nls_io;
*slots = 1;
- res = vfat_valid_longname(name, len, xlate);
- if (res < 0)
- return res;
if (vfat_valid_shortname(name, len, utf8) >= 0) {
- vfat_format_name(name, len, de->name, utf8);
- return 0;
+ if (!force_long) {
+ vfat_format_name_fast(name, len, de->name);
+ return 0;
+ }
+ vfat_format_name_fast(name, len, msdos_name);
+ } else {
+ res = vfat_valid_longname(name, len, xlate);
+ if (res < 0)
+ return res;
+ res = vfat_create_shortname(dir, name, len, msdos_name, utf8);
+ if (res < 0)
+ return res;
}
- res = vfat_create_shortname(dir, name, len, msdos_name, utf8);
- if (res < 0)
- return res;
return vfat_fill_long_slots(ds, name, len, msdos_name, slots, xlate,
utf8, nls);
-- Chip Salzenberg - a.k.a. - <chip@valinux.com> "I wanted to play hopscotch with the impenetrable mystery of existence, but he stepped in a wormhole and had to go in early." // MST3K - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Thu Aug 31 2000 - 21:00:24 EST