Export to GitHub

grub4dos-chenall - issue #167

FAT32 file name/directory name upper/lower case issue


Posted on Feb 23, 2014 by Happy Kangaroo

What steps will reproduce the problem:

If a USB drive is formatted as FAT32, the case of the filenames and folders is not correct when listed by ls command.

See attached screenshots.

What is the expected output? What do you see instead?

This is important because if specifying a name for linux, the case needs to be correct.

Some filenames and folders are correct, but others are not???

What version of the product are you using? On what operating system? 0.4.5c 17 Jan 2014

Please provide any additional information below.

If I create two folder in the root E2B MNU A Aa

in grub4dos they are listed as e2b mnu a Aa

if I change E2B to xE2B, then grub4dos lists it as xE2B (correct!)

If I create a folder MAINMENU in the root, grub4dos lists it as mainmenu. If I change it to MAINMENUx, grub4dos lists it correctly. If I remove the x, grub4dos lists it as mainmenu again!

If I create a folder ANTIVIRUS, then grub4dos lists it correctly as ANTIVIRUS. If I shorten it to ANTIVIRU, it is listed as antiviru.

Is it to do with the sum of the letters ???

Attachments

Comment #1

Posted on Feb 25, 2014 by Happy Kangaroo

This seems to be a FAT v. VFAT issue. Byte 12 in the directory entry has bit 4 = lowercase extension, bit 3=lowercase base filename. The main thing is that when specifying filenames or folder names as a kernel parameter - e.g. scan-iso/filename=/fred or from=/fred/doris.iso or from=/FRED/DORIS.ISO are linux distros case sensitive?

e.g. CentOS displays filenames in the same way that Win7 does (i.e. as determined by byte 12).

fsys_fat.c has code:

short_name: /* XXX convert to 8.3 filename format here */ { int i, j, c;

for (i = 0; i < 8 && (c = filename[i] = tolower (dir_buf[i]))
       && /*!isspace (c)*/ c != ' '; i++);

filename[i++] = '.';

for (j = 0; j < 3 && (c = filename[i + j] = tolower (dir_buf[8 + j]))
       && /*!isspace (c)*/ c != ' '; j++);

if (j == 0)
  i--;

filename[i + j] = 0;
  }

This should look at byte 12 bits 3 & 4 to determine whether to use uppercase or lowercase, not just convert all to lowercase.

Maybe a switch in grub4dos could control what mode it is in FAT or VFAT ???

Comment #2

Posted on Feb 25, 2014 by Happy Kangaroo

This (very bad!) code seems to work

short_name: /* XXX convert to 8.3 filename format here / { int i, j, c; if ( (dir_buf[12] & 8) == 8) { for (i = 0; i < 8 && (c = filename[i] = tolower (dir_buf[i])) && /!isspace (c)*/ c != ' '; i++);

}

if ( (dir_buf[12] & 8) == 0)
{
for (i = 0; i < 8 && (c = filename[i] =  (dir_buf[i]))
       && /*!isspace (c)*/ c != ' '; i++);
}

filename[i++] = '.';

if ( (dir_buf[12] & 16) == 16)
{
for (j = 0; j < 3 && (c = filename[i + j] = tolower (dir_buf[8 + j]))
       && /*!isspace (c)*/ c != ' '; j++);
}

if ( (dir_buf[12] & 16) == 0)
{
for (j = 0; j < 3 && (c = filename[i + j] =  (dir_buf[8 + j]))
       && /*!isspace (c)*/ c != ' '; j++);
}

if (j == 0)
  i--;

filename[i + j] = 0;
  }

valid_filename:

Comment #3

Posted on Feb 25, 2014 by Happy Kangaroo

define LCASE_BASE 0x08 // filename base in lower case

define LCASE_EXT 0x10 // filename extension in lower case

This is used to define the bits.

Comment #4

Posted on Feb 26, 2014 by Massive Kangaroo

Try and see if this could work:

short_name: /* XXX convert to 8.3 filename format here */ { unsigned int i, j, c, y;

define TOLOWER(c,y) (((y) && ((unsigned)((c) - 'A') < 26)) ? ((c)|0x20) : (c))

y = (dir_buf[12] & 0x08);   // filename base in lower case
for (i = 0; i < 8 && (c = filename[i] = TOLOWER (dir_buf[i], y))
       && /*!isspace (c)*/ c != ' '; i++);

filename[i++] = '.';

y = (dir_buf[12] & 0x10);   // filename extension in lower case
for (j = 0; j < 3 && (c = filename[i+j] = TOLOWER (dir_buf[8+j], y))
       && /*!isspace (c)*/ c != ' '; j++);

if (j == 0)
  i--;

filename[i + j] = 0;
  }
Attachments

Comment #5

Posted on Feb 26, 2014 by Happy Kangaroo

Yes - works fine :-)

Comment #6

Posted on Feb 26, 2014 by Happy Kangaroo

P.S. Are tolower and TOLOWER identical in function?

Comment #7

Posted on Feb 27, 2014 by Massive Kangaroo

no, not identical.

TOLOWER is a "conditional tolower", it turns char to lower case if and only if y is True or Yes.

Comment #8

Posted on Feb 27, 2014 by Happy Kangaroo

Sure, but what I mean is

tolower equivalent to (((y) && ((unsigned)((c) - 'A') < 26)) ? ((c)|0x20) : (c))

Comment #9

Posted on Feb 27, 2014 by Massive Kangaroo

as explained above, in the case of y == True,

tolower(c) is equivalent to (((y) && ((unsigned)((c) - 'A') < 26)) ? ((c)|0x20) : (c))

Comment #10

Posted on Feb 27, 2014 by Happy Kangaroo

OK thanks - will there be a new 0.4.5c version soon please? I want to release a new version of Easy2Boot with the new version of grldr. Thanks :-)

Comment #11

Posted on Feb 27, 2014 by Massive Kangaroo

I think you may compile your own "new" version. And I think it will be equivalent to the upcoming release by grub4dos team.

Comment #12

Posted on Feb 28, 2014 by Helpful Elephant

Adoption in GRUB4DOS 0.4.6a .

Comment #13

Posted on Mar 2, 2014 by Helpful Elephant

Comment deleted

Comment #14

Posted on Mar 4, 2014 by Helpful Elephant

If both long file names, another short file names, grub4dos content output by long file names. If only short file names, grub4dos uppercase to lowercase. After modification, GRUB4DOS will be 12 bytes, 3,4-bit control.

Comment #15

Posted on Jun 21, 2014 by Happy Hippo

This issue was updated by revision r374.

Status: Fixed

Labels:
Type-Defect Priority-Medium