Block device access not alinged sector boundary fails...

Why don't the following commands work?

# dd if=/dev/ada4 of=/dev/null bs=1 count=512 skip=1
# dd if=/dev/ada4 of=/dev/null bs=511 count=512 skip=1

Only the following works: # dd if=/dev/ada4 of=/dev/null bs=512 count=512 skip=1. Because of this, I cannot random-access some packed structure directly on a partition.
 
Because it is a block device. Meaning you can only access it one block at a time. For disks, the "block" is commonly known as a sector (although the correct name should actually be block, and there is a distinction between logical block size and physical block size, but everybody just calls it a sector). For traditional disk drives, the sector size is 512 bytes (modern disk drives often have 4096 byte sectors, some disks have 520 or 528 byte sectors, CDs often have 2048 byte sectors, but most of the time sectors = 512 bytes).

The problem is actually deep in the hardware of the disk drive. A disk drive really can only write in units of sectors. The hardware is not even capable of modifying anything smaller than a sector, because it has to perform a "checksum" calculation (technically called ECC) on a sector-by-sector basis. And because you can't write anything smaller than a sector, there is also no hardware support to read anything smaller than a sector. In theory, the hardware could be taught to do transfers smaller than a secotr. But because the software that knows how to deal with raw disks (typically a file system, sometimes a data base, and occasionally utilities such as fdisk or gpart) knows how to deal in whole sectors, there is just no need for it.

The counterpart to a block device is a character device. There, you can read and write individual characters (thence the name). Classic example is a serial port.

What you have to do: either modify your program to read/write whole 512 byte units and pick them apart yourself, or copy data to/from the block device to something else (for example a temporary file), and then work on the temporary file. For example:
# dd if=/dev/ada4 of=/tmp/ada4.copy bs=512 count=512
# dd if=/tmp/ada4.copy bs=1 or 511 count=512 skip=1
and so on.
 
Thanks for the detailed explanation. Yes, that's a block device, I can access only multiple of blocks at a time. But, I have a question: why doesn't FreeBSD support accessing block devices like Linux does? On Linux, disk devices are also accessible at any location on a byte-unit basis - I mean when the disk device is opened using the same way as a regular file, that is seekable to any location (not a block boundary) and data can be read from it directly. FreeBSD does not, thus I cannot use some FUSE-based file system on a partition which has space-efficiently packed data structures and does not consider that use with block devices. The sample code above is just for testing, I don't really use that.
 
Back
Top