diff --git a/src/calibre/devices/udisks.py b/src/calibre/devices/udisks.py new file mode 100644 index 0000000000..ba26c2b56c --- /dev/null +++ b/src/calibre/devices/udisks.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import dbus +import os + +def node_mountpoint(node): + + def de_mangle(raw): + return raw.replace('\\040', ' ').replace('\\011', '\t').replace('\\012', + '\n').replace('\\0134', '\\') + + for line in open('/proc/mounts').readlines(): + line = line.split() + if line[0] == node: + return de_mangle(line[1]) + return None + + +class UDisks(object): + + def __init__(self): + if os.environ.get('CALIBRE_DISABLE_UDISKS', False): + raise Exception('User has aborted use of UDISKS') + self.bus = dbus.SystemBus() + self.main = dbus.Interface(self.bus.get_object('org.freedesktop.UDisks', + '/org/freedesktop/UDisks'), 'org.freedesktop.UDisks') + + def device(self, device_node_path): + devpath = self.main.FindDeviceByDeviceFile(device_node_path) + return dbus.Interface(self.bus.get_object('org.freedesktop.UDisks', + devpath), 'org.freedesktop.UDisks.Device') + + def mount(self, device_node_path): + d = self.device(device_node_path) + try: + return unicode(d.FilesystemMount('', + ['auth_no_user_interaction', 'rw', 'noexec', 'nosuid', + 'sync', 'nodev', 'uid=1000', 'gid=1000'])) + except: + # May be already mounted, check + mp = node_mountpoint(str(device_node_path)) + if mp is None: + raise + return mp + + def unmount(self, device_node_path): + d = self.device(device_node_path) + d.FilesystemUnmount(['force']) + + def eject(self, device_node_path): + parent = device_node_path + while parent[-1] in '0123456789': + parent = parent[:-1] + devices = [str(x) for x in self.main.EnumerateDeviceFiles()] + for d in devices: + if d.startswith(parent) and d != parent: + try: + self.unmount(d) + except: + import traceback + print 'Failed to unmount:', d + traceback.print_exc() + d = self.device(parent) + d.DriveEject([]) + +def mount(node_path): + u = UDisks() + u.mount(node_path) + +def eject(node_path): + u = UDisks() + u.eject(node_path) + +if __name__ == '__main__': + import sys + dev = sys.argv[1] + print 'Testing with node', dev + u = UDisks() + print 'Mounted at:', u.mount(dev) + print 'Ejecting' + u.eject(dev) + + diff --git a/src/calibre/devices/usbms/device.py b/src/calibre/devices/usbms/device.py index 6fcfb9e7f0..6f938cbcbd 100644 --- a/src/calibre/devices/usbms/device.py +++ b/src/calibre/devices/usbms/device.py @@ -530,16 +530,8 @@ class Device(DeviceConfig, DevicePlugin): return drives def node_mountpoint(self, node): - - def de_mangle(raw): - return raw.replace('\\040', ' ').replace('\\011', '\t').replace('\\012', - '\n').replace('\\0134', '\\') - - for line in open('/proc/mounts').readlines(): - line = line.split() - if line[0] == node: - return de_mangle(line[1]) - return None + from calibre.devices.udisks import node_mountpoint + return node_mountpoint(node) def find_largest_partition(self, path): node = path.split('/')[-1] @@ -585,6 +577,13 @@ class Device(DeviceConfig, DevicePlugin): label += ' (%d)'%extra def do_mount(node, label): + try: + from calibre.devices.udisks import mount + mount(node) + return 0 + except: + pass + cmd = 'calibre-mount-helper' if getattr(sys, 'frozen_path', False): cmd = os.path.join(sys.frozen_path, cmd) @@ -617,6 +616,7 @@ class Device(DeviceConfig, DevicePlugin): if not mp.endswith('/'): mp += '/' self._linux_mount_map[main] = mp self._main_prefix = mp + self._linux_main_device_node = main cards = [(carda, '_card_a_prefix', 'carda'), (cardb, '_card_b_prefix', 'cardb')] for card, prefix, typ in cards: @@ -732,6 +732,11 @@ class Device(DeviceConfig, DevicePlugin): pass def eject_linux(self): + try: + from calibre.devices.udisks import eject + return eject(self._linux_main_device_node) + except: + pass drives = self.find_device_nodes() for drive in drives: if drive: diff --git a/src/calibre/manual/customize.rst b/src/calibre/manual/customize.rst index c35defc0b0..e0f799f572 100644 --- a/src/calibre/manual/customize.rst +++ b/src/calibre/manual/customize.rst @@ -24,6 +24,7 @@ Environment variables * ``CALIBRE_OVERRIDE_DATABASE_PATH`` - allows you to specify the full path to metadata.db. Using this variable you can have metadata.db be in a location other than the library folder. Useful if your library folder is on a networked drive that does not support file locking. * ``CALIBRE_DEVELOP_FROM`` - Used to run from a calibre development environment. See :ref:`develop`. * ``CALIBRE_OVERRIDE_LANG`` - Used to force the language used by the interface (ISO 639 language code) + * ``CALIBRE_DISABLE_UDISKS`` - Used to disable the use of udisks for mounting/ejecting. Set it to 1 to use calibre-mount-helper instead. * ``SYSFS_PATH`` - Use if sysfs is mounted somewhere other than /sys * ``http_proxy`` - Used on linux to specify an HTTP proxy