Sky Watch

# Wallpaper in a Encrypted Volume

## The Problem

I have three volumes in my Mac. I decided to encrypt the two non-boot volumes just for the sake of it. So I did that.

The next time I booted into the OS, I was greeted by an ultra-friendly dialog box asking for passwords. I did not want to do that every time I restart, so I let it remember the passwords in keychain. And the next time I restarted, I found my fine wallpaper was replaced by the default galaxy-in-space image, which I did not really fancy.

## Solution Number One

I knew the reason was that the encrypted volumes were mounted after the desktop was loaded. And given the stuborn-ness of Mac OS, it is probably humanly impossible to change that order. So I looked for an alternative — writing a script to kill the Dock application, which automatically reloads the desktop, and somehow running this script when I log in. If I am lucky enough, the script might be run after the encrypted volume is mounted. Here is the script,

#!/bin/sh
exec killall Dock


I ran it to confirm its correctness. Then I added it to my “Login Items” (try a better name next time, Apple). But, it did not work. Apparently it was executed before the volume was mounted.

## Solution Number Two

I had to search on the web to start my second attempt. This time it was a more apple-ish method. One can attach a script to a directory in Mac by setup a “folder action”, so that when there are some changes to that directory, the script gets to run. So in principle I could do this to /Volumes, and when a volume is mounted, the folder action should be done automatically. The problem is I do not like my desktop to flick all the time, so I need to know the mounted volume has a specific name. Noticing “Shared” being the name, I wrote an applescript for that,

on adding folder items to this_folder after receiving MountedVolumes
repeat with Volume in MountedVolumes
if name of Volume is "Shared" then
quit application "Dock"
end if
end repeat


I did not know if this is correct. I did not even read it a second time, and I suggest you avoid doing that as well. Applescripts are so purely ugly, one would have nightmares after reading too many of them. If one insists on getting some nightmares, I recommend Peskin — at least it has much more contents.

So I attached the script to /Volumes, and tried to unmount and mount the encrypted volume. Nothing happened (well, I mean besides the volume being unmounted and mounted...). Awesome. I did not like this method in the first place.

## Solution Number Three

So I did more search on the web, and found that the daemon launcher in Mac was launchd. It has a bunch of interfaces. One may use launchctl to start or stop a daemon, to list all daemons alive, to list all daemons available, and much more. Daemons are defined with XML files. A feature particularly useful in my scenario is the ability to run a daemon when a volume is mounted. So I created the following launchd job, and saved it as a plist under ~/Library/LaunchAgents,

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
http://www.apple.com/DTDs/PropertyList-1.0.dtd >
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.darksair.refreshdesktop</string>
<key>ProgramArguments</key>
<array>
<string>/Users/corsair/programs/refresh-desktop.sh</string>
</array>
<key>KeepAlive</key>
<false/>
<key>StartOnMount</key>
<true/>
<key>LaunchOnlyOnce</key>
<true/>
</dict>
</plist>


And refresh-desktop.sh ran like thus

#!/bin/sh

FileVolList=/tmp/volume-list.txt

if [ ! -e ${FileVolList} ]; then touch${FileVolList}
fi
if ! grep '^Shared' ${FileVolList} > /dev/null; then ls -1 /Volumes >${FileVolList}
if grep '^Shared' ${FileVolList} > /dev/null; then # Shared is mounted. exec killall Dock fi fi ls -1 /Volumes >${FileVolList}


Then I restarted the machine, and found that several seconds after the encrypted volume was mounted, the desktop flickered, and the correct wallpaper was loaded. Another stupid problem solved!