Short version: In what circumstances is dd safe to use for copying data, safe meaning that there is no risk of corruption due to a partial read or write?
Long version — preamble: dd is often used to copy data, especially from or to a device (example). It's sometimes attributed mystical properties of being able to access devices at a lower level than other tools (when in fact it's the device file that's doing the magic) — yet dd if=/dev/sda is the same thing as cat /dev/sda. dd is sometimes thought to be faster, but cat can beat it in practice. Nonetheless, dd has unique properties that make it genuinely useful sometimes.
Problem: dd if=foo of=bar is not, in fact, the same as cat <foo >bar. On most unices¹, dd makes a single call to read(). (I find POSIX fuzzy on what constitutes “reading an input block” in dd.) If read() returns a partial result (which, according to POSIX and other reference documents, it's allowed to unless the implementation documentation says otherwise), a partial block is copied. Exactly the same issue exists for write().
Observations: In practice, I've found that dd can cope with block devices and regular files, but that may just be that I haven't exercised it much. When it comes to pipes, it's not difficult to put dd at fault; for example try this code:
yes | dd of=out bs=1024k count=10
and check the size of the out file (it's likely to be well under 10MB).
Question: In what circumstances is dd safe to use for copying data? In other words, what conditions on the block sizes, on the implementation, on the file types, etc, can ensure that dd will copy all the data?
(GNU dd has a fullblock flag to tell it to call read() or write() in a loop so as to transfer a full block. So dd iflag=fullblock oflag=fullblock is always safe. My question is about the case when these flags (which don't exist on other implementations) are not used.)
¹ I've checked on OpenBSD, GNU coreutils and BusyBox.