16736b2052e02a56b0a1954ad5298ca41edad438
[enigma2.git] / lib / python / Components / Harddisk.py
1 from os import system, listdir, statvfs, popen, makedirs
2
3 from Tools.Directories import SCOPE_HDD, resolveFilename
4 from Tools.CList import CList
5
6 def tryOpen(filename):
7         try:
8                 procFile = open(filename)
9         except IOError:
10                 return ""
11         return procFile
12
13 def num2prochdx(num):
14         return "/proc/ide/hd" + ("a","b","c","d","e","f","g","h","i")[num] + "/"
15
16 class Harddisk:
17         def __init__(self, index):
18                 self.index = index
19
20                 host = (self.index & 2) >> 1
21                 bus = 0
22                 target = (self.index & 1)
23
24                 self.prochdx = num2prochdx(index)
25                 self.devidex = "/dev/ide/host%d/bus%d/target%d/lun0/" % (host, bus, target)
26
27         def getIndex(self):
28                 return self.index
29
30         def bus(self):
31                 ret = ""
32
33                 if self.index & 2:
34                         ret = "External (CF) - "
35                 else:
36                         ret = "Internal - "
37                 
38                 if self.index & 1:
39                         return ret + "Slave"
40                 else:
41                         return ret + "Master"
42
43         def capacity(self):
44                 procfile = tryOpen(self.prochdx + "capacity")
45                 
46                 if procfile == "":
47                         return ""
48
49                 line = procfile.readline()
50                 procfile.close()
51                 
52                 try:
53                         cap = int(line)
54                 except:
55                         return ""
56                 
57                 cap = cap / 1000 * 512 / 1000
58                 
59                 return "%d.%03d GB" % (cap/1024, cap%1024)
60                                                                 
61         def model(self):
62                 procfile = tryOpen(self.prochdx + "model")
63
64                 if procfile == "":
65                         return ""
66
67                 line = procfile.readline()
68                 procfile.close()
69
70                 return line.strip()
71
72         def free(self):
73                 procfile = tryOpen("/proc/mounts")
74                 
75                 if procfile == "":
76                         return -1
77
78                 free = -1
79                 while 1:
80                         line = procfile.readline()
81                         if line == "":
82                                 break
83                         if line.startswith(self.devidex):
84                                 parts = line.strip().split(" ")
85                                 try:
86                                         stat = statvfs(parts[1])
87                                 except OSError:
88                                         continue
89                                 free = stat.f_bfree/1000 * stat.f_bsize/1000
90                                 break
91                 procfile.close()
92                 return free             
93
94         def numPartitions(self):
95                 try:
96                         idedir = listdir(self.devidex)
97                 except OSError:
98                         return -1
99                 numPart = -1
100                 for filename in idedir:
101                         if filename.startswith("disc"):
102                                 numPart += 1
103                         if filename.startswith("part"):
104                                 numPart += 1
105                 return numPart
106
107         def unmount(self):
108                 cmd = "/bin/umount " + self.devidex + "part*"
109                 res = system(cmd)
110                 return (res >> 8)
111
112         def createPartition(self):
113                 cmd = "/sbin/sfdisk -f " + self.devidex + "disc"
114                 sfdisk = popen(cmd, "w")
115                 sfdisk.write("0,\n;\n;\n;\ny\n")
116                 sfdisk.close()
117                 return 0
118
119         def mkfs(self):
120                 cmd = "/sbin/mkfs.ext3 -T largefile -m0 " + self.devidex + "part1"
121                 res = system(cmd)
122                 return (res >> 8)
123
124         def mount(self):
125                 cmd = "/bin/mount -t ext3 " + self.devidex + "part1"
126                 res = system(cmd)
127                 return (res >> 8)
128
129         def createMovieFolder(self):
130                 try:
131                         makedirs(resolveFilename(SCOPE_HDD))
132                 except OSError:
133                         return -1
134                 return 0
135
136         errorList = [ _("Everything is fine"), _("Creating partition failed"), _("Mkfs failed"), _("Mount failed"), _("Create movie folder failed"), _("Unmount failed")]
137
138         def initialize(self):
139                 self.unmount()
140
141                 if self.createPartition() != 0:
142                         return -1
143
144                 if self.mkfs() != 0:
145                         return -2
146
147                 if self.mount() != 0:
148                         return -3
149
150                 #only create a movie folder on the internal hdd
151                 if not self.index & 2 and self.createMovieFolder() != 0:
152                         return -4
153                 
154                 return 0
155                 
156 def existHDD(num):
157         mediafile = tryOpen(num2prochdx(num) + "media")
158
159         if mediafile == "":
160                 return -1
161
162         line = mediafile.readline()
163         mediafile.close()
164         
165         if line.startswith("disk"):
166                 return 1
167         
168         return -1
169
170 class Partition:
171         def __init__(self, mountpoint, description = "", force_mounted = False):
172                 self.mountpoint = mountpoint
173                 self.description = description
174                 self.force_mounted = force_mounted
175
176         def stat(self):
177                 return statvfs(self.mountpoint)
178
179         def free(self):
180                 try:
181                         s = self.stat()
182                         return s.f_bavail * s.f_bsize
183                 except OSError:
184                         return None
185         
186         def total(self):
187                 try:
188                         s = self.stat()
189                         return s.f_blocks * s.f_bsize
190                 except OSError:
191                         return None
192
193         def mounted(self):
194                 # THANK YOU PYTHON FOR STRIPPING AWAY f_fsid.
195                 # TODO: can os.path.ismount be used?
196                 if self.force_mounted:
197                         return True
198                 procfile = tryOpen("/proc/mounts")
199                 for n in procfile.readlines():
200                         if n.split(' ')[1] == self.mountpoint:
201                                 return True
202                 return False
203
204 class HarddiskManager:
205         def __init__(self):
206                 hddNum = 0
207                 self.hdd = [ ]
208                 
209                 self.partitions = [ ]
210                 
211                 self.on_partition_list_change = CList()
212                 
213                 for hddNum in range(8):
214                         if existHDD(hddNum):
215                                 hdd = Harddisk(hddNum)
216                                 self.hdd.append(hdd)
217
218                 # currently, this is just an enumeration of what's possible,
219                 # this probably has to be changed to support automount stuff.
220                 # still, if stuff is mounted into the correct mountpoints by
221                 # external tools, everything is fine (until somebody inserts 
222                 # a second usb stick.)
223                 p = [
224                                         ("/media/hdd", _("Harddisk")), 
225                                         ("/media/card", _("Card")), 
226                                         ("/media/cf", _("Compact Flash")),
227                                         ("/media/mmc1", _("MMC Card")),
228                                         ("/media/net", _("Network Mount")),
229                                         ("/media/ram", _("Ram Disk")),
230                                         ("/media/usb", _("USB Stick")),
231                                         ("/", _("Internal Flash"))
232                                 ]
233                 
234                 for x in p:
235                         self.partitions.append(Partition(mountpoint = x[0], description = x[1]))
236
237         def getAutofsMountpoint(self, device):
238                 return "/autofs/%s/" % (device)
239
240         def addHotplugPartition(self, device, description):
241                 p = Partition(mountpoint = self.getAutofsMountpoint(device), description = description, force_mounted = True)
242                 self.partitions.append(p)
243                 self.on_partition_list_change("add", p)
244
245         def removeHotplugPartition(self, device):
246                 mountpoint = self.getAutofsMountpoint(device)
247                 for x in self.partitions[:]:
248                         if x.mountpoint == mountpoint:
249                                 self.partitions.remove(x)
250                                 self.on_partition_list_change("remove", x)
251
252         def HDDCount(self):
253                 return len(self.hdd)
254
255         def HDDList(self):
256                 list = [ ]
257                 for hd in self.hdd:
258                         hdd = hd.model() + " (" 
259                         hdd += hd.bus()
260                         cap = hd.capacity()     
261                         if cap != "":
262                                 hdd += ", " + cap
263                         hdd += ")"
264                         list.append((hdd, hd))
265
266                 return list
267
268         def getMountedPartitions(self):
269                 return [x for x in self.partitions if x.mounted()]
270
271 harddiskmanager = HarddiskManager()