Source

udiskie / udiskie / umount.py

Full commit
"""
Udiskie unmount utilities.
"""
__all__ = [
    'unmount_device', 'lock_device', 'remove_device', 'lock_slave',
    'unmount', 'unmount_all']

import logging
import dbus

import udiskie.device

def unmount_device(device):
    """
    Unmount a Device.

    Checks to make sure the device is unmountable and then unmounts.
    Return value indicates whether an action was performed successfully.
    The special value `None` means unknown/unreliable.

    """
    logger = logging.getLogger('udiskie.umount.unmount_device')
    if not device.is_handleable or not device.is_filesystem:
        logger.debug('skipping unhandled device %s' % (device,))
        return False
    if not device.is_mounted:
        logger.debug('skipping unmounted device %s' % (device,))
        return False
    try:
        device.unmount()
        logger.info('unmounted device %s' % (device,))
    except dbus.exceptions.DBusException, dbus_err:
        logger.error('failed to unmount device %s: %s' % (device,
                                                            dbus_err))
        return None
    return True

def lock_device(device):
    """
    Lock device.

    Checks to make sure the device is lockable, then locks.
    Return value indicates whether an action was performed successfully.
    The special value `None` means unknown/unreliable.

    """
    logger = logging.getLogger('udiskie.umount.lock_device')
    if not device.is_handleable or not device.is_crypto:
        logger.debug('skipping unhandled device %s' % (device,))
        return False
    if not device.is_unlocked:
        logger.debug('skipping locked device %s' % (device,))
        return False
    try:
        device.lock([])
        logger.info('locked device %s' % (device,))
    except dbus.exceptions.DBusException, dbus_err:
        logger.error('failed to lock device %s: %s' % (device, dbus_err))
        return None
    return True

def remove_device(device):
    """Unmount or lock the device depending on device type."""
    logger = logging.getLogger('udiskie.umount.remove_device')
    if not device.is_handleable:
        logger.debug('skipping unhandled device %s' % (device,))
        return False
    if device.is_filesystem:
        return unmount_device(device)
    elif device.is_crypto:
        return lock_device(device)

def lock_slave(device):
    """
    Lock the luks slave of this device.

    Will not lock the slave if it is still used by any mounted file system.
    Return value indicates success.

    """
    logger = logging.getLogger('udiskie.umount.lock_slave')
    if not device.is_luks_cleartext:
        logger.debug('skipping non-luks-cleartext device %s' % (device,))
        return False
    slave_path = device.luks_cleartext_slave
    slave = udiskie.device.Device(device.bus, slave_path)
    if slave.is_luks_cleartext_slave:
        return False
    return lock_device(slave)


def unmount(path):
    """Unmount or lock a filesystem

    The filesystem must match the criteria for a filesystem mountable by
    udiskie.  path is either the physical device node (e.g. /dev/sdb1) or the
    mount point (e.g. /media/Foo)."""

    logger = logging.getLogger('udiskie.umount.unmount')
    bus = dbus.SystemBus()

    device = udiskie.device.get_device(bus, path)
    if device:
        logger.debug('found device owning "%s": "%s"' % (path, device))
        if remove_device(device):
            return device
    return None


def unmount_all():
    """Unmount all filesystems handleable by udiskie."""
    unmounted = []
    bus = dbus.SystemBus()
    for device in udiskie.device.get_all(bus):
        if unmount_device(device):
            unmounted.append(device)
    return unmounted