25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

usb_drive_mounter.py 3.0 KiB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. # Copyright 2015 Adafruit Industries.
  2. # Author: Tony DiCola
  3. # License: GNU GPLv2, see LICENSE.txt
  4. import glob
  5. import subprocess
  6. import time
  7. import pyudev
  8. class USBDriveMounter(object):
  9. """Service for automatically mounting attached USB drives."""
  10. def __init__(self, root='/mnt/usbdrive', readonly=False):
  11. """Create an instance of the USB drive mounter service. Root is an
  12. optional parameter which specifies the location and file name prefix for
  13. mounted drives (a number will be appended to each mounted drive file
  14. name). Readonly is a boolean that indicates if the drives should be
  15. mounted as read-only or not (default false, writable).
  16. """
  17. self._root = root
  18. self._readonly = readonly
  19. self._context = pyudev.Context()
  20. def remove_all(self):
  21. """Unmount and remove mount points for all mounted drives."""
  22. for path in glob.glob(self._root + '*'):
  23. subprocess.call(['umount', '-l', path])
  24. subprocess.call(['rm', '-r', path])
  25. def mount_all(self):
  26. """Mount all attached USB drives. Readonly is a boolean that specifies
  27. if the drives should be mounted read only (defaults to false).
  28. """
  29. self.remove_all()
  30. # Enumerate USB drive partitions by path like /dev/sda1, etc.
  31. nodes = [x.device_node for x in self._context.list_devices(subsystem='block',
  32. DEVTYPE='partition') \
  33. if 'ID_BUS' in x and x['ID_BUS'] == 'usb']
  34. # Mount each drive under the mount root.
  35. for i, node in enumerate(nodes):
  36. path = self._root + str(i)
  37. subprocess.call(['mkdir', path])
  38. args = ['mount']
  39. if self._readonly:
  40. args.append('-r')
  41. args.extend([node, path])
  42. subprocess.check_call(args)
  43. def start_monitor(self):
  44. """Initialize monitoring of USB drive changes."""
  45. self._monitor = pyudev.Monitor.from_netlink(self._context)
  46. self._monitor.filter_by('block', 'partition')
  47. self._monitor.start()
  48. def poll_changes(self):
  49. """Check for changes to USB drives. Returns true if there was a USB
  50. drive change, otherwise false.
  51. """
  52. # Look for a drive change.
  53. device = self._monitor.poll(0)
  54. # If a USB drive changed (added/remove) remount all drives.
  55. if device is not None and device['ID_BUS'] == 'usb':
  56. return True
  57. # Else nothing changed.
  58. return False
  59. if __name__ == '__main__':
  60. # Run as a service that mounts all USB drives as read-only under the default
  61. # path of /mnt/usbdrive*.
  62. drive_mounter = USBDriveMounter(readonly=True)
  63. drive_mounter.mount_all()
  64. drive_mounter.start_monitor()
  65. print 'Listening for USB drive changes (press Ctrl-C to quite)...'
  66. while True:
  67. if drive_mounter.poll_changes():
  68. print 'USB drives changed!'
  69. drive_mounter.mount_all()
  70. time.sleep(0)