There's not a lot of information about this on The Google, so hopefully this blog will help anyone who wants to know how to get the serial number of a FAT partition from within a Unix-like operating system (including Linux and Mac OS X).
First, this is what I mean about serial numbers. Suppose you're using a Windows system, have a floppy disk at drive
A:/ and a regular USB flash drive at
E:/, and you run these commands in the command prompt:
C:\>vol E: Volume in drive E is CRUZER Volume Serial Number is 955C-59BF C:\>vol A: Volume in drive A has no label. Volume Serial Number is EC2B-36AFThese serial numbers are assigned when the drive is formatted; reformatting a floppy disk or flash drive will give it a different serial number.
According to The Wikipedia, the serial number (ID) is kept in two different places on the partition depending on the version of FAT being used.
In FAT12 and FAT16 (used with floppy disks), the ID begins at byte offset 0x27 (39 in decimal); in FAT32 (used with flash drives and external hard drives), the ID begins at 0x43 (67 in decimal).
So, with the handy
dd utility that comes standard on pretty much any Unix-like system, you can extract this information and display it. Here are a couple of one-liners you can run in a Unix terminal. I'll explain how they work afterward.
# For FAT32 filesystems (modern flash drives) dd if=/dev/sdb1 skip=67 bs=1 count=4 | hexdump -v -e '1/1 "%02X" " "' | xargs perl -e '@_=@ARGV; print "Serial Number: $_$_-$_$_\n"' # For FAT12/16 filesystems (old floppy drives) dd if=testfloppy.img skip=39 bs=1 count=4 | hexdump -v -e '1/1 "%02X" " "' | xargs perl -e '@_=@ARGV; print "Serial Number: $_$_-$_$_\n"'I underlined the input file (if) and byte offset (skip) in both of these commands. In the first one, I ran the command on a real, physical, flash drive, that had a device node at
/dev/sdb1for its one and only partition. In the second one, I ran it on a floppy disk image file (who has a computer with a real floppy drive these days?)
If you're going to be using a physical device like in my first command, you need to run the command with root privileges (regular users can't read directly from the device node). My second example (using an image file) can be run as a regular user, however.
These commands printed in the terminal for me:
(for the flash drive) 4+0 records in 4+0 records out 4 bytes (4 B) copied, 3.3445e-05 s, 120 kB/s Serial Number: 955C-59BF (for the floppy image) 4+0 records in 4+0 records out 4 bytes (4 B) copied, 3.1551e-05 s, 127 kB/s Serial Number: EC2B-36AFAnd now, how the commands work. I'll use the flash drive command as the example. In this one-liner, three commands are being executed at once:
dd if=/dev/sdb1 skip=67 bs=1 count=4 hexdump -v -e '1/1 "%02X" " "' xargs perl -e '@_=@ARGV; print "Serial Number: $_$_-$_$_\n"'The
ddcommand gets the operating system to read raw data from the flash drive at
/dev/sdb1, skipping the first 67 bytes, reading only 1 byte at a time, and reading a total of 4 bytes. This gets the 4 byte serial number; now we need to display it in hexadecimal like Windows and DOS.
The hexdump command takes the 4 binary bytes and displays them in hexadecimal. On my flash drive, it looks like this:
BF 59 5C 95. Note that the hex codes are out of order; Windows shows them as
955C-59BF - basically, the reverse of what hexdump shows. Hexdump is showing the correct order; Windows and DOS reverse them when they show you the serial number.
So, we run it through xargs (which turns the four hex numbers into four separate parameters) and sends them to a quick Perl script, which prints out "
Serial Number:" and puts the hex codes in the correct order, to give the same result as Windows and DOS.
One could use this information to make a
vol command for Unix. If the command checks other places in the filesystem headers to determine the version of FAT, it could automatically use the correct byte offset and get the serial number from both floppy disks and flash drives.