om@2: #!/bin/env python om@2: # -*- coding: utf-8 -*- om@2: om@2: # ------------------------------------------------------------ om@2: # autoshadow.py om@2: # om@2: # Listen on DBus and mount any USB stick automatically om@2: # and invoke shadowfuse for it om@2: # om@2: # Autor: Oliver Maurhart, om@2: # om@2: # Copyright (C) 2013 AIT Austrian Institute of Technology om@2: # AIT Austrian Institute of Technology GmbH om@2: # Donau-City-Strasse 1 | 1220 Vienna | Austria om@2: # http://www.ait.ac.at om@2: # om@2: # This program is free software; you can redistribute it and/or om@2: # modify it under the terms of the GNU General Public License om@2: # as published by the Free Software Foundation version 2. om@2: # om@2: # This program is distributed in the hope that it will be useful, om@2: # but WITHOUT ANY WARRANTY; without even the implied warranty of om@2: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the om@2: # GNU General Public License for more details. om@2: # om@2: # You should have received a copy of the GNU General Public License om@2: # along with this program; if not, write to the Free Software om@2: # Foundation, Inc., 51 Franklin Street, Fifth Floor, om@2: # Boston, MA 02110-1301, USA. om@2: # ------------------------------------------------------------ om@2: om@2: om@2: # ------------------------------------------------------------ om@2: # imports om@2: om@2: import argparse om@2: import dbus om@2: import dbus.glib om@2: import dbus.service om@2: import gobject om@2: import sys om@2: om@2: om@2: # ------------------------------------------------------------ om@2: # const om@2: om@2: om@2: __version__ = "0.1" om@2: om@2: om@2: # ------------------------------------------------------------ om@2: # code om@2: om@2: om@2: class AutoShadowService(dbus.service.Object): om@2: om@2: """The AutoShadowService is the DBus object which listens on UDisk2 events and decides to mount and shadow a device. om@2: om@2: This class incorporates a DBus service (at.ac.ait.opensecurity.AutoShadow) and binds om@2: itself to the /AutoShadow object. om@2: """ om@2: om@2: def __init__(self): om@2: om@2: bus = dbus.SystemBus() om@2: bus_name = dbus.service.BusName('at.ac.ait.opensecurity.AutoShadow', bus) om@2: dbus.service.Object.__init__(self, bus_name, '/AutoShadow') om@2: om@2: # get the UDisk2 system object om@2: try: om@2: udisk2 = bus.get_object('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2') om@2: except: om@2: sys.stderr.write('Failed to aquire DBus Service org.freedesktop.UDisks2 object /org/freedesktop/UDisks2 on system DBus.\n') om@2: sys.exit(1) om@2: om@2: # connect our signal om@2: udisk2.connect_to_signal('InterfacesAdded', self.interface_added, sender_keyword='sender') om@2: om@2: om@2: def interface_added(*args, **kwargs): om@2: om@2: """Entry point for signal for new interfaces""" om@2: om@2: # a new interface has been added om@2: object_path = args[1] om@2: interfaces_and_properties = args[2] om@2: interface_keys = interfaces_and_properties.keys() om@2: om@2: if (interface_keys[0] == 'org.freedesktop.UDisks2.Drive'): om@2: om@2: # added a new drive om@2: drive_values = interfaces_and_properties[interface_keys[0]] om@2: drive_id = str(drive_values['Id']) om@2: drive_vendor = str(drive_values['Vendor']) om@2: drive_removeable = bool(drive_values['Removable']) om@2: print('detected new drive: id=\'{0}\' vendor=\'{1}\' removeable={2}'.format(drive_id, drive_vendor, drive_removeable)) om@2: om@2: if (interface_keys[0] == 'org.freedesktop.UDisks2.Block'): om@2: om@2: # added a new device - filesystem? om@2: if ('org.freedesktop.UDisks2.Filesystem' in interface_keys): om@2: om@2: # pick values of the device om@2: device_values = interfaces_and_properties[interface_keys[0]] om@2: device_path = bytearray(device_values['Device'][0:-1]).decode('latin-1') om@2: print('detected new device: path=\'{0}\''.format(device_path)) om@2: enforce_mount('/org/freedesktop/UDisks2/block_devices/' + device_path.split('/')[-1]) om@2: om@2: om@2: def listen(self): om@2: """Start listening on DBus""" om@2: self.loop = gobject.MainLoop() om@2: self.loop.run() om@2: om@2: om@2: @dbus.service.method('at.ac.ait.opensecurity.AutoShadow') om@2: def Quit(self): om@2: """Terminate this service""" om@2: self.loop.quit() om@2: om@2: om@2: @dbus.service.method('at.ac.ait.opensecurity.AutoShadow', out_signature='s') om@2: def Version(self): om@2: """Give a version string""" om@2: return __version__ om@2: om@2: om@2: def enforce_mount(udisk_object): om@2: om@2: """This function does the real mounting of drives. om@2: It also enforces the MirrorFuse on these mounts. om@2: """ om@2: om@2: print("ENFORCING mount of " + udisk_object) om@2: om@2: om@2: def main(): om@2: om@2: # parse command line om@2: parser = argparse.ArgumentParser(description = 'Automount USB storage devices and invoke shadowfuse for it.') om@2: args = parser.parse_args() om@2: om@2: # setup DBus event loop om@2: autoshadow_service = AutoShadowService() om@2: autoshadow_service.listen() om@2: om@2: om@2: # start om@2: if __name__ == "__main__": om@2: main() om@2: om@2: