This patch originated with "H. Kawaguchi" <[EMAIL PROTECTED]>,
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. -              <[EMAIL PROTECTED]>
"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 [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to