December 26, 2008

Linux & Automounting of removable USB disks: Xfce take

Automounting of the removable USB devices seems to be a recurring problem for many Linux users. It's caused by the opaque interaction between ConsoleKit, PolicyKit and the desktop environment. Even if the desktop environment supports the volume management (and I believe all major Linux desktops do: GNOME, KDE, XFCE), missing just one link in the fragile chain of interactions between the desktop components will break automounting, and possibly other things such as sound in PulseAudio.

I'll take Xfce desktop as an example since I've had some troubles with it automounting the USB flash sticks. The prerequisites for working automounting in Xfce are: running dbus daemon (it's a must for the recent desktops anyway), running consolekit daemon, running Thunar (check for "thunar --daemon" process), and configured Thunar volume management (check "Enable Volume Management" option in the Advanced tab of the File Manager section in the settings).

But even having all that running doesn't guarantee the success. Enter the infamous "org.freedesktop.hal.storage.mount-removable no <-- (action, result )" error message, which seems to be perfectly in line with a long-time Unix tradition of the cryptic error messages. What's worse, the error window doesn't elaborate on what component has failed and why.

Common answer to that is the addition of the following snippet to /etc/PolicyKit/PolicyKit.conf:
<match action="org.freedesktop.hal.storage.mount-removable">
<return result="yes">
</return></match>

However this is actually wrong - this fix is akin to removing the password from some user account if the user is unable to login instead of providing them with the new password.

Another symptom of this problem is the lack of PolicyKit authorizations in the polkit-auth output (check at the end of this post for a "good" authorization list):
$ polkit-auth
org.freedesktop.hal.device-access.cdrom

After the long investigation I found that my X session wasn't registered with ConsoleKit:
$ ck-list-sessions 
Session2:
uid = '501'
realname = ''
seat = 'Seat1'
session-type = ''
active = FALSE
x11-display = ''
x11-display-device = ''
display-device = '/dev/tty1'
remote-host-name = ''
is-local = TRUE
on-since = '2008-12-23T19:04:59Z'
idle-since-hint = '2008-12-23T19:05:33Z'

See, only my tty1 console session is there, no sign of my X session started from that console. Here's how a registered X session should look:
$ ck-list-sessions 
...
Session4:
uid = '501'
realname = ''
seat = 'Seat1'
session-type = ''
active = TRUE
x11-display = ':0'
x11-display-device = '/dev/tty7'
display-device = ''
remote-host-name = ''
is-local = TRUE
on-since = '2008-12-26T09:28:52Z'

Why my Xorg session wasn't registered?
Here I must confess that I don't use GDM or any other display manager, so I (correctly) assumed that it was the cause. Apparently GDM and KDM take care of registering with the ConsoleKit, and /usr/bin/startxfce4 script used to start Xfce from the console fails to do that.

After some more Googling and experimentation I found this XDM bug which gave me a hint - /usr/bin/ck-xinit-session should be executed during the Xorg startup, preferably immediately after X server is launched.

Here's my solution to this: create .config/xfce4/xinitrc in your home directory, make it executable and invoke /usr/bin/ck-xinit-session before Xfce xinitrc:

echo -e '#!/bin/sh\n\n' > ~/.config/xfce4/xinitrc
echo 'exec /usr/bin/ck-xinit-session sh /etc/xdg/xfce4/xinitrc' >> ~/.config/xfce4/xinitrc
chmod u+x ~/.config/xfce4/xinitrc

After starting Xfce, I checked the session list and my X session was there. Bingo! After inserting a guinea USB stick and waiting a few seconds, I was greeted with a Thunar window with the USB stick content. So automounting finally worked, too, and without enabling it for everyone and everywhere with that PolicyKit.conf hack.

Here's a "working" output from polkit-auth for the reference:
org.freedesktop.hal.wol.enabled
org.freedesktop.hal.wol.enable
org.freedesktop.hal.wol.supported
org.freedesktop.hal.storage.mount-removable
org.freedesktop.hal.storage.eject
org.freedesktop.hal.storage.crypto-setup-removable
org.freedesktop.hal.power-management.shutdown
org.freedesktop.hal.power-management.reboot
org.freedesktop.hal.power-management.set-powersave
org.freedesktop.hal.power-management.suspend
org.freedesktop.hal.power-management.hibernate
org.freedesktop.hal.power-management.cpufreq
org.freedesktop.hal.power-management.lcd-panel
org.freedesktop.hal.power-management.light-sensor
org.freedesktop.hal.power-management.keyboard-backlight
org.freedesktop.hal.lock
org.freedesktop.hal.killswitch.bluetooth
org.freedesktop.hal.killswitch.wlan
org.freedesktop.hal.killswitch.wwan
org.freedesktop.hal.dockstation.undock
org.freedesktop.hal.device-access.sound
org.freedesktop.hal.device-access.video4linux
org.freedesktop.hal.device-access.cdrom
org.freedesktop.hal.device-access.dvb
org.freedesktop.hal.device-access.camera
org.freedesktop.hal.device-access.scanner
org.freedesktop.hal.device-access.audio-player
org.freedesktop.hal.device-access.ieee1394-iidc
org.freedesktop.hal.device-access.ieee1394-avc
org.freedesktop.hal.device-access.pda
org.freedesktop.consolekit.system.stop
org.freedesktop.consolekit.system.restart
org.pulseaudio.acquire-real-time

I hope this guide will be useful for those diehards who don't use GDM/KDM. As a bonus, this technique fixes the sound in PulseAudio for me.