您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

81 行
3.0 KiB

  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)