2008-11-22

Working with FAT32 in Ubuntu Linux

While I was working on my Xubuntu laptop server project I learned a lot about working with FAT32 drives on Linux, and I learned all of it the hard way.

Only the owner of a FAT32 mount can set file time stamps on it.

I tried using rsync to copy a directory from my mounted NSLU2 NAS to a FAT32 drive:

rsync -av /NASmountpoint /FAT32mountpoint

That caused all kinds of errors saying rsync couldn't set permissions on the encrypted drive. A little research showed that its not possible for rsync to set permissions on FAT32. So then I tried:

rsync -rltDv /NASmountpoint /FAT32mountpoint

That did better, but then gave errors about not being able to set dates on directories. So then I tried:

rsync -rltDvO /NASmountpoint /FAT32mountpoint

Adding the -O switch tells it not to try and set the date on directories. That fixed the errors, but then I noticed that the date-time of all of the files being copied over was set to today, which is not at all what I wanted.

I thought maybe it was a problem with rsync, so I tried using cp:

cp -arv /NASmountpoint/ /FAT32mountpoint

Result: The files copied, but the timestamps were not preserved and cp gave this message for each file: "cp: preserving times for `/media/truecrypt1/Washing Machines': Operation not permitted"

I double checked the permissions on the Truecrypt mount:

drwxrwxrwx 3 nobody andy 32768 2008-10-30 03:59

It looks like every user should have full permissions, but apparently they don't since its not possible to set file timestamps!

Next experiment: Dismount FAT32 partition and then remount it with option "uid=andy,umask=0000" and repeat the exact same cp operation.

Result: All the files copy over with the original timestamps properly preserved! Even the original timestamps were preserved on the directories, which is something rsync couldn't do under any circumstances.

Conclusion: In order to preserve original timestamps when using rsync or cp to copy files from a Samba share to a FAT32 mount you have to be logged in as the owner. Any other user will get an error, even if that user has full permissions to the FAT32 mount.

Next experiment: Dismounted the FAT32 partition, mounted it again with options "uid=nobody,umask=1000" and then try copying to it from the original NAS mount using "sudo cp..."

Result: All the files copied successfully with original timestamps preserved, but cp spit out the following error for each file "failed to preserve ownership for ... operation not permitted."

Next experiment: Try using "sudo -u nobody cp..." to run the copy command as user "nobody" which is the owner of the FAT32 partition.

Result: All files copied successfully with original timestamps preserved with no errors.

Conclusion: Only the owner of a FAT32 mount can copy files to it from another FAT32 mount without losing timestamps.

Experiment: Copy files from the NAS to my Xubuntu home directory, and then copy them to the Truecrypt partition (owner = nobody) as user andy.

Result: Original timestamps not preserved and cp gives errors.

Conclusion: Only the owner of a FAT32 mount can copy files to it without losing timestamps.

Once I understood the problem I was able to google other references to it:

Preserving time stamps on FAT32 copies Linux questions forum thread

Even the owner of a FAT32 mount can't set directory times reliably

Although I was now able to copy over the original file time stamps correctly I noticed that all of the directory modification times were set to the time I ran the rsync command, which is not what I wanted at all. A little googling uncovered this forum posting about this problem:

http://ubuntuforums.org/showthread.php?t=886048

This forum posting suggested adding the option "--modify-window=1", which gives 1 second slack on how closely file and directory times have to match before rsync will see them as different, and someone said that worked to correctly preserve original directory timestamps. This forum posting also referenced this article about Linux and FAT32:

http://www.osnews.com/story/9681/The_vfat_file_system_and_Linux/page1

Incidentally, this article recommended using these options when using rsync to a FAT32 drive:

rsync -rvt --modify-window=1

So, I was finally ready to do a dry run test of rsync to synchronize two FAT32 partitions:

sudo -u nobody rsync -av --delete --modify-window=1 /media/FirstFAT32/ /media/SecondFAT32 > /home/andy/logs/rsync_test.log

Success! The original directory timestamps were preserved, the new files were copied from the source to the destination with the original time stamps, the files deleted from the source were deleted from the destination, and nothing else was changed.

However, once I changed the destination FAT32 drive's mount option to "shortname=mixed" (see below) I noticed that the directory times on directories were not being preserved any longer when I ran rsync. I thought I had solved that problem! I went back and ran the exact same rsync command that had worked before, but the directory times were still not preserved! I think the only thing that had changed since it worked correctly the first time was mounting the truecrypt volumes with "shortname=mixed" but how could that make a difference?

Some more experimenting revealed that at least one empty directory had its time preserved. I tried cranking modify-window up to 2, but that still didn't work. I never did figure this one out.

The nightmare continues: The capitalization of short files names is messed up with FAT32 mounts

While I was researching the above, I came across this cryptic little tidbit:

Another lesson is that the FAT32 partition should be mounted with the "shortname=mixed" option. If not, the rsync gets messed up. The default option is "lower," which means that files and directories with short names will have their names forced to lower case. But then rsync will think they're different from the ones it sees in the source that are upper case, and it will send the upper case ones again, and then delete the lower case ones. But since it's really the same files, the end result is it transfers a bunch of data and then deletes it all! Not good.

Comparing my existing NAS with the duplicate on the FAT32 drive, sure enough I found that at least one directory name with an all caps name on the NAS had been converted to all lowercase on the encrypted drive. Doh!

So time to revise the FAT32 mount options to:

sudo mount -t vfat -o shortname=mixed /media/sdc1 /media/SecondFAT32

When I tested it by copying over some new files with short all caps names it seemed to work properly.

Haven't I suffered enough?: Rsync freaks out about capitalization changes when syncing two FAT32 drives

I now knew how to correctly preserve the capitalization of file names when copying to a FAT32 mount, but what to do about all the existing files and directories that had their case changed on my earlier attemps? I decided to try running an rsync dry run to see if it would pick up on the files and directories where the case of the name didn't match:

sudo -u nobody rsync -avn --delete --modify-window=2 --stats /media/FirstFAT32/ /media/SecondFAT32 > /home/andy/logs/test_sync.log

Then I verified the dry run log looked right and it showed that rsync planned to copy all the files and directories with a capitalization mismatch. Then I ran the same command without the n option to fire for effect. However, when I checked over the logs I noticed something very peculiar: Not all of the file and directory names with the wrong case were fixed. Some were, but not all. Even weirder, on these unfixed files rsync said in the log that it was deleting them on the destination, but then never said it copied them to the destination, and when I looked they were still on the destination. Whats up with that? Not only that, but there were big differences in the number of gigs copied between the dry run log and the actual run log.

By this point Linux had beat me into submission, so rather than try to puzzle out this weird behavior I just deleted everything on the /media/SecondFAT32 and started over by using cp to copy everything all over again.

When will it end: Accented characters in file names are lost with FAT32 mounts by default

I thought I was finally done. However, like in some Hollywood blockbuster where you think the villain is dead but then he suddenly springs back to life to threaten the heros again, Linux was not done with me yet.

When I checked over the copy I had made, all the characters with accents in the file names had been changed to underscores! Doh! I used a Windows box to run a Robocopy from the NAS to the encrypted drive, and it spotted and copied over those files with files with the corrected accented characters in their file names.

I found this article which discusses the missing accented characters problem with FAT32 mounts:

http://www.osnews.com/story/9681/The_vfat_file_system_and_Linux/page2/

Following the advice from this post I mounted by source FAT32 drive like so:

sudo mount -t vfat -o shortname=mixed,iocharset=utf8 /dev/sdc1 /media/FirstFAT32

I mounted the second FAT32 drive the same way. Thankfully that appeared to work and preserve accented characters in the file names.

Incidentally, the same accented characters problem happens when you mount a Samba share on a Linux box. I was never able to solve the problem, but this post claims to have a solution that apparently worked for other people:

http://ubuntuforums.org/showthread.php?t=728751

I spent a lot of time trying to solve this, but no matter what I did, I could not manage to mount my NSLU2 NAS so that it would show the accented characters in the file names. I suspect its because my NSLU2 is a few years old and uses an older version of Samba, and the solution posted in this forum post will only work on current versions of Samba.

1 comment:

Matt Spitz said...

THANK YOU! I've hit several of these problems before, and it's nice to have all the solutions laid out real nice.

Interesting note:
I couldn't get the shortname=mixed to work as an option in /etc/fstab. It only works passed as -o in the 'mount' command (for me anyway).

Bravo, sir.