chiark / gitweb /
Add proper copyright statements.
[cura.git] / Cura / util / removableStorage.py
1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
2 import platform
3 import string
4 import glob
5 import os
6 import stat
7 import time
8 import subprocess
9 try:
10         from xml.etree import cElementTree as ElementTree
11 except:
12         from xml.etree import ElementTree
13
14 _removeableCache = None
15 _removeableCacheTime = None
16
17 def _parseStupidPListXML(e):
18         if e.tag == 'plist':
19                 return _parseStupidPListXML(list(e)[0])
20         if e.tag == 'array':
21                 ret = []
22                 for c in list(e):
23                         ret.append(_parseStupidPListXML(c))
24                 return ret
25         if e.tag == 'dict':
26                 ret = {}
27                 key = None
28                 for c in list(e):
29                         if c.tag == 'key':
30                                 key = c.text
31                         elif key is not None:
32                                 ret[key] = _parseStupidPListXML(c)
33                                 key = None
34                 return ret
35         if e.tag == 'true':
36                 return True
37         if e.tag == 'false':
38                 return False
39         return e.text
40
41 def _findInTree(t, n):
42         ret = []
43         if type(t) is dict:
44                 if '_name' in t and t['_name'] == n:
45                         ret.append(t)
46                 for k, v in t.items():
47                         ret += _findInTree(v, n)
48         if type(t) is list:
49                 for v in t:
50                         ret += _findInTree(v, n)
51         return ret
52
53 def getPossibleSDcardDrives():
54         global _removeableCache, _removeableCacheTime
55         if _removeableCache is not None and time.time() - _removeableCacheTime < 5.0:
56                 return _removeableCache
57
58         drives = []
59         if platform.system() == "Windows":
60                 from ctypes import windll
61                 import ctypes
62                 bitmask = windll.kernel32.GetLogicalDrives()
63                 for letter in string.uppercase:
64                         if bitmask & 1 and windll.kernel32.GetDriveTypeA(letter + ':/') == 2:
65                                 volumeName = ''
66                                 nameBuffer = ctypes.create_unicode_buffer(1024)
67                                 if windll.kernel32.GetVolumeInformationW(ctypes.c_wchar_p(letter + ':/'), nameBuffer, ctypes.sizeof(nameBuffer), None, None, None, None, 0) == 0:
68                                         volumeName = nameBuffer.value
69                                 if volumeName == '':
70                                         volumeName = 'NO NAME'
71
72                                 freeBytes = ctypes.c_longlong(0)
73                                 if windll.kernel32.GetDiskFreeSpaceExA(letter + ':/', ctypes.byref(freeBytes), None, None) == 0:
74                                         continue
75                                 if freeBytes.value < 1:
76                                         continue
77                                 drives.append(('%s (%s:)' % (volumeName, letter), letter + ':/', volumeName))
78                         bitmask >>= 1
79         elif platform.system() == "Darwin":
80                 p = subprocess.Popen(['system_profiler', 'SPUSBDataType', '-xml'], stdout=subprocess.PIPE)
81                 xml = ElementTree.fromstring(p.communicate()[0])
82                 p.wait()
83
84                 xml = _parseStupidPListXML(xml)
85                 for dev in _findInTree(xml, 'Mass Storage Device'):
86                         if 'removable_media' in dev and dev['removable_media'] == 'yes' and 'volumes' in dev and len(dev['volumes']) > 0:
87                                 for vol in dev['volumes']:
88                                         if 'mount_point' in vol:
89                                                 volume = vol['mount_point']
90                                                 drives.append((os.path.basename(volume), volume, os.path.basename(volume)))
91         else:
92                 for volume in glob.glob('/media/*'):
93                         drives.append((os.path.basename(volume), volume, os.path.basename(volume)))
94
95         _removeableCache = drives
96         _removeableCacheTime = time.time()
97         return drives
98
99 def ejectDrive(driveName):
100         if platform.system() == "Windows":
101                 cmd = '"%s" %s>NUL' % (os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'EjectMedia.exe')), driveName)
102         elif platform.system() == "Darwin":
103                 cmd = "diskutil eject '%s' > /dev/null 2>&1" % (driveName)
104         else:
105                 cmd = "umount '%s' > /dev/null 2>&1" % (driveName)
106         if os.system(cmd):
107                 return False
108         else:
109                 return True
110
111 if __name__ == '__main__':
112         print getPossibleSDcardDrives()