Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
corpnewt
GitHub Repository: corpnewt/gibMacOS
Path: blob/master/Scripts/diskwin.py
175 views
1
import subprocess, plistlib, sys, os, time, json, csv
2
sys.path.append(os.path.abspath(os.path.dirname(os.path.realpath(__file__))))
3
from Scripts import run
4
5
class Disk:
6
7
def __init__(self):
8
self.r = run.Run()
9
self.wmic = self._get_wmic()
10
if self.wmic and not os.path.exists(self.wmic):
11
self.wmic = None
12
self.disks = {}
13
self._update_disks()
14
15
def _get_wmic(self):
16
# Attempt to locate WMIC.exe
17
wmic_list = self.r.run({"args":["where","wmic"]})[0].replace("\r","").split("\n")
18
if wmic_list:
19
return wmic_list[0]
20
return None
21
22
def update(self):
23
self._update_disks()
24
25
def _update_disks(self):
26
self.disks = self.get_disks()
27
28
def _get_rows(self, row_list):
29
rows = []
30
last_row = []
31
for row in row_list:
32
if not row.strip(): # Empty
33
if last_row: # Got a row at least - append it and reset
34
rows.append(last_row)
35
last_row = []
36
continue # Skip anything else
37
# Not an empty row - let's try to get the info
38
try: last_row.append(" : ".join(row.split(" : ")[1:]))
39
except: pass
40
return rows
41
42
def _get_diskdrive(self):
43
disks = []
44
if self.wmic: # Use WMIC where possible
45
try:
46
wmic = self.r.run({"args":[self.wmic, "DiskDrive", "get", "DeviceID,Index,Model,Partitions,Size", "/format:csv"]})[0]
47
# Get the rows - but skip the first 2 (empty, headers) and the last 1 (empty again)
48
disks = list(csv.reader(wmic.replace("\r","").split("\n"), delimiter=","))[2:-1]
49
# We need to skip the Node value for each row as well
50
disks = [x[1:] for x in disks]
51
except:
52
pass
53
if not disks: # Use PowerShell and parse the info manually
54
try:
55
ps = self.r.run({"args":["powershell", "-c", "Get-WmiObject -Class Win32_DiskDrive | Format-List -Property DeviceID,Index,Model,Partitions,Size"]})[0]
56
# We need to iterate the rows and add each column manually
57
disks = self._get_rows(ps.replace("\r","").split("\n"))
58
except:
59
pass
60
return disks
61
62
def _get_ldtop(self):
63
disks = []
64
if self.wmic: # Use WMIC where possible
65
try:
66
wmic = self.r.run({"args":[self.wmic, "path", "Win32_LogicalDiskToPartition", "get", "Antecedent,Dependent"]})[0]
67
# Get the rows - but skip the first and last as they're empty
68
disks = wmic.replace("\r","").split("\n")[1:-1]
69
except:
70
pass
71
if not disks: # Use PowerShell and parse the info manually
72
try:
73
ps = self.r.run({"args":["powershell", "-c", "Get-WmiObject -Class Win32_LogicalDiskToPartition | Format-List -Property Antecedent,Dependent"]})[0]
74
# We need to iterate the rows and add each column manually
75
disks = self._get_rows(ps.replace("\r","").split("\n"))
76
# We need to join the values with 2 spaces to match the WMIC output
77
disks = [" ".join(x) for x in disks]
78
except:
79
pass
80
return disks
81
82
def _get_logicaldisk(self):
83
disks = []
84
if self.wmic: # Use WMIC where possible
85
try:
86
wmic = self.r.run({"args":[self.wmic, "LogicalDisk", "get", "DeviceID,DriveType,FileSystem,Size,VolumeName", "/format:csv"]})[0]
87
# Get the rows - but skip the first 2 (empty, headers) and the last 1 (empty again)
88
disks = list(csv.reader(wmic.replace("\r","").split("\n"), delimiter=","))[2:-1]
89
# We need to skip the Node value for each row as well
90
disks = [x[1:] for x in disks]
91
except:
92
pass
93
if not disks: # Use PowerShell and parse the info manually
94
try:
95
ps = self.r.run({"args":["powershell", "-c", "Get-WmiObject -Class Win32_LogicalDisk | Format-List -Property DeviceID,DriveType,FileSystem,Size,VolumeName"]})[0]
96
# We need to iterate the rows and add each column manually
97
disks = self._get_rows(ps.replace("\r","").split("\n"))
98
except:
99
pass
100
return disks
101
102
def get_disks(self):
103
# We hate windows... all of us.
104
#
105
# This has to be done in 3 commands,
106
# 1. To get the PHYSICALDISK entries, index, and model
107
# 2. To get the drive letter, volume name, fs, and size
108
# 3. To get some connection between them...
109
#
110
# May you all forgive me...
111
112
disks = self._get_diskdrive()
113
p_disks = {}
114
for ds in disks:
115
if len(ds) < 5:
116
continue
117
p_disks[ds[1]] = {
118
"device":ds[0],
119
"model":" ".join(ds[2:-2]),
120
"type":0 # 0 = Unknown, 1 = No Root Dir, 2 = Removable, 3 = Local, 4 = Network, 5 = Disc, 6 = RAM disk
121
}
122
# More fault-tolerance with ints
123
p_disks[ds[1]]["index"] = int(ds[1]) if len(ds[1]) else -1
124
p_disks[ds[1]]["size"] = int(ds[-1]) if len(ds[-1]) else -1
125
p_disks[ds[1]]["partitioncount"] = int(ds[-2]) if len(ds[-2]) else 0
126
127
if not p_disks:
128
# Drat, nothing
129
return p_disks
130
# Let's find a way to map this biz now
131
ldtop = self._get_ldtop()
132
for l in ldtop:
133
l = l.lower()
134
d = p = mp = None
135
try:
136
dp = l.split("deviceid=")[1].split('"')[1]
137
mp = l.split("deviceid=")[-1].split('"')[1].upper()
138
d = dp.split("disk #")[1].split(",")[0]
139
p = dp.split("partition #")[1]
140
except:
141
pass
142
if any([d, p, mp]):
143
# Got *something*
144
if p_disks.get(d,None):
145
if not p_disks[d].get("partitions",None):
146
p_disks[d]["partitions"] = {}
147
p_disks[d]["partitions"][p] = {"letter":mp}
148
# Last attempt to do this - let's get the partition names!
149
parts = self._get_logicaldisk()
150
if not parts:
151
return p_disks
152
for ps in parts:
153
if len(ps) < 2:
154
# Need the drive letter and disk type at minimum
155
continue
156
# Organize!
157
plt = ps[0] # get letter
158
ptp = ps[1] # get disk type
159
# Initialize
160
pfs = pnm = None
161
psz = -1 # Set to -1 initially for indeterminate size
162
try:
163
pfs = ps[2] # get file system
164
psz = ps[3] # get size
165
pnm = ps[4] # get the rest in the name
166
except:
167
pass
168
for d in p_disks:
169
p_dict = p_disks[d]
170
for pr in p_dict.get("partitions",{}):
171
pr = p_dict["partitions"][pr]
172
if pr.get("letter","").upper() == plt.upper():
173
# Found it - set all attributes
174
pr["size"] = int(psz) if len(psz) else -1
175
pr["file system"] = pfs
176
pr["name"] = pnm
177
# Also need to set the parent drive's type
178
if len(ptp):
179
p_dict["type"] = int(ptp)
180
break
181
return p_disks
182
183