HAL methods at storage device level, to mount/unmount/eject volumes
Kay Sievers
kay.sievers at vrfy.org
Thu Dec 8 07:49:26 PST 2005
HAL volume method interface to request privileged operations like mount, umount, eject
Every storage device which contains a recognized filesystem exposes the
methods, which can be invoked over the usual HAL D-BUS interface:
Mount(string:path, string:options)
UnMount()
Eject()
In the future, this interface could be extended to provide SetLabel(),
Format() or any other useful action.
For the Mount() method, the name for the mount point directory in /media
can be specified. Also the usual otions passed to the mount call can be
passed as a single string:
/org/freedesktop/Hal/devices/volume_uuid_3e999973_00c9_4917_9442_b7633bd95b9e.Mount("Photos", "ro,iocharset=iso8859-1")
will request the mounting of the device at /media/Photos. It will be mounted
read-only and with the specified character encoding.
The methods and the interface are defined here:
/usr/share/hal/fdi/policy/10osvendor/20-storage-methods.fdi
Helper scripts executed with the a method invocation are located here:
/usr/share/hal/scripts/hal-system-storage-<method-name>
The D-BUS interface is controlled by the usual bus access control, which
can be limited to locally logged-in users by specifying:
<policy context="default">
<deny send_interface="org.freedesktop.Hal.Device.Volume"/>
</policy>
<policy at_console="true">
<allow send_interface="org.freedesktop.Hal.Device.Volume"/>
</policy>
in:
/etc/dbus-1/system.d/hal.conf
The invoked method helpers, usually implemented as shell scripts, will need to
check for secure operations. Even when only locally logged in users are allowed
to invoke methods, the mount script itself, must check the options passed from
the user call.
All the policy about storage handling will live in the user session only. It is
driven by an asynchronous event sequence. The desktop session will receive an
event for a new storage device, can match against the offered persisten properties of
the device or volume, lookup an already stored or compute a new moutpoint and request
the mounting of the volume by invoking the method on the hal device object.
Order of events:
################
New Media:
new device kernel -> hal(new device) -> desktop (new udi)
desktop (matching config against udi, request mount with udi and options from config)
hal (create mountpoint, mount)
kernel (mount)
kernel (mount change event) -> hal -> desktop
Request Eject/Umount in GUI:
desktop (request umount)
hal (umount) - if it fails, desktop throws error
hal (remove mountpoint if created by hal)
kernel (umount/shutdown device)
kernel (mount change event) -> hal -> desktop
Press EjectButton
HAL (reads event from device) -> desktop ("EjectPressed")
desktop (request umount)
hal (umount) - if it fails, desktop throws error
kernel (umount)
kernel (mount change event) -> hal -> desktop
Mount Method Example:
#####################
dbus-send --system --print-reply --dest=org.freedesktop.Hal \
/org/freedesktop/Hal/devices/volume_uuid_a5ea6ca9_485c_4e0f_95b3_ea85324403e2 \
org.freedesktop.Hal.Device.Volume.Mount string:MyDevice string:ro
mount:
$ dbus-send --system --print-reply --dest=org.freedesktop.Hal ...
method return sender=:1.496 -> dest=:1.629
uint32 0
failing mount:
$ dbus-send --system --print-reply --dest=org.freedesktop.Hal ...
Error org.freedesktop.Hal.Device.Volume.AlreadyMounted: /media/MyDevice
UnMount Method Example:
#######################
dbus-send --system --print-reply --dest=org.freedesktop.Hal \
/org/freedesktop/Hal/devices/volume_uuid_a5ea6ca9_485c_4e0f_95b3_ea85324403e2 \
org.freedesktop.Hal.Device.Volume.UnMount
umount:
$ dbus-send --system --print-reply --dest=org.freedesktop.Hal /org/freede ...
method return sender=:1.496 -> dest=:1.634
uint32 0
failing umount:
kay at pim:~/hal-mount> dbus-send --system --print-reply --dest=org.freedesktop.Hal /org/freede ...
Error org.freedesktop.Hal.Device.Volume.NotMounted:
Thanks,
Kay
-------------- next part --------------
<?xml version="1.0" encoding="UTF-8"?>
<deviceinfo version="0.2">
<device>
<match key="volume.fsusage" string="filesystem">
<append key="info.interfaces" type="strlist">org.freedesktop.Hal.Device.Volume</append>
<append key="org.freedesktop.Hal.Device.Volume.method_names" type="strlist">Mount</append>
<append key="org.freedesktop.Hal.Device.Volume.method_signatures" type="strlist">ss</append>
<append key="org.freedesktop.Hal.Device.Volume.method_execpaths" type="strlist">hal-system-storage-mount</append>
<append key="org.freedesktop.Hal.Device.Volume.method_names" type="strlist">UnMount</append>
<append key="org.freedesktop.Hal.Device.Volume.method_signatures" type="strlist"></append>
<append key="org.freedesktop.Hal.Device.Volume.method_execpaths" type="strlist">hal-system-storage-unmount</append>
<append key="org.freedesktop.Hal.Device.Volume.method_names" type="strlist">Eject</append>
<append key="org.freedesktop.Hal.Device.Volume.method_signatures" type="strlist"></append>
<append key="org.freedesktop.Hal.Device.Volume.method_execpaths" type="strlist">hal-system-storage-eject</append>
</match>
</device>
</deviceinfo>
-------------- next part --------------
#!/bin/sh -e
# Copyright (C) 2005, Kay Sievers <kay.sievers at vrfy.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2.
MOUNT_ROOT="/media"
# Check for environment variables
if [ "$HAL_PROP_BLOCK_DEVICE" == "" ] || [ "$HAL_PROP_INFO_UDI" == "" ] ; then
echo "Missing or empty environment variable(s)." >&2
echo "This script should be started by hald." >&2
exit 1
fi
# check if device is already mounted
if [ "$HAL_PROP_VOLUME_IS_MOUNTED" = "true" ]; then
echo "org.freedesktop.Hal.Device.Volume.AlreadyMounted" >&2
echo "$HAL_PROP_VOLUME_MOUNT_POINT" >&2
exit 1
fi
# read parameters
read GIVEN_MOUNTPOINT
read GIVEN_MOUNTOPTIONS
# if no mountpoint, get mountpoint from label
if [ "$GIVEN_MOUNTPOINT" == "" ]; then
case "$HAL_PROP_VOLUME_LABEL" in
*[!A-Za-z0-9_\-\+:]*)
break
;;
esac
GIVEN_MOUNTPOINT="$HAL_PROP_VOLUME_LABEL"
fi
# if no mountpoint, use default name
if [ "$GIVEN_MOUNTPOINT" == "" ]; then
GIVEN_MOUNTPOINT="disk"
fi
# validate characters in mountpoint
case "$GIVEN_MOUNTPOINT" in
*[!A-Za-z0-9_\-\+:]*)
echo "org.freedesktop.Hal.Device.Volume.InvalidMountpoint" >&2
echo "" >&2
exit 1
;;
esac
MOUNTPOINT="$GIVEN_MOUNTPOINT"
# pass only whitelisted mount options
if [ "$GIVEN_MOUNTOPTIONS" != "" ]; then
MOUNTOPTIONS="nosuid,nodev,user"
case "$GIVEN_MOUNTOPTIONS" in
*ro*)
MOUNTOPTIONS="$MOUNTOPTIONS,ro"
;;
esac
case "$GIVEN_MOUNTOPTIONS" in
*sync*)
MOUNTOPTIONS="$MOUNTOPTIONS,sync"
;;
esac
case "$GIVEN_MOUNTOPTIONS" in
*quiet*)
MOUNTOPTIONS="$MOUNTOPTIONS,quiet"
;;
esac
fi
# append number to mountpoint if it already exists
if [ -e "$MOUNT_ROOT/$MOUNTPOINT" ]; then
NUM=1;
while [ -e "$MOUNT_ROOT/$MOUNTPOINT-$NUM" ]; do
NUM=$(($NUM + 1))
done
MOUNTPOINT="$MOUNTPOINT-$NUM"
fi
# create directory and mark it for cleanup with an extended attribute
if [ ! -e "$MOUNT_ROOT/$MOUNTPOINT" ]; then
MOUNTPOINT_CREATED=1
mkdir "$MOUNT_ROOT/$MOUNTPOINT"
attr -s HAL_MOUNTPOINT -V "$HAL_PROP_INFO_UDI" "$MOUNT_ROOT/$MOUNTPOINT" > /dev/null 2>&1
fi
if [ ! -e "$MOUNT_ROOT/$MOUNTPOINT" ]; then
echo "org.freedesktop.Hal.Device.Volume.FailedToCreateMountpoint" >&2
echo "$MOUNT_ROOT/$MOUNTPOINT" >&2
exit 1
fi
# mount and return status
mount -o "$MOUNTOPTIONS" -t "$HAL_PROP_VOLUME_FSTYPE" "$HAL_PROP_BLOCK_DEVICE" "$MOUNT_ROOT/$MOUNTPOINT" > /dev/null 2>&1
if [ $? -ne 0 ]; then
if [ -n "$MOUNTPOINT_CREATED" ]; then
rmdir "$MOUNT_ROOT/$MOUNTPOINT"
fi
echo "org.freedesktop.Hal.Device.Volume.MountFailed" >&2
echo "$MOUNT_ROOT/$MOUNTPOINT" >&2
exit 1
fi
exit 0
-------------- next part --------------
#!/bin/sh -e
# Copyright (C) 2005, Kay Sievers <kay.sievers at vrfy.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2.
# Check for environment variables
if [ "$HAL_PROP_BLOCK_DEVICE" == "" ] || [ "$HAL_PROP_INFO_UDI" == "" ] ; then
echo "Missing or empty environment variable(s)." >&2
echo "This script should be started by hald." >&2
exit 1
fi
if [ "$HAL_PROP_VOLUME_IS_MOUNTED" != "true" ]; then
echo "org.freedesktop.Hal.Device.Volume.NotMounted" >&2
echo "$HAL_PROP_VOLUME_MOUNT_POINT" >&2
exit 1
fi
umount "$HAL_PROP_VOLUME_MOUNT_POINT" > /dev/null 2>&1 || true
if [ $? -ne 0 ]; then
echo "org.freedesktop.Hal.Device.Volume.UnMountFailed" >&2
echo "$HAL_PROP_VOLUME_MOUNT_POINT" >&2
exit 1
fi
# remove directory only if HAL has created it
attr -q -g HAL_MOUNTPOINT "$HAL_PROP_VOLUME_MOUNT_POINT" > /dev/null 2>&1 || exit 0
rmdir --ignore-fail-on-non-empty "$HAL_PROP_VOLUME_MOUNT_POINT"
exit 0
-------------- next part --------------
#!/bin/sh
# Copyright (C) 2005, Kay Sievers <kay.sievers at vrfy.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2.
#
# Check for environment variables
if [ "$HAL_PROP_BLOCK_DEVICE" == "" ] || [ "$HAL_PROP_INFO_UDI" == "" ] ; then
echo "Missing or empty environment variable(s)." >&2
echo "This script should be started by hald." >&2
exit 1
fi
eject "$HAL_PROP_BLOCK_DEVICE" > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "org.freedesktop.Hal.Device.Volume.EjectFailed" >&2
echo "$HAL_PROP_BLOCK_DEVICE" >&2
exit 1
fi
exit 0
More information about the hal
mailing list