
Dd is not a disk writing tool (2015) - Ianvdl
http://www.vidarholen.net/contents/blog/?p=479
======
pixelbeat
Yes "D" is not for disk/drive/device/...

It comes from the DD (data definition) statement of OS/360 JCL, and hence why
dd has the unusual option syntax compared to other unix utils

BTW if you are using dd to write usb drives etc. it's useful to bypass the
Linux VM as much as possible to avoid systems stalls, especially with slow
devices. You can do that with O_DIRECT. Also dd recently got a progress
option, so...

    
    
        dd bs=2M if=disk.img of=/dev/sda... status=progress iflag=direct oflag=direct
    

Note dd is a lower level tool, which is why there are some gotchas when using
for higher level operations. I've noted a few at:

[http://www.pixelbeat.org/docs/coreutils-
gotchas.html#dd](http://www.pixelbeat.org/docs/coreutils-gotchas.html#dd)

~~~
carussell
You don't have to wait for updates to newer versions to get dd to report its
progress. The status line that dd prints when it finishes can also be forced
at any point during dd's operation by sending the USR1 or INFO signals to the
process. E.g.:

    
    
        ps a | grep "\<dd"
        # [...]
        kill -USR1 $YOUR_DD_PID
    

or

    
    
        pkill -USR1 ^dd
    

It also doesn't require you to get everything nailed down at the beginning.
You've just spent the last 20 seconds waiting and realize you want a status
update, but you didn't think to specify the option ahead of time? No problem.

I've thought that dd's behavior could serve as a model for a new standard of
interaction. Persistent progress indicators are known to cause performance
degradation unless implemented carefully. And reality is, you generally don't
need something to constantly report its progress even while you're not
looking, anyway.

To figure out the ideal interaction, try modeling it after the conversation
you'd have if you were talking to a person instead of your shell:

"Hey, how much longer is it going to take to flash that image?"

The way dd works is close to this scenario.

~~~
pixelbeat
Yes this is true. Note BSD supports this better with Ctrl-T to generate
SIGINFO, which one can send to any command even if not supported, in which
case it's ignored. Using kill on linux, and having that kill processes by
default is decidedly more awkward.

It's also worth noting the separate "progress" project which can be used to
give the progress of running file based utilities.

We generally have pushed back on adding progress to each of the coreutils for
these reasons, but the low overhead of implementation and high overlap with
existing options was deemed enough to warrant adding this to dd

~~~
stuaxo
Ctrl-T for SIGINFO is pretty useful, it would be good if Linux could pick this
up.

~~~
circuit_breaker
Been waiting for years, frankly. I guess if I was motivated enough and had the
time, I could do the research and submit patches..

~~~
feld
They don't want it. Even if you got the patches accepted to the kernel they'd
never accept patches to GNU Coreutils to support it.

~~~
feld
The most recent comment I've seen on this is lukewarm at best:
[http://lkml.iu.edu/hypermail/linux/kernel/1411.0/03374.html](http://lkml.iu.edu/hypermail/linux/kernel/1411.0/03374.html)

------
voidz
Most of the time it's much better (as in, faster) to just use cat (or pv, to
get a nice progress bar) for writing a file to a block device, because it
streams, and lets underlying heuristics worry about block sizes and whatnot.

So:

    
    
      cat foobar.img > /dev/sdi
    

will stream the file rather than what dd does, i.e. read block, write block,
read block, write block and so on.

Usually I also lower the vm.dirty_bytes and vm.dirty_background_bytes to 16
resp. 48 MB (in bytes) beforehand, which limits the buffer sizes to those
amounts. Else it will seem that the progress bar indicates 300MB/s is written,
and when it completes you still have to wait a really long time for things to
have been written out. Afterwards I restore back vm.dirty_ratio and
vm.dirty_background_ratio to respectively 10 and 5 - the defaults on my
system.

I wish that all of those projects, tutorials etc. that explain how to write
their image to a block device, like an sdcard, would start advise using cat,
because there is no reason to use dd, it's just something that people stick
with because others do it too.

I only use dd for specific blocks, like writing back a backup of the mbr, or
as a rudimentary hex editor.

~~~
RJIb8RBYxzAMX9u
> I wish that all of those projects, tutorials etc. that explain how to write
> their image to a block device, like an sdcard, would start advise using cat,
> because there is no reason to use dd, it's just something that people stick
> with because others do it too.

I'd wondered whether dd or cat were faster, and indeed cat is faster, but not
by much. Also, for some embedded devices, you have to write to specific
offsets, so dd is more convenient and explicit. Lastly, cat composes poorly
with sudo.

    
    
      $ sudo dd if=foobar.img of=/dev/sdi # works
      $ sudo cat foobar.img > /dev/sdi    # fails unless root b/c redirection is done by shell
    

> I only use dd for specific blocks, like writing back a backup of the mbr, or
> as a rudimentary hex editor.

xxd / xxd -r is much nicer, but I suppose sometimes vim is not available...

~~~
nerdponx
Would

    
    
        sudo (cat foobar.img > /dev/sdi)
    

Work?

~~~
sply
No, you should use

    
    
      sudo sh -c "cat foobar.img > /dev/sdi"
    

or

    
    
      sudo -s "cat foobar.img > /dev/sdi"

~~~
RJIb8RBYxzAMX9u
I was originally going to put that in my examples, but opted to leave it out,
because with sh -c you have to think about escaping special characters. Most
of the time it doesn't matter, but when running commands as root you ought to
be absolutely sure.

~~~
nerdponx
What about using a here-doc (as in
[http://stackoverflow.com/a/16514624/2954547](http://stackoverflow.com/a/16514624/2954547))?

    
    
        sudo sh <<EOF
        cat foobar.img > /dev/sdi
        EOF

------
realfinkployd
"Legend has it that the intended name, “cc”, was taken by the C compiler, so
the letters were shifted by one to give “dd”."

Legend is wrong, this clearly derived from the mainframe JCL DD command. This
is also why the syntax is so non unix-like.

[https://en.wikipedia.org/wiki/Job_Control_Language#In-
stream...](https://en.wikipedia.org/wiki/Job_Control_Language#In-stream_input)

------
ComputerGuru
I've seen people try to use dd to clone a bad disk before tossing it or
attempting recovery - while dd is not the right tool for the job, ddrescue [0]
is.

ddrescue gives you options for error handling and will skip past bad blocks,
it handles read errors much more gracefully.

[0]:
[https://www.gnu.org/software/ddrescue/](https://www.gnu.org/software/ddrescue/)

~~~
wa2flq
Agreed,using dd on media with flaws is not straight forward.

See [http://www.noah.org/wiki/Dd_-
_Destroyer_of_Disks](http://www.noah.org/wiki/Dd_-_Destroyer_of_Disks)

~~~
chillingeffect
Breaking your silence! Are you Mr. Spurrier? Ciao.

------
II2II
There are likely a number of reasons for using dd in tutorials designed for
beginners:

\- it is available by default on all Unix systems

\- it distinguishes between input and output (i.e. if= and of=)

\- it reports results

\- it avoids using a common command for a dangerous operation that the user
may not understand

dd also has another benefit: the ability to select a range of blocks to copy
from and to. This isn't the most common scenario, but it certainly pops up on
some devices.

~~~
beams_of_light
Sometimes, it seems like people try to outsmart common knowledge, and it's
fine to present new ideas, but one doesn't have to call what most know works
and use inappropriate for the tasks they use it to perform.

------
ryao
> This belief can make simple tasks complicated. How do you combine dd with
> gzip? How do you use pv if the source is raw device? How do you dd over ssh?

These operations are not that complicated. Behold the magic of UNIX pipes:

dd if=/dev/sdb | pv | gzip -c | ssh name@host "gzip -dc | dd of=/dev/sdc"

~~~
koala_man
It's even easier once you realize that dd is not required to read/write disks:

pv /dev/sdb | gzip -c | ssh name@host "gzip -dc > /dev/sdc"

Not only is this shorter with less cargo cult steps, it also gives a much
better `pv` output now that it can determine the size and show a percentage.

~~~
takeda
Not that parent poster's example is better than yours, since it also doesn't
do it, but I believe the biggest strength of dd over cat or redirection, is
that you can specify block size. With right block size you will get far better
performance and reduce wear of the device when writing block by click than
when writing data byte by byte.

The key though is to be aware of block size, and use multiply of it.

~~~
koala_man
It's not quite as simple as that when you're dealing with pipelines. For
example:

    
    
        cat /dev/zero | strace dd bs=1M of=/dev/null
    

will show that you're not actually writing 1M blocks. You're just reading
whatever `cat` outputs (128KiB blocks on my system), so all you've done is an
unnecessary pipe and copy. You would have been better off just redirecting.

Similarly,

    
    
        dd if=/dev/zero bs=1M | strace gzip -1 > /dev/null
    

will show you that `gzip` will not start processing larger blocks. You're just
adding an additional copy. Linux already has readahead, so I don't know if
you'll ever see a benefit to this.

On my system, adding dd with higher block size on both sides of a gzip -1
pipeline just ends up being slower.

~~~
takeda
That's because bs means "up to" so if input comes at smaller blocks it will
write in those. You should use obs, and preferably specify ibs to being
multiple of obs.

------
barhun
\+ "On UNIX, the adage goes, everything is a file."

\- not all the things on unix are abstracted as files (or 'byte streams' to be
more accurate). however, i/o resources and some ipc facilities are defined so.
an operating system provides many other abstractions in addition to these such
as processes, threads, non-stream devices, concurrency and synchronization
primitives, etc.; thus it's absolutely wrong to say that everything is a file
on unix.

~~~
RJIb8RBYxzAMX9u
"Everything is a file on UNIX" is as true as "Vulcan's cannot lie."

~~~
na85
I assume Vulcans can lie?

~~~
LeoPanthera
Technically they cannot lie. But they can exaggerate. Or omit facts.

------
mschuster91
The unique advantage of dd over cat, cp and friends: you can specify the block
size.

Just try (on OS X) dd if=disk.img of=/dev/disk1... first speedup is gained by
using rdisk1, but the real improvement comes with the bs=1m. 2 vs 16 vs 300
MB/s on my machine, when cloning via USB-SATA adapter.

~~~
nothrabannosir
I always wondered: what determines the optimal block size, and how can I know?

~~~
mschuster91
In theory the native block size (512 bytes for most drives these days) should
be the fastest, but the problem is that if you're doing such small sized I/O,
you introduce a shitload of overhead for all the individual r/w calls - I
guess that a huge blocksize benefits from DMA and look-ahead reads.

~~~
kosma
> native block size (512 bytes for most drives these days)

Not anymore. Advanced Format (4096-byte sector) hard drives have taken the
market like a storm, and SSDs benefit even more from using larger I/O sizes
(because erase sectors are way larger).

~~~
mschuster91
Ah, I thought it was the other way round. Thanks for the information.

Do you know a way to get an SSD's native erase sector size?

~~~
zielmicha
I would guess that using erase sector size as a block size won't help, because
SSD controller anyway rearranges blocks all the time.

------
notacoward
More importantly: dd is not a benchmarking tool. I can't count how many times
people have complained about dd being slow on a distributed filesystem. Well,
yeah. When you're writing only one block at a time with no
concurrency/parallelism at all, over a network interface that has much higher
latency than your disk interface, of course it's slow. When you're using tiny
block sizes, as about 80% of these people do, the effect is only magnified.
Unless your use case _for a distributed system_ is a single user who doesn't
even multitask, use iozone or fio instead.

~~~
sh_tinh_hair
Sure it is. It tells you exactly what performance a single threaded
application can expect with serial read()s and write()s (and whatever options
you choose to invoke dd with) against whatever file source and
constraints/conditions are extant at the time. Perfectly valid.

~~~
notacoward
OK, so it tells you how a very poorly written application - one which probably
shouldn't be running on such a system in the first place - will perform. And
it's useless for everyone else. Here, have an internet point.

~~~
sh_tinh_hair
It also tells you how a bunch of common tools will fare against your
wonderfully designed solution that is only 'truly' testable by sophisticated
methods.

Thanks for whatever it is that you gave me. I don't keep up with nomenclature
these days.

~~~
notacoward
Let me try to be a bit clearer. Yes, dd will tell you how _one instance_ of a
common tool might perform. That's one piece of information, but very likely
the least interesting piece of information for most use cases. It would be far
more useful to know how performance changes as you run _many instances_ of
those same common tools simultaneously, or what kind of performance a well
written application can achieve. Iozone or fio can give you all of the answers
dd would have, and many more answers besides.

Using dd in this role _and then complaining about the result_ before running
any other kind of test is a waste of everyone's time. No filesystem, even
local, is optimized for that kind of performance. You do know the difference
between performance and scalability, don't you? People who evaluate server-
oriented systems in 2017 based on a methodology more appropriate for a 1997
desktop are doomed to fail. In everything.

------
koala_man
Hello! I'm the author of this article.

Sorry for the confusion: dd is still a very useful tool for copying disks.

The point is that you should not feel like you have to shoehorn dd into any
command dealing with disks, because only dd is somehow "raw" or "low level"
enough to access them.

For example, if you have a command like this:

    
    
        pv file1 | gzip | ssh host "gzip -d > file2"
    

and you want to make it work with disks, just replace file1 and file2 with
/dev/yourdisks and it's fine.

------
pmontra
Indeed

    
    
        $ man dd
        NAME
               dd - convert and copy a file
    
        SYNOPSIS
               dd [OPERAND]...
               dd OPTION
    
        DESCRIPTION
               Copy a file, converting and formatting according to the operands.
        
        ...
    

More at [http://man7.org/linux/man-
pages/man1/dd.1.html](http://man7.org/linux/man-pages/man1/dd.1.html)

See the part after "Each CONV symbol may be:"

------
rollthehard6
I came from Solaris land originally and it always surprises me how seldom
people use filesystem level utilities to copy such stuff, i.e. ufsdump |
ufsrestore or dump | restore

Works a treat and using the fs level tool you know everything will be properly
copied, much safer.

~~~
rollthehard6
Obviously I'm not talking about raw devices, but people copying disks which
often don't have that many filesystems on them.

------
peterburkimsher
Can we have a single-purpose tool for getting the text between two delimiter
strings?

I know it's possible with regex, but given how frequently that parsing logic
is needed, and the difficulty of getting sed right, I think a "tb" tool would
be very helpful.

~~~
tacostakohashi
At least for delimiter characters, that's what cut is.

~~~
eigengrau
Unless those characters are Unicode (unpatched GNU cut).

------
erikb
Reminds me of "find", which is another tool that is mostly just used for its
most boring application.

~~~
hasenj
What are some of its more interesting applications?

~~~
erikb
If you need to do anything on a list of files/dirs, but they are not in the
same place, or not easily filterable (e.g., all sub directories "/Fillion" but
not the ones that start with "Nathan") you can use find to prefilter
everything, then hand it over via xargs (if you want all to be handled by one
instance of the action program) or with "-exec" (if you want each instance to
be handled by a separate instance by the action program).

Also check out "find tutorial" articles like this one:
[http://www.grymoire.com/Unix/Find.html](http://www.grymoire.com/Unix/Find.html)
(e.g., did you know you can filter by size?)

------
tambourine_man
Yes, but you can't set block size to n bytes in cat.

Also, it's useful to have in the back of your mind that dd can very easily
mean Disk Destroyer, specially because of it's sui generis syntax

~~~
koala_man
On the other hand, cat's block size can increase over time to remain
reasonable. When I first became aware of it, it was 4 KiB. Now strace shows my
GNU cat using 128 KiB.

------
iamdave
It also doesn't stand for 'destroy-disk' as was thought by a junior admin I
employed once, and eventually had to fire because the level of incompetence
was getting to the point of almost being destructive.

Nope, that's not hyperbole. I had to stop the kid from almost installing
software that would have connected to a known botnet to help a user connect a
personal computer to the VPN. He passed enough checks during the interview we
figured "Okay, we can train him in the rest of the things"

Lesson learned.

~~~
brokenmachine
What software connects to a known botnet to allow connection to a VPN?

~~~
iamdave
[https://www.pcworld.com/article/2928340/ultra-popular-
hola-v...](https://www.pcworld.com/article/2928340/ultra-popular-hola-vpn-
extension-sold-your-bandwidth-for-use-in-a-botnet-attack.amp.html?client=ms-
android-hms-tmobile-us)

A user was wanting to bypass some of our network restrictions and the intrepid
jr. Admin suggested Hola unblocker to watch Netflix with me sitting 3 feet
away.

This was effectively the final straw and convinced me I had made the wrong
hire. He was out two days later.

------
voltagex_
If you're building disk images with blank space in them (say, for an 8GB EMMC,
but your root is only 2GB) you may want to use bmap-tools [1] [2]

This way only actual data is written to the device, blocks of zeros can be
skipped.

1: [https://lwn.net/Articles/563355/](https://lwn.net/Articles/563355/) 2:
[https://github.com/01org/bmap-tools](https://github.com/01org/bmap-tools)

------
daveguy
It may not be a disk writing tool, but it works wonders for swapping from HDD
to SDD without having windows freak out and decide you are stealing it.

~~~
UhUhUhUh
Seconded.

------
ScottBurson
My favorite thing to do with 'dd' is to break up multi-gigabyte log files
into, say, 500MB chunks, so I can easily view and search them in XEmacs (this
is 'csh' syntax as I use 'tcsh'):

    
    
      foreach i (0 1 2 3 [...])
      dd <big.log >big.log.$i bs=500m count=1 skip=$i
      end
    

(XEmacs is very fast at reading large files but has a 1GB limit.)

~~~
abbeyj
How about using

    
    
        split -db 500M big.log big.log.
    ?

~~~
ScottBurson
Oh wow, I never knew about that. Thanks!

------
mlaux
> It’s unique in its ability to issue seeks and reads of specific lengths,
> which enables a whole world of shell scripts that have no business being
> shell scripts. Want to simulate a lseek+execve? Use dd!

How would one simulate a call to execve with dd? Seems like a totally
different problem domain.

~~~
kosma
There's a common idiom of skipping a file header and handing off processing to
some other program, like this:

    
    
        cat foo | ( dd bs=$HEADERSIZE skip=1 of=/dev/null; process-foo-contents )

~~~
fiddlerwoaroof
Cool, although this doesn't really help with my most common-case, skipping the
first line.

    
    
        (head -1 > /dev/null; cat -) < file

~~~
koala_man
This is undefined behavior: while `head -1` will only output a single line, it
may read more.

It happens to work on GNU head when stdin is seekable file, because GNU head
specifically rewinds the stream before exiting:

    
    
        $ (strace  -e read,write,lseek head -1 > /dev/null; cat -) < file
        ...
        read(0, "hello\nworld\n", 8192)         = 12
        lseek(0, -6, SEEK_CUR)                  = 6    # <-- here
        write(1, "hello\n", 6)                  = 6
        +++ exited with 0 +++
    

If not for that explicit `lseek`, `head -1` would have skipped the entire 8k
buffer.

As far as I know, this is exclusive to GNU cat. Neither Busybox nor OSX cat
will do this, and will therefore throw away an entire buffer instead of just
the first line. You can try it out:

(busybox head -1 > /dev/null; cat -) < file

~~~
fiddlerwoaroof
Interesting. Is this true of `tail -n +2` as well? (On mobile, can't test at
the moment).

~~~
ucs
Tail employs a large read buffer as well, but it does not matter because you
wouldn't use it in the same manner.

Tail is the right tool for the job here. But if you wish to stick with your
idiom, _read_ will reliably consume a single line of input, regardless of how
it is implemented:

    
    
      (read -r; cat) < file

~~~
koala_man
If anyone is wondering why `read` can reliably read a single line while head
can't, it's because it reads byte by byte.

This is just as inefficient as it sounds, but it doesn't matter much in
practice since you rarely read a lot with it.

------
skipt
dd is for converting EBCDIC to ASCII and vice versa :)

    
    
      $ echo how now brown cow > text.ascii
      $ dd conv=ebcdic < text.ascii > text.ebcdic
      0+1 records in
      0+1 records out
      18 bytes copied, 0.000261094 s, 68.9 kB/s
      $ od -xc text.ebcdic 
      0000000    9688    40a6    9695    40a6    9982    a696    4095    9683       
              210 226 246   @ 225 226 246   @ 202 231 226 246 225   @ 203 226
      0000020    25a6
              246   %
      0000022
      $ dd conv=ascii < text.ebcdic
      how now brown cow
      0+1 records in
      0+1 records out
      18 bytes copied, 0.000140529 s, 128 kB/s

------
dockinator
What? Yes dd absolutely is a disk writing tool, although that is not the only
or even the tool's intended primary purpose.

It is useful for generating serial IO for a variety of purposes. For example,
writing data with specific target block size; allocating contiguous blocks for
use by an application (be it zeroing out a thin LUN before partitioning, or a
file system); or simply dumping the content of one device to another (or to a
file).

Good luck stretching out a thin LUN or creating an empty file that allocates
contiguous space with cat.

------
vermaden
> How do you combine dd with gzip?

# dd < /dev/ada0 bs=8m | gzip -c -9 > /mnt/file.raw.gz

> How do you use pv if the source is raw device?

# dd < /dev/ada0 bs=8m | pv | dd > /dev/ada1 bs=8m

> How do you dd over ssh?

# dd < /dev/ada0 bs=8m | gzip -9 | pv | ssh user@host 'dd > /dev/da1 bs=8m'

> This belief can make simple tasks complicated.

As master Dennis Ritchie once said - "UNIX is very simple, it just needs a
genius to understand its simplicity."

~~~
vacri
Did you really want an un-gzip'd copy on your target in that last one?

------
jwr
The best thing about dd is that you can use it with conv=noerror, which will
let you recover as much data as possible from an otherwise damaged device.

~~~
Freaky
That loses you a dd blocksize chunk, which is likely much bigger than the
underlying damaged sector.

ddrescue or recoverdisk (part of FreeBSD base) will both skip over unreadable
blocks, then retry with smaller block sizes along the damaged areas to save as
much data as possible.

~~~
cellularmitosis
Indeed. Also, you'd actually want 'conv=noerror,sync'. The 'sync' keeps the
input and output block counts in sync (if an input block can't be read, it
writes an output block of zeros to keep the block counts in 'sync').

The arch wiki page is very useful:
[https://wiki.archlinux.org/index.php/disk_cloning](https://wiki.archlinux.org/index.php/disk_cloning)

------
bradknowles
IIRC, there was a windowing system called "W", which pre-dated X. However, it
was crude and there was good reason for wanting to replace it.

~~~
floatboth
Funny how the new windowing system is also "W"…
([https://wayland.freedesktop.org](https://wayland.freedesktop.org) especially
the logo)

------
acomjean
So what is the best way to clone a disk(or in my case a raspberry pi sd cars)?

I tried to backup one of my cards last week using dd > .iso file and then
tried to put it on a new card. I tried with /dev/Rdisk (faster) but none of
the new cards was bootable.

So this is saying just use copy.

(I ended up just creating a second boot disk, and ftping the files over which
seems less than ideal...)

~~~
koala_man
The article doesn't say to stop using `dd` to write disks.

It's just saying that if you have other commands that can read/write files,
such as `pv /dev/thing > file.img` (to show a progress bar), you don't have to
try to shoe-horn dd into it just because /dev/thing happens to be a drive.

------
Poiesis
In my experience dd is great for binary data. Yes, pretty much everything on
Unix operates on files, as does dd. But so many utilities are either line
based or don't handle null bytes, and it's a pain to have determine how a
given program handles binary data when I know dd will at least not mess with
it.

------
fuzzfactor
"Not a disk-writing tool?!?"

Who knew?

Now we have pretty good confirmation that this little utility is performing
way more effectively than designed.

Software itself could probably benefit from some of the same approaches that
allowed this little computer program to outperform its original design goals,
in ways that might not have been anticipated.

------
catwell
One of those Unix tools that would deserve to be better known is dcfldd
([http://dcfldd.sourceforge.net/](http://dcfldd.sourceforge.net/)). It is
basically dd with extra powers including on-the-fly hashing, progression,
multiple outputs...

------
YeGoblynQueenne
>> The reason why people started using it in the first place is that it does
exactly what it’s told, no more and no less.

Oh yes indeed. And for this exact reason, "dd" is commonly backronymed to
"Data Death" (or, indeed, " _Disk_ Death").

------
microcolonel
This is not strictly true. For example, good luck trying to scp a device to a
remote host.

~~~
progman
> scp a device to a remote host
    
    
      dd if=/dev/hda bs=512 | (ssh root@remote dd of=/dev/hdX bs=512)
    

where bs=512 is the block size in bytes. Of course, the hdX drive must be
different from the remote hosts's main drive, otherwise dd won't complete :-)

~~~
microcolonel
That is not my point. I meant to say that scp itself will refuse to open the
block device file for reading.

------
juliangoldsmith
The statement

    
    
      cp myfile.iso /dev/sdb
    

is simply wrong. That will overwrite the device node for your flash drive with
the ISO, instead of writing the data to the drive.

------
andrewshadura
bmaptool is my image writing tool, and I think it should be yours too.

