Tuesday, April 19, 2005

The joy of disk images

I've recently become an addict to MACOSX disk images.

We've all seen and felt disk images, those .dmg files that most software
comes as, but until I started playing around with them I didn't realise
how powerful they were. It all started with trying to burn an ISO format
CD and has degenerated to using images to backup data to my IPOD.

Allow me to explain.

I had downloaded a Linux distro for a friend and wanted to burn it to a
CD. So doing what I thought was the right thing I tried to drag the ISO
image into a blank CD (that I'd just inserted into the CD drive). But, to
my surprise, I got a "This is too big to fit" error.

So I tried the next most obvious thing: I double clicked on the ISO
image. Now, instead of bringing up some sort of CD burning tool,

MACOSX MOUNTED THE ISO IMAGE AS A DISK !.

I was able to browse the filesystem, look at the contents of the ISO and
generally treat it like a mounted file system.

Not being a virgin to things like loopfs I wasn't really shocked, but I
had to dig into how far apple had gone with automounting image files.
After a fair amount of googling I learnt learnt a lot of scary stuff
about disk images.

So what ? Well, what we're talking about is a REAL FILESYSTEM that can
live anywhere, In any format you like. Just like tarballs, all the
permissions and other stuff are stored in the image. But unlike a tarball
you can add and delete data by mounting the image and using normal
commands like 'cp' and 'mv'

I also found that the tool I really needed was the "Disk Utility" (you can
find it in the Utilities folder). This is the motherlode of all things
image wise and it has a CLI. From here you can burn images to CD, create
images and do all sorts of other neat things...

If you want to burn and ISO image you just DRAG the ISO into the pane on
the left and select 'Burn'. This almost makes sense.

But you can also create disk images (those .dmg files). Select
'Images->new->Blank Image...' And you can create a .dmg in any size and
format you want. From then on you can mount that image and add stuff into
it.

If you already have some files, you can create a custom sized image.
Select 'Images->new->Image from Folder...' And you'll have .dmg of that
data. Packaging made simple.

Trust me, it gets better.

Digging further I found that "Disk Utility" has a command line version
that is more powerful, its called "hdiutil" (man hdiutil) and has the all
important 'SPARSE' feature. A SPARSE image is a disk image that only uses
up as much disk space as the contents, not the actual size of the disk.
So you can create a 4GB disk image, but if there is nothing in it, it will
be a lot smaller (like ~10Mb).

You can try this yourself, want a journalled HFS+ filesystem ?

hdiutil create -type SPARSE -size 4g -fs HFS+J ~/Desktop/tmp.dmg

Then mount the file that gets created on your desktop (tmp.dmg.sparseimage)

So now we're really getting somewhere. For me this is very useful because
my IPOD is windows format,

This is a deliberate choice because it means I can mount the disk anywhere
and get at the data, but VFAT doesn't really handle permissions very
well. As I have some data that will really only work on a MAC and I'd
like to keep its permissions. Solution : create a sparse disk image on
the IPOD and copy the files into that. I can also use things like rsync
to keep the data up to date with the originals (this is a tad harder with
'tar')

What about encryption ?

Well, it is probably a good idea to encrypt your whole disk, but
something about that concept scares me - do I really want to boot from an
encrypted kernel ? Instead, I can just keep some of my data on an
encrypted disk image:

  hdiutil create -encryption -size 50m e.dmg -fs HFS+J


I can mount it when I need to, and just leave it sitting there when I
don't.

The list of features is really endless, but I'll finish the way I started,
with that ISO image. It turns out I CAN burn a CD from the commandline :

  hdiutil burn myImage.iso 


Oh, and I enjoyed this snippet from the hdiutil manpage :


Image from folder (new-style):
hdiutil create -srcfolder mydir mydir.dmg

Image from folder (10.1-style; of historical interest):
du -s myFolder # du(1) will count resource forks
10542
hdiutil create -sectors 10642 folder # add ~1% for filesytem
hdid -nomount folder.dmg
...
/dev/disk1s2 Apple_HFS
newfs_hfs -v myFolderImage /dev/rdisk1s2
hdiutil detach disk1
hdid folder.dmg
...
/dev/disk1s2 Apple_HFS /Volumes/myFolderImage
sudo mount -u -t hfs -o perm /dev/disk1s2 /Volumes/myFolderImage
# optionally enable owners; sudo unneeded if manually mounted

ditto -rsrcFork myFolder /Volumes/myFolderImage
hdiutil detach disk1s2 # when you are all done
hdiutil convert -format UDZO -o folder.z.dmg folder.dmg # compress