view · edit · print · history

Under normal circumstances with both Unslung and OpenSlug it is possible to mount a FAT file system(approve sites) (the original file system used by Microsoft products) with the simple command:

mount <device> <directory>

for example, if the file system is in the first partition on the second hard drive and you want to mount it on /mnt:

mount /dev/sdb1 /mnt

This will mount the partition with long filename support using the kernel vfat module. The kernel knows about FAT file systems and knows which module to look for.

This will not work if the relevant kernel modules are not installed, or have been removed. See the troubleshooting section below.

There is, however, one big problem with the simple mount command. With no arguments mount will make an arbitrary choice (depending on kernel configuration) of the method to represent the long file names on the Linux system. This will either cause many characters to be replaced by ?, resulting in different files with the same name, or it will cause the case insensitive file name matching which the vfat module implements to not work.

The mount command to fix this depends on the local character set you want to use, it will be something like:

mount -o codepage=850,iocharset=iso8859-1,utf8 /dev/sdb1 /mnt

Avoiding character problems

To avoid the problem with characters the mount command needs to be passed the three extra arguments shown above - two parameters and a flag.

You need to find out the values for the two parameters. If the FAT file system is only to be used on UNIX and you don't care about the case insensitivity arbitrary values are fine. If you need to swap the disk back to a proprietary Microsoft system or case insensitive behaviour is important you need to choose the values carefully.

The language selection parameters

There are two parameters for historical reasons. The parameters perform the same function - defining how to interpret the bytes used to store a file name - but in slightly different contexts.

the OEM charset used to interpret byte values between 128 and 255 in a short file name. This is a numeric reference to the relevant IBM code page definition.
the definition of the byte encoding used to represent each UNICODE character of a long file name.

The original FAT file system implementations (up to FAT16?) stored the file names in 11 bytes. A byte value less than 128 is assumed to indicate an ASCII character - only a very restricted number of the possible values are permitted (for example lower case a-z are not permitted.) Values 128 and greater are interpreted using the codepage value.

Later versions of the file system, starting with VFAT in Windows 95, added support for UNICODE(approve sites) characters. UNICODE represents each character in 16 bits, the UNICODE consortium defined a single set of characters sufficient to represent all the distinct characters (but not glyphs) in use throughout the world.

Linux file systems do not support 16 bit characters. The iocharset option handles this by defining a byte representation for the characters. This is equivalent to what the pre-UNICODE Microsoft FAT file systems did in the short file names (using codepage).

Internally the Linux file system code makes no assumption about the encoding of the characters beyond treating the two byte values 0 and 47 (the ASCII '/' character) specially. Externally - in devices and in many applications - Linux is moving toward the UTF-8 encoding of UCS, which allows the representation of both UNICODE (16 bit) and ISO/IEC 10646 (UCS - 32 bit characters).

A short overview of ISO/IEC 10646 and Unicode(approve sites) is a reasonable high level overview, though not an introduction.

As a result of the support for UTF-8 selecting the right iocharset value is much less important - the only thing it affects is the pairs of values considered to be different cases of the same character.

Selecting a codepage

Because short file names are stored as bytes it is necessary to select a code page to (in effect) define what short file names are valid.

On FAT file systems not intended for use on existing Microsoft computers the default - 437 - is adequate. It has the advantage that there are relatively fewer useful characters in the range 128-255, therefore more file names will be stored as unambiguous long file names. It has the disadvantage that very few Linux systems use this as the code page - 850 (a western european code page) is more common.

Given a Microsoft system, simply find the code page used for the disk partition! To do this type the command chcp at a DOS command prompt.

If all you care about is the correct handling of upper and lower case characters for your language just leave the code page as the default.

Selecting iocharset

Many Linux users select utf8 as the iocharset value. This works well for file names from languages which do not have distinguished upper and lower case characters, but has the disadvantage that the kernel vfat module will not regard any characters as differing only in case.

This causes weird behaviour with the ASCII Latin characters A-Z when used in short file names - the vfat module may attempt to create or access a file with a short name differing only in case from an existing file and this will fail when the lower levels of the filesystem convert lowercase a-z to upper case.

Despite this the default on OpenSlug is to make the default iocharset be utf8 as this is the only default setting which guarantees not to change a large number of UNICODE characters into ? characters!

To avoid this, and to gain better interworking with Microsoft products, select the iocharset corresponding to your normal language. When the utf8 flag is specified along with iocharset the iocharset value only controls the character case handling - it has no effect on the encoding of the UNICODE characters as this will always use UTF-8.

The utf8 flag cannot be specified by default - it must be given as an explicit argument to mount

You can find the available character sets from ipkg by listing the relevant kernel modules:

ipkg list 'kernel-module-nls-*'

The tail of the module name gives the character set (or codepage).

The mount command

Combine the codepage, iocharset and utf8 to give the options for mount. If you use utf8 as the value for iocharset the utf8 flag is not necessary, but it is harmless. For example, on a Greek system:

mount -o codepage=869,iocharset=iso8859-7 /dev/sdb1 /mnt

This will probably fail the first time you try it because the character sets are not installed on the system:

# mount -o codepage=869,iocharset=iso8859-7 /dev/sdb1 /mnt
mount: Mounting /dev/sda1 on /mnt failed: Invalid argument

Use logread to check the cause of the problem:

kernel: Unable to load NLS charset cp869
kernel: FAT: codepage cp869 not found

Then use ipkg to install the required code page and charset. The name of the code page module is:

kernel-module-nls-cp<code page number>

That of the iocharset is:


Accessing the short file names

The Linux vfat module hides the short file names. There is no way round this - it is only possible to see either the short names or the long names!

To see the short names (in cases where there is a long name too) the partition can be mounted using the msdos module. You may need to install the kernel module (kernel-module-msdos). Then mount command still requires a codepage value, but iocharset and utf8 are not used:

mount -t msdos -o codepage=850 /dev/sdb1 /mnt

Select the code page as before. The file system will show only the short names, and only valid short names may be used for new files. The behaviour when using an invalid name may be unexpected - the name simply gets truncated.


As a first step it is worth adding the -t option to the mount command to ensure that the kernel looks for the correct module.

mount -t vfat

as appropriate (with the other arguments as before.) In rare cases this may cause the kernel autoload to succeed. If the autoload itself is failing there is a bigger problem with your system setup, but you can work round it by using insmod directly if necessary.

The most likely problem is that a kernel module is missing from your installation, however the symptom is typically just the error Invalid argument from mount:

# mount /dev/sda3 /mnt
mount: Mounting /dev/sda3 on /mnt failed: Invalid argument

logread will normally give some clue as to the nature of the problem - for example in the above case /dev/sda3 was not a FAT partition:

kernel: FAT: bogus number of reserved sectors
kernel: VFS: Can't find a valid FAT filesystem on dev sda3.

If the message is No such device and the partition device is correct:

# mount /dev/sdb1 /mnt
mount: Mounting /dev/sdb1 on /mnt failed: No such device

The file system module itself is almost certainly missing (this condition may also produce the Invalid argument message). Use ipkg to install it - either kernel-module-vfat or kernel-module-msdos. ipkg may need to install other modules too. It will install the nls support modules but it will not install specific code pages or character sets, follow the instructions above to install the correct code page and charset using ipkg.

view · edit · print · history · Last edited by jbowler.
Originally by jbowler.
Page last modified on April 14, 2005, at 03:26 PM