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
end adding folder items to

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!

comments powered by Disqus