86263641a921cca62fdb756a0d3fea7efb660dd0
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / DeviceManager / plugin.py
1 from Components.Label import Label
2 from Components.ActionMap import ActionMap
3 from Components.config import config, ConfigSelection, getConfigListEntry, ConfigSubsection, ConfigEnableDisable, ConfigYesNo, ConfigInteger
4 from Components.ConfigList import ConfigListScreen
5 from Components.Console import Console
6 from Components.GUIComponent import GUIComponent
7 from Components.Harddisk import harddiskmanager
8 from Components.MenuList import MenuList
9 from Components.Pixmap import Pixmap, MultiPixmap
10 from Components.Sources.List import List
11 from Components.Sources.StaticText import StaticText
12 from Plugins.Plugin import PluginDescriptor
13 from Screens.MessageBox import MessageBox
14 from Screens.Screen import Screen
15 from Screens.VirtualKeyBoard import VirtualKeyBoard
16 from Tools.BoundFunction import boundFunction
17 from Tools.LoadPixmap import LoadPixmap
18 from Tools.Notifications import AddNotificationWithCallback
19 from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN, SCOPE_METADIR
20 from skin import loadSkin
21 from os import system, makedirs, path, listdir, statvfs, popen
22 import os
23 import re
24 import time
25
26 from Components.Sources.StaticText import StaticText
27 from Components.FileList import FileList
28 from Screens.InputBox import InputBox
29 from Components.Input import Input
30 from Screens.ChoiceBox import ChoiceBox
31 from enigma import eTimer
32 from __init__ import _
33
34 config.plugins.devicemanager = ConfigSubsection()
35 config.plugins.devicemanager.hotplug_enable = ConfigEnableDisable(default=True)
36 config.plugins.devicemanager.mountcheck_enable = ConfigEnableDisable(default=True)
37
38 def readFile(filename):
39         file = open(filename)
40         data = file.read().strip()
41         file.close()
42         return data
43
44 def byteConversion(byte):
45         if type(byte) == str and len(byte) == 0:
46                 return ""
47         if type(byte) != long:
48                 byte = long(byte)
49         if byte > 1024*1024*1024:
50                 int_part = byte/1024/1024/1024
51                 dec_part = byte%(1024*1024*1024)/(1024*1024)
52                 return "%d.%d GB"%(int_part, dec_part)
53         else:
54                 int_part = byte/1024/1024
55                 dec_part = byte%(1024*1024)/1024
56                 return "%d.%d MB"%(int_part, dec_part)
57
58 def checkStrValue(value , empty = ""):
59         if type(value) != str or len(value) == 0:
60                 return empty
61         return value
62
63 class DeviceManagerConfiguration(Screen, ConfigListScreen):
64         def __init__(self,session):
65                 self.session = session
66                 Screen.__init__(self,session)
67                 self.skinName = "Setup"
68                 self.createConfigList()
69                 ConfigListScreen.__init__(self, self.list, session = self.session)
70                 self["key_red"] = StaticText(_("Cancel"))
71                 self["key_green"] = StaticText(_("OK"))
72                 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
73                 {
74                         "ok": self.keySave,
75                         "cancel": self.keyCancel,
76                         "red": self.keyCancel,
77                         "green": self.keySave,
78                 }, -2)
79                 self.onShown.append(self.setWindowTitle)
80                 self.old_hotplug_enable = config.plugins.devicemanager.hotplug_enable.value
81                 
82         def setWindowTitle(self):
83                 self.setTitle(_("DeviceManager configuration"))
84
85         def createConfigList(self):
86                 self.list = []
87                 self.list.append(getConfigListEntry(_("Enable mount check for HDD : "), config.plugins.devicemanager.mountcheck_enable))
88                 self.list.append(getConfigListEntry(_("Harddisk standby after : "), config.usage.hdd_standby))
89                 self.list.append(getConfigListEntry(_("Mount known devices automatically : "), config.plugins.devicemanager.hotplug_enable))
90
91         def keySave(self):
92                 if config.plugins.devicemanager.hotplug_enable.value:
93                         if not DeviceManagerhotplugDeviceStart in harddiskmanager.on_partition_list_change:
94                                 harddiskmanager.on_partition_list_change.append(DeviceManagerhotplugDeviceStart)
95                 else:
96                         if DeviceManagerhotplugDeviceStart in harddiskmanager.on_partition_list_change:
97                                 harddiskmanager.on_partition_list_change.remove(DeviceManagerhotplugDeviceStart)
98
99                 for x in self["config"].list:
100                         x[1].save()
101                 self.close()
102
103 class DeviceManager(Screen):
104         skin = """
105                 <screen position="center,center" size="670,400" title="DeviceManager">
106                         <ePixmap pixmap="skin_default/buttons/red.png" position="20,0" size="140,40" alphatest="on" />
107                         <ePixmap pixmap="skin_default/buttons/green.png" position="180,0" size="140,40" alphatest="on" />
108                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="340,0" size="140,40" alphatest="on" />
109                         <ePixmap pixmap="skin_default/buttons/blue.png" position="500,0" size="140,40" alphatest="on" />
110                         <widget name="key_red" position="20,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#9f1313" transparent="1" />
111                         <widget name="key_green" position="180,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#1f771f" transparent="1" />
112                         <widget name="key_yellow" position="340,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#a08500" transparent="1" />
113                         <widget name="key_blue" position="500,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#18188b" transparent="1" />
114                         <ePixmap pixmap="skin_default/div-h.png" position="0,48" size="670,2" alphatest="on" />
115                         <widget source="menu" render="Listbox" position="0,48" size="670,350" scrollbarMode="showOnDemand">
116                                 <convert type="TemplatedMultiContent">
117                                 {"templates":
118                                         {"default": (54,[
119                                                         MultiContentEntryText(pos = (100, 0), size = (560, 30), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 0), # index 0 is vendor  - model
120                                                         MultiContentEntryText(pos = (100, 32), size = (130, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1), # index 1 is Device
121                                                         MultiContentEntryText(pos = (230, 32), size = (130, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2), # index 2 is Size
122                                                         MultiContentEntryText(pos = (360, 32), size = (130, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 3), # index 3 is Partitions
123                                                         MultiContentEntryText(pos = (490, 32), size = (140, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 4), # index 4 is Removable
124                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 52), size = (670, 2), png = 5), # png 5 is the div pixmap
125                                                 ]),
126                                         "partitions": (98, [
127                                                         MultiContentEntryText(pos = (100, 0), size = (560, 30), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 0), # index 1 is Partition
128                                                         MultiContentEntryText(pos = (100, 32), size = (560, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1), # index 2 is Mounted on
129                                                         MultiContentEntryText(pos = (100, 54), size = (560, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2), # index 3 UUID
130                                                         MultiContentEntryText(pos = (100, 76), size = (140, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 3), # index 4 Type
131                                                         MultiContentEntryText(pos = (230, 76), size = (140, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 4), # index 5 Size_total
132                                                         MultiContentEntryText(pos = (380, 76), size = (200, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 5), # index 6 Size_free
133                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 96), size = (670, 2), png = 6), # png 6 is the div pixmap
134                                                 ]),
135                                         "mountpoint": (54,[
136                                                         MultiContentEntryPixmapAlphaTest(pos = (10, 7), size = (30, 30), png = 0), # index 0: picture
137                                                         MultiContentEntryText(pos = (40, 0), size = (500, 30), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1), # index 1 name
138                                                         MultiContentEntryText(pos = (40, 32), size = (500, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2), # index 2 path
139                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 52), size = (670, 2), png = 5), # index 5 is the div pixmap
140                                                 ])
141                                         },
142                                         "fonts": [gFont("Regular", 22),gFont("Regular", 16),gFont("Regular", 28)],
143                                         "itemHeight": 54
144                                 }
145                                 </convert>
146                         </widget>
147                 </screen>
148                 """
149
150         def __init__(self, session):
151                 Screen.__init__(self, session)
152                 self.session = session
153                 self.currList = "default"
154                 self.currDevice = None
155                 self.currPartition = None
156                 self.defaultMountPoint = "/media/hdd"
157                 self.deviceList = []
158                 self["menu"] = List(self.deviceList)
159                 self["key_red"] = Label(_("Close"))
160                 self["key_green"] = Label(" ")
161                 self["key_yellow"] = Label(" ")
162                 self["key_blue"] = Label(" ")
163
164                 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions", "MenuActions" ],
165                 {
166                         "ok": self.keyOk,
167                         "cancel": self.keyCancel,
168                         "red": self.keyCancel,
169                         "green": self.keyOk,
170                         "yellow": self.keyYellow,
171                         "blue": self.keyBlue,
172                         "menu": self.keyMenu,
173                 }, -2)
174                 self.DeviceManagerConsole = Console()
175                 self.loadIcon()
176                 if not self.selectionChanged in self["menu"].onSelectionChanged:
177                         self["menu"].onSelectionChanged.append(self.selectionChanged)
178                 self.onLayoutFinish.append(self.showDeviceList)
179                 self.onLayoutFinish.append(self.addPartitionListChange)
180                 self.onClose.append(self.removePartitionListChange)
181 #               self.onLayoutFinish.append(self.hotplugInactive)
182 #               self.onClose.append(self.hotplugActive)
183                 self.onChangedEntry = []
184                 self.blockDevices = {}
185
186         def addPartitionListChange(self):
187                 harddiskmanager.on_partition_list_change.append(self.partitionListChanged)
188
189         def removePartitionListChange(self):
190                 harddiskmanager.on_partition_list_change.remove(self.partitionListChanged)
191
192         def partitionListChanged(self, action, device):
193                 print "[Device manager] hotplug partitionListChanged"
194                 if self.currList != "default" and device.device[:3] != self.currDevice["blockdev"]:
195                         return
196                 self.showDeviceList()
197
198         def hotplugInactive(self):
199                 global devicemanagerhotplugactive
200                 print "[Device manager] hotplug Inctive"
201                 devicemanagerhotplugactive = False
202
203         def hotplugActive(self):
204                 global devicemanagerhotplugactive
205                 print "[Device manager] hotplug Active"
206                 devicemanagerhotplugactive = True
207
208         def loadIcon(self):
209                 self.icon_button_green = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/buttons/button_green.png"))
210                 self.divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
211
212         def selectionChanged(self):
213                 if self.currList == "partitions":
214                         currentPartition = self.getCurrentPartition()
215                         if currentPartition is not None:
216                                 if currentPartition["mountpoint"] != "":
217                                         self["key_green"].setText(_("Umount"))
218                                 else:
219                                         self["key_green"].setText(_("Mount"))
220
221                                 if currentPartition["fstype"] == "":
222                                         self["key_blue"].setText("")
223                                 elif currentPartition["fstype"][:3] == "ext":
224                                         self["key_blue"].setText(_("Check"))
225                                 else:
226                                         self["key_blue"].setText("")
227
228         def showDeviceList(self):
229                 self.deviceList = []
230                 self["key_red"].setText(_("Close"))
231                 self["key_green"].setText(_("Ok"))
232                 self["key_yellow"].setText(" ")
233                 self["key_blue"].setText(_("Initialize"))
234                 deviceinfo.refresh()
235                 for device in deviceinfo.getBlockDevices():
236                         deviceEntry = (
237                                 "%s - %s"%(device["vendor"], device["model"]), # vendor : str, model : str, index 0 
238                                 _("device : %s")%(device["blockdev"]), # str
239                                 _("Size : %s")%(byteConversion(device["size"])), # str, bytes
240                                 _("Partitions : %s")%(len(device["partitions"])), # list
241                                 _("Removable : %s")%(device["removable"] and 'Yes' or 'No'), # bool [True, False]
242                                 self.divpng, # png 5
243                                 device, # index 6
244                                 )
245 #                       print "[DeviceManager] deviceEntry : ", deviceEntry
246                         self.deviceList.append(deviceEntry)
247                 self.currList = "default"
248                 self["menu"].style = "default"
249                 self["menu"].setList(self.deviceList)
250
251         def showPartitionList(self):
252                 if self.currDevice is None:
253                         return
254                 partitionList = []
255                 for partition in self.currDevice["partitions"]:
256                         partitionInfo = deviceinfo.getPartitionInfo(partition)
257                         partitionEntry = (
258                                 _("Partition : /dev/%s")%partition, # index 0
259                                 _("Mounted on : %s")%checkStrValue(partitionInfo["mountpoint"], _("not mounted")),
260                                 _("UUID : %s")%checkStrValue(partitionInfo["uuid"], _("unknown")),
261                                 _("Type : %s")%checkStrValue(partitionInfo["fstype"], _("unknown")),
262                                 _("Size : %s")%checkStrValue(byteConversion(partitionInfo["size"]), _("unknown")),
263                                 _("Free : %s")%checkStrValue(byteConversion(partitionInfo["free"]), _("unknown")),
264                                 self.divpng, # index 6
265                                 partitionInfo, # index 7
266                         )
267 #                       print "[DeviceManager] partitionEntry : ",partitionEntry
268                         partitionList.append(partitionEntry)
269                 if len(partitionList) != 0:
270                         self["key_red"].setText(_("Devices"))
271                         self["key_green"].setText(_("Mount"))
272                         self["key_yellow"].setText(_("Format"))
273                         self["key_blue"].setText(_("Check"))
274                         self.currList = "partitions"
275                         self["menu"].style = "partitions"
276                         self["menu"].setList(partitionList)
277                         self.selectionChanged()
278                 else:
279                         self.session.open(MessageBox, _("No partition list found on device.\nPlease click BLUE key and do Initialize to use this device."), MessageBox.TYPE_ERROR, timeout = 10)
280
281
282         def showMountPointSetup(self):
283                 if self.currDevice is None or self.currPartition is None:
284                         return
285                 partition =  self.currPartition["partition"]
286                 if not os.access("/autofs/%s"%partition,0):
287                         self.session.open(MessageBox, _("This partition is not mountable.\nYou need to check or format this partition."), MessageBox.TYPE_ERROR, timeout = 10)
288                         return
289                 self["key_red"].setText(_("Partitions"))
290                 self["key_green"].setText(_("Ok"))
291                 self["key_yellow"].setText("")
292                 self["key_blue"].setText("")
293                 self.mountPointList = []
294                 currentMountPoint = self.currPartition["mountpoint"]
295                 if currentMountPoint == "":
296                         currentMountPoint = "'not mounted'"
297                 defaultMountPoint = self.getDefaultMountPoint()
298                 autoMountPoint = self.getAutoMountPoint()
299                 defaultMountPointEntry = (self.icon_button_green, _("Set up Default Mount Point"), _("Mount Point : %s ->%s")%(currentMountPoint, defaultMountPoint), "default", defaultMountPoint, self.divpng)
300                 autoMountPointEntry = (self.icon_button_green, _("Automatically set up a Mount Point"), _("Mount Point : %s -> %s")%(currentMountPoint, autoMountPoint), "auto", autoMountPoint, self.divpng)
301                 manuallyMountPointEntry = (self.icon_button_green, _("User manually Set up a Mount Point"), _("Mount Point : click ok button on here."), "manual", "", self.divpng)
302                 if not path.ismount(defaultMountPoint):
303                         self.mountPointList.append(defaultMountPointEntry)
304                 self.mountPointList.append(autoMountPointEntry)
305                 self.mountPointList.append(manuallyMountPointEntry)
306                 self.currList = "mountpoint"
307                 self["menu"].style = "mountpoint"
308                 self["menu"].setList(self.mountPointList)
309
310         def getCurrentDevice(self):
311                 if self.currList == "default":
312                         return self["menu"].getCurrent()[6]
313                 return None
314
315         def getCurrentPartition(self):
316                 if self.currList == "partitions":
317                         return self["menu"].getCurrent()[7]
318                 return None
319
320         def keyOk(self):
321 #               print "keyOk"
322                 if self.currList == "default":
323                         self.currDevice = self.getCurrentDevice()
324                         if len(self.currDevice["partitions"]) == 0:
325                                 self.session.open(MessageBox, _("No partition list found on device.\nPlease click BLUE key and do Initialize to use this device."), MessageBox.TYPE_ERROR, timeout = 10)
326                         else:
327                                 self.showPartitionList()
328                 elif self.currList == "partitions":
329                         currMountPoint = self.getCurrentPartition()["mountpoint"]
330                         currUuid = self.getCurrentPartition()["uuid"]
331                         if currMountPoint == "":
332                                 self.currPartition = self.getCurrentPartition()
333                                 self.showMountPointSetup()
334                         else:
335                                 self.doUmount(currMountPoint, self.showPartitionList)
336                 elif self.currList == "mountpoint":
337 # self["menu"].getCurrent() : (green_button, "menu description", "mount point description, "default", mountpoint, self.divpng)
338                         currEntry = self["menu"].getCurrent()[3]
339                         if currEntry == "default":
340 #                               print "Setup mountpoint default!"
341                                 self.doMount(self.currPartition, self["menu"].getCurrent()[4])
342                         elif currEntry == "auto":
343 #                               print "Setup mountpoint automatically!"
344                                 self.doMount(self.currPartition, self["menu"].getCurrent()[4])
345                         else:
346 #                               print "Setup mountpoint manually!"
347                                 self.session.openWithCallback(self.MountpointBrowserCB, MountpointBrowser)
348                 else:
349                         pass
350
351         def keyCancel(self):
352 #               print "keyCancel"
353                 if self.DeviceManagerConsole is not None:
354                         if len(self.DeviceManagerConsole.appContainers):
355                                 for name in self.DeviceManagerConsole.appContainers.keys():
356                                         self.DeviceManagerConsole.kill(name)
357                 if self.currList == "partitions":
358                         self.currDevice = None
359                         self.showDeviceList()
360                 elif self.currList == "mountpoint":
361                         self.currPartition = None
362                         self.showPartitionList()
363                 else: # currList = "default"
364                         self.close()
365
366         def keyYellow(self):
367                 if self.currList == "partitions":
368                         partition = self.getCurrentPartition()
369                         self.choiceBoxFstype()
370
371         def keyBlue(self):
372                 if self.currList == "default":
373                         device = self.getCurrentDevice()
374                         self.session.openWithCallback(self.deviceInitCB, DeviceInit, device["blockdev"], device["size"])
375                 elif self.currList == "partitions":
376                         partition = self.getCurrentPartition()
377                         self.session.openWithCallback(self.deviceCheckCB, DeviceCheck, partition)
378
379         def keyMenu(self):
380                 self.session.open(DeviceManagerConfiguration)
381
382         def deviceInitCB(self, ret = True):
383                 self.showDeviceList()
384
385         def deviceCheckCB(self, ret = True):
386                 self.showPartitionList()
387
388         def deviceFormatCB(self, ret = True):
389                 self.showPartitionList()
390
391         def choiceBoxFstype(self):
392                 menu = []
393                 menu.append((_("ext2 - recommended for USB flash memory"), "ext2"))
394                 menu.append((_("ext3 - recommended for harddisks"), "ext3"))
395                 menu.append((_("ext4 - experimental"), "ext4"))
396                 menu.append((_("vfat - for USB flash memory"), "vfat"))
397                 self.session.openWithCallback(self.choiceBoxFstypeCB, ChoiceBox, title=_("Choice filesystem."), list=menu)
398
399         def choiceBoxFstypeCB(self, choice):
400                 if choice is None:
401                         return
402                 else:
403                         partition = self.getCurrentPartition()
404                         self.session.openWithCallback(self.deviceFormatCB, DeviceFormat, partition, choice[1])
405
406 # about mount funcs..
407         def doUmount(self, mountpoint, callback):
408                 cmd = "umount %s"%mountpoint
409                 print "[DeviceManager] cmd : %s"%cmd
410                 self.DeviceManagerConsole.ePopen(cmd, self.doUmountFinished, (mountpoint, callback))
411
412         def doUmountFinished(self, result, retval, extra_args = None):
413                 (mountpoint, callback) = extra_args
414                 if retval == 0:
415 # update current mount state ,devicemanager.cfg
416                         devicemanagerconfig.updateConfigList()
417                 else:
418                         self.session.open(MessageBox, _("Can't umount %s. \nMaybe device or resource busy.")%mountpoint, MessageBox.TYPE_ERROR, timeout = 10)
419                 callback()
420
421         def getDefaultMountPoint(self):
422                 return self.defaultMountPoint
423
424         def getAutoMountPoint(self):
425                 mountPoint = "/media/"+self.currDevice["model"]
426                 mountPoint = mountPoint.replace(' ','-')
427                 if path.ismount(mountPoint):
428                         partnum = 2
429                         while 1:
430                                 mountPoint_fix = mountPoint+str(partnum)
431                                 if not path.ismount(mountPoint_fix):
432                                         break
433                                 partnum +=1
434                         mountPoint = mountPoint_fix
435                 return mountPoint
436
437         def doMount(self, partition, mountpoint):
438                 try:
439                         device = partition["partition"]
440                         fstype = partition["fstype"]
441                         if mountpoint.endswith("/"):
442                                 mountpoint = retval[:-1]
443                         if mountpoint.find(' ') != -1:
444                                 mountpoint = mountpoint.replace(' ','-')
445                         dev = deviceinfo.checkMountPoint(mountpoint)
446                         if dev is None:
447                                 if not path.exists(mountpoint):
448                                         print "[deviceManager] make dir %s"%mountpoint
449                                         makedirs(mountpoint)
450                                 if fstype == "ntfs":
451                                         cmd = "ntfs-3g /dev/%s %s" % (device, mountpoint)
452                                 else:
453                                         cmd = "mount /dev/%s %s" % (device, mountpoint)
454                                 os.system(cmd)
455                                 print "[DeviceManager] cmd : %s"%cmd
456                                 if mountpoint == "/media/hdd":
457                                         movieDir = mountpoint + "/movie"
458                                         if not pathExists(movieDir):
459                                                 print "[DeviceManager] make dir %s"%movieDir
460                                                 os.makedirs(movieDir)
461                                 self.showPartitionList()
462 # update current mount state ,devicemanager.cfg
463                                 devicemanagerconfig.updateConfigList()
464                         else:
465                                 self.session.open(MessageBox, _("Mount Failed!\nCurrent path is already mounted by \"%s\"")%dev, MessageBox.TYPE_ERROR, timeout = 10)
466                 except:
467                         self.session.open(MessageBox, _("Mount Failed!(%s -> %s)")%(device, mountpoint), MessageBox.TYPE_ERROR, timeout = 10)
468
469         def MountpointBrowserCB(self, retval = None):
470                 if retval and retval is not None:
471                         mountPoint = retval.strip().replace(' ','')
472                         if retval.endswith("/"):
473                                 mountPoint = retval[:-1]
474                         print "Mount point from MountpointBrowser : %s"%mountPoint
475                         if not path.exists(mountPoint):
476                                 self.session.open(MessageBox, _("Mount Point is not writeable.\nPath : %s")%mountPoint, MessageBox.TYPE_ERROR, timeout = 10)
477
478                         else:
479                                 self.doMount(self.currPartition, mountPoint)
480 # mount funcs end..
481
482 # Initializing Start...
483 class DeviceInit(Screen):
484         skin = """<screen position="0,0" size="0,0"/>"""
485         def __init__(self, session, device, devicesize):
486                 Screen.__init__(self, session)
487                 self.session = session
488                 self.deviceInitConsole = Console()
489                 self.device = device
490                 self.devicesize = int(devicesize)
491                 self.inputbox_partitions = 1
492                 self.inputbox_partitionSizeList = []
493                 self.inputbox_partitionSizeTotal = self.inputbox_partitionSizeRemain = int(self.devicesize/1024/1024)
494                 self.msgWaiting = None
495                 self.msgWaitingMkfs = None
496                 self.devicenumber = 0
497                 self.newpartitions = 0
498                 self.onLayoutFinish.append(self.timerStart)
499                 self.initStartTimer = eTimer()
500                 self.initStartTimer.callback.append(self.confirmMessage)
501                 self.createFSStartTimer = eTimer()
502                 self.createFSStartTimer.callback.append(self.createFilesystemStart)
503                 self.exitMessageTimer = eTimer()
504                 self.exitMessageTimer.callback.append(self.exitMessage)
505                 self.msg = ""
506
507         def timerStart(self):
508                 self.initStartTimer.start(100,True)
509
510         def confirmMessage(self):
511                 message = _("Do you really want to initialize the device?\nAll data on the device will be lost!")
512                 self.session.openWithCallback(self.confirmed, MessageBox, message)
513
514         def confirmed(self, ret):
515                 if ret:
516                         self.InitializeStart()
517                 else:
518                         self.exit()
519
520         def exit(self, ret = True):
521                 self.close()
522
523         def unmountAll(self, device):
524                 mounts = file('/proc/mounts').read().split('\n')
525                 cmd = ""
526 # umount all
527                 for line in mounts:
528                         if not line.startswith("/dev/" + device):
529                                 continue
530                         cmd += "umount %s ;"% line.split()[0]
531                         os.system(cmd)
532 #recheck if umounted
533                 mounts = file('/proc/mounts').read().split('\n')
534                 for line in mounts:
535                         if line.startswith("/dev/" + device):
536                                 return False
537                 return True
538
539         def InitializeStart(self):
540                 self.InputPartitionSize_step1()
541
542         def InputPartitionSize_step1(self):
543                 self.session.openWithCallback(self.InputPartitionSize_step1_CB, InputBox, title=_("How many partitions do you want?(1-4)"), text="1", maxSize=False, type=Input.NUMBER)
544
545         def InputPartitionSize_step1_CB(self, ret):
546                 if ret is not None and int(ret) in range(1,5): # ret in 1~4
547                         self.inputbox_partitions = int(ret)
548                         self.InputPartitionSize_step2()
549                 else:
550                         self.session.openWithCallback(self.exit, MessageBox, _("The number you entered is wrong!"), MessageBox.TYPE_ERROR, timeout = 10)
551
552         def InputPartitionSize_step2(self):
553                 current_partition = len(self.inputbox_partitionSizeList)+1
554                 if self.inputbox_partitionSizeRemain == 0:
555                         self.initInitializeConfirm()
556                 elif current_partition == self.inputbox_partitions:
557                         self.inputbox_partitionSizeList.append(str(self.inputbox_partitionSizeRemain))
558                         self.initInitializeConfirm()
559                 else:
560                         text = str(int(self.inputbox_partitionSizeRemain/(self.inputbox_partitions-len(self.inputbox_partitionSizeList) )))
561                         self.session.openWithCallback(self.InputPartitionSize_step2_CB, InputBox, title=_("Input size of partition %s.(Max = %d MB)")%(current_partition,self.inputbox_partitionSizeRemain ), text=text, maxSize=False, type=Input.NUMBER)
562
563         def InputPartitionSize_step2_CB(self, ret):
564                 if ret is not None:
565                         if self.inputbox_partitionSizeRemain < int(ret) or int(ret) == 0:
566                                 self.InputPartitionSize_step2()
567                         else:
568                                 self.inputbox_partitionSizeList.append(str(ret))
569                                 self.inputbox_partitionSizeRemain -= int(ret)
570                                 self.InputPartitionSize_step2()
571                 else:
572                         self.session.openWithCallback(self.exit ,MessageBox, _("The number you entered is wrong!"), MessageBox.TYPE_ERROR, timeout = 10)
573
574         def initInitializeConfirm(self):
575 #               print self.inputbox_partitionSizeList
576                 partitionsInfo = ""
577                 for index in range(len(self.inputbox_partitionSizeList)):
578                         print "partition %d : %s Bytes"%(index+1, str(self.inputbox_partitionSizeList[index]))
579                         partitionsInfo += "partition %d : %s MB\n"%(index+1, str(self.inputbox_partitionSizeList[index]))
580                 self.session.openWithCallback(self.initInitializeConfirmCB, MessageBoxConfirm, _("%s\nStart Device Inititlization?") % partitionsInfo , MessageBox.TYPE_YESNO)
581
582         def initInitializeConfirmCB(self,ret):
583                 if ret:
584                         self.initInitialize()
585                 else:
586                         self.exit()
587         
588         def initInitialize(self):
589                 if not self.unmountAll(self.device):
590                         self.session.openWithCallback(self.exit, MessageBox, _("umounting failed!Maybe some files in mount point are open"), MessageBox.TYPE_ERROR, timeout = 10)
591                 else:
592                         msg = _("InitInitializing, please wait ...")
593                         msg += _("\nDevice : %s")%self.device
594                         msg += _("\nSize : %s MB\n")%self.inputbox_partitionSizeTotal
595                         for index in range(len(self.inputbox_partitionSizeList)):
596                                 msg += _("\npartition %d : %s MB")%(index+1, str(self.inputbox_partitionSizeList[index]))
597                         self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
598                         set = ""
599                         partitions = len(self.inputbox_partitionSizeList)
600                         if partitions == 1:
601                                 cmd = 'printf "8,\n;0,0\n;0,0\n;0,0\ny\n" | sfdisk -f -uS /dev/' + self.device
602                         else:
603                                 for p in range(4):
604                                         if partitions > p+1:
605                                                 set += ",%s\n"%(self.inputbox_partitionSizeList[p])
606                                         else:
607                                                 set +=";\n"
608                                 set+="y\n"
609                                 cmd = 'printf "%s" | sfdisk -f -uM /dev/%s'%(set,self.device)
610                         self.deviceInitConsole.ePopen(cmd, self.initInitializeFinished)
611
612         def initInitializeFinished(self, result, retval, extra_args = None):
613                 if retval == 0:
614                         cmd = "sfdisk -R /dev/%s ; sleep 5" % (self.device)
615                         self.deviceInitConsole.ePopen(cmd, self.initInitializingRefreshFinished)
616                 else:
617                         errorMsg = "initInitializing device Error at /dev/%s"%self.device
618                         self.msgWaiting.run_close(False, errorMsg)
619
620         def initInitializingRefreshFinished(self, result, retval, extra_args = None):
621                 cmd = "/bin/umount /dev/%s*" % (self.device)
622                 self.deviceInitConsole.ePopen(cmd, self.initInitializingUmountFinished)
623
624         def initInitializingUmountFinished(self, result, retval, extra_args = None):
625                 partitions = open("/proc/partitions")
626                 self.devicenumber = 0
627                 self.newpartitions = 0
628                 for part in partitions:
629                         res = re.sub("\s+", " ", part).strip().split(" ")
630                         if res and len(res) == 4 and res[3][:3] == self.device:
631                                 if len(res[3]) > 3 and res[3][:2] == "sd":
632                                         self.newpartitions += 1
633                 partitions.close()
634                 self.msgWaiting.run_close(True)
635 #               self.createFilesystem(self.newpartitions)
636
637         def createFilesystem(self, newpartitions):
638                 self.devicenumber = self.devicenumber + 1
639                 fulldevicename = "/dev/" + self.device + str(self.devicenumber)
640                 shortdevicename = self.device + str(self.devicenumber)
641 # get partition size
642                 partitions = open("/proc/partitions")
643                 for part in partitions:
644                         res = re.sub("\s+", " ", part).strip().split(" ")
645                         if res and len(res) == 4:
646                                 if res[3] == shortdevicename:
647                                         partitionsize = int(res[2])
648                                         break
649                 partitions.close()
650
651                 if partitionsize > 64 * 1024 * 1024:
652                         cmd = "/sbin/mkfs.ext3 "
653                         filesystem = "ext3"
654                 else:
655                         cmd = "/sbin/mkfs.ext2 "
656                         filesystem = "ext2"
657                         
658                 if partitionsize > 2 * 1024 * 1024:
659                         cmd += "-T largefile "
660                 cmd += "-m0 " + fulldevicename
661
662                 msg = _("Create filesystem, please wait ...")
663                 msg += _("\nPartition : %s") % (fulldevicename)
664                 msg += _("\nFilesystem : %s") % (filesystem)
665                 msg += _("\nSize : %d MB\n")%int(self.inputbox_partitionSizeList[self.devicenumber-1])
666                 self.msgWaitingMkfs = self.session.openWithCallback(self.msgWaitingMkfsCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
667                 self.deviceInitConsole.ePopen(cmd, self.createFilesystemFinished, (self.device, fulldevicename))
668
669         def createFilesystemFinished(self, result, retval, extra_args = None):
670                 device = extra_args[0]
671                 fulldevicename = extra_args[1]
672                 if retval == 0:
673                         self.msgWaitingMkfs.run_close(True)
674                 else:
675                         errorMsg = _("Creating filesystem Error")
676                         if fulldevicename is not None:
677                                 errorMsg += _(" at /dev/%s")%fulldevicename
678                         self.msgWaitingMkfs.run_close(False, errorMsg)
679
680         def createFilesystemStart(self):
681                 self.createFilesystem(self.newpartitions)
682
683         def msgWaitingCB(self, ret, msg=""):
684                 if ret:
685                         self.createFSStartTimer.start(100,True)
686                 else:
687                         self.success = False
688                         self.msg = msg
689                         self.exitMessageTimer.start(100,True)
690
691         def msgWaitingMkfsCB(self, ret, msg=""):
692                 if self.devicenumber < self.newpartitions:
693                         self.createFSStartTimer.start(100,True)
694                 else:
695                         if ret == True:
696                                 self.success = True
697                                 self.msg = _("Device Initialization finished sucessfully!")
698                                 self.exitMessageTimer.start(100,True)
699                         else:
700                                 self.success = False
701                                 self.msg = msg
702                                 self.exitMessageTimer.start(100,True)
703
704         def exitMessage(self):
705                 if self.success:
706                         self.session.openWithCallback(self.exit, MessageBox, self.msg, MessageBox.TYPE_INFO, timeout = 10)
707                 else:
708                         self.session.openWithCallback(self.exit, MessageBox, self.msg, MessageBox.TYPE_ERROR, timeout = 10)
709         
710 # Initializing end
711
712 # device check start..
713 class DeviceCheck(Screen):
714         skin = """<screen position="0,0" size="0,0"/>"""
715         def __init__(self, session, partition):
716                 Screen.__init__(self, session)
717                 self.session = session
718                 self.deviceCheckConsole = Console()
719                 self.partition = partition
720                 self.onLayoutFinish.append(self.timerStart)
721                 self.checkStartTimer = eTimer()
722                 self.checkStartTimer.callback.append(self.confirmMessage)
723
724         def timerStart(self):
725                 self.checkStartTimer.start(100,True)
726
727         def confirmMessage(self):
728                 fssize = self.partition["size"]
729                 if long(fssize) > 1024*1024*1024*16:
730                         message = _("Do you really want to check the filesystem?\nThis could take lots of time!")
731                         self.session.openWithCallback(self.confirmed, MessageBox, message)
732                 else:
733                         self.deviceCheckStart()
734
735         def confirmed(self, ret):
736                 print "confirmed : ",ret
737                 if ret:
738                         self.deviceCheckStart()
739                 else:
740                         self.exit()
741
742         def deviceCheckStart(self):
743                 print "deviceCheckStart "
744                 print "partition : ", self.partition
745                 device = self.partition["partition"]
746                 mountpoint = self.partition["mountpoint"]
747                 fstype = self.partition["fstype"]
748                 fssize = self.partition["size"]
749                 if device is not None and fstype.startswith("ext"):
750                         msg = _("Check filesystem, please wait ...")
751                         msg += _("\nDevice : /dev/%s")%(device)
752                         msg += _("\nFilesystem : %s")%(fstype)
753                         self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
754                         if mountpoint != "":
755                                 self.doUmountFsck(device, mountpoint, fstype)
756                         else:
757                                 self.umountFsckFinished("NORESULT", 0, (device, mountpoint, fstype))
758                 else:
759                         self.exit()
760
761         def doUmountFsck(self, device, mountpoint, fstype):
762                 cmd = "umount /dev/%s" % device
763                 self.deviceCheckConsole.ePopen(cmd, self.umountFsckFinished, (device, mountpoint, fstype))
764
765         def umountFsckFinished(self, result, retval, extra_args = None):
766                 device = extra_args[0]
767                 mountpoint = extra_args[1]
768                 fstype = extra_args[2]
769                 if retval == 0:
770                         cmd = "fsck." + fstype + " -f -p /dev/" + device
771                         self.deviceCheckConsole.ePopen(cmd, self.fsckFinished, extra_args)
772                 else:
773                         errorMsg = _("Can not umount device /dev/%s.\nMaybe some files of the filesystem are open")%device
774                         self.msgWaiting.run_close(False,errorMsg)
775                         
776         def fsckFinished(self, result, retval, extra_args = None):
777                 device = extra_args[0]
778                 mountpoint = extra_args[1]
779                 if retval == 0:
780                         text = _("Filesystem check finished sucessfully")
781                         self.msgWaiting.run_close(True, text)
782                 else:
783                         text = _("Error checking disk. The disk or filesystem may be damaged")
784                         self.msgWaiting.run_close(False, text)
785
786         def msgWaitingCB(self, ret, msg):
787                 if ret:
788                         self.session.open(MessageBox, msg, MessageBox.TYPE_INFO, timeout = 10)
789                 else:
790                         self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 10)
791
792                 partition = self.partition["partition"]
793                 mountpoint = self.partition["mountpoint"]
794                 fstype = self.partition["fstype"]
795                 if mountpoint != "":
796                         if fstype == "ntfs":
797                                 cmd = "ntfs-3g /dev/" + partition + " " + mountpoint
798                         else:
799                                 cmd = "mount /dev/" + partition + " " + mountpoint
800                         self.deviceCheckConsole.ePopen(cmd, self.mountPartitionFinished)
801                 else:
802                         self.exit()
803
804         def mountPartitionFinished(self, result, retval, extra_args = None):
805                 self.exit()
806
807         def exit(self):
808                 self.close()
809
810 #device check end
811
812 #device format start
813 class DeviceFormat(Screen):
814         skin = """<screen position="0,0" size="0,0"/>"""
815         def __init__(self, session, partition, newfstype):
816                 Screen.__init__(self, session)
817                 self.session = session
818                 self.deviceFormatConsole = Console()
819                 self.partition = partition
820                 self.newfstype = newfstype
821                 self.unmountedList = []
822                 self.onLayoutFinish.append(self.timerStart)
823                 self.formatStartTimer = eTimer()
824                 self.formatStartTimer.callback.append(self.DeviceFormatStart)
825
826         def timerStart(self):
827                 self.formatStartTimer.start(100,True)
828
829         def DeviceFormatStart(self):
830                 print "DeviceFormatStart : ", self.partition,
831                 print "Filesystem : ",self.newfstype
832                 device = self.partition["partition"]
833                 devicepath = "/dev/"+device
834                 mountpoint = self.partition["mountpoint"]
835                 fssize = self.partition["size"]
836                 newfstype = self.newfstype
837
838                 msg = _("Format filesystem, please wait ...")
839                 msg += _("\nDevice : %s")%(devicepath)
840                 msg += _("\nFilesystem : %s")%(newfstype)
841                 msg += _("\nSize : %s")%(byteConversion(fssize))
842                 self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox_2.TYPE_INFO, enable_input = False)
843                 if mountpoint != "":
844                         self.doumountPartition()
845                 else:
846                         self.umountPartitionFinished("NORESULT", 0)
847
848         def doumountPartition(self):
849                 oldfstype = self.partition["fstype"]
850                 newfstype = self.newfstype
851
852                 if newfstype == oldfstype:
853                         device = self.partition["partition"]
854                 else:
855                         device = self.partition["partition"][:3]
856                 cmd = ""
857                 mounts = file('/proc/mounts','r')
858                 for line in mounts.readlines():
859                         if line.startswith("/dev/%s"%device):
860                                 cmd += "umount %s;"%line.split()[0]
861                                 self.unmountedList.append([line.split()[0], line.split()[1]])
862                 self.deviceFormatConsole.ePopen(cmd, self.umountPartitionFinished)
863
864         def umountPartitionFinished(self, result, retval, extra_args = None):
865                 partition = self.partition["partition"]
866                 oldfstype = self.partition["fstype"]
867                 newfstype = self.newfstype
868                 if retval == 0:
869                         if oldfstype == newfstype:
870                                 self.changePartitionIDFinished("NORESULT", 0)
871                         else:
872                                 cmd = "sfdisk --change-id /dev/%s %s" % (partition[:3], partition[3:])
873                                 if newfstype[:3] == "ext":
874                                         cmd += " 83"
875                                 else:
876                                         cmd += " c"
877                                 self.deviceFormatConsole.ePopen(cmd, self.changePartitionIDFinished)
878                 else:
879                         errorMsg = _("Can not umount device /dev/%s.\nMaybe some files of the filesystem are open")%partition[:3]
880                         self.msgWaiting.run_close(False,errorMsg)
881
882         def changePartitionIDFinished(self, result, retval, extra_args = None):
883                 device = self.partition["partition"][:3]
884                 mountpoint = self.partition["mountpoint"]
885                 oldfstype = self.partition["fstype"]
886                 newfstype = self.newfstype
887                 if retval == 0:
888                         if oldfstype == newfstype:
889                                 self.refreshPartitionFinished("NORESULT", 0)
890                         else:
891                                 cmd = "sfdisk -R /dev/%s; sleep 5"%(device)
892                                 self.deviceFormatConsole.ePopen(cmd, self.refreshPartitionFinished)
893                 else:
894                         errorMsg = _("Can not change the partition ID for %s")%device
895                         self.msgWaiting.run_close(False,errorMsg)
896
897         def refreshPartitionFinished(self, result, retval, extra_args = None):
898                 print "refreshPartitionFinished!"
899                 partition = self.partition["partition"]
900                 mountpoint = self.partition["mountpoint"]
901                 size = int(self.partition["size"])/1024/1024
902                 oldfstype = self.partition["fstype"]
903                 newfstype = self.newfstype
904                 if retval == 0:
905                         if newfstype == "ext4":
906                                 cmd = "/sbin/mkfs.ext4 -F "
907                                 if size > 2 * 1024:
908                                         cmd += "-T largefile "
909                                 cmd += "-O extent,flex_bg,large_file,uninit_bg -m1 /dev/" + partition
910                         elif newfstype == "ext3":
911                                 cmd = "/sbin/mkfs.ext3 -F "
912                                 if size > 2 * 1024:
913                                         cmd += "-T largefile "
914                                 cmd += "-m0 /dev/" + partition
915                         elif newfstype == "ext2":
916                                 cmd = "/sbin/mkfs.ext2 -F "
917                                 if size > 2 * 1024:
918                                         cmd += "-T largefile "
919                                 cmd += "-m0 /dev/" + partition
920                         elif newfstype == "vfat":
921                                 if size > 4 * 1024 * 1024:
922                                         cmd = "/usr/sbin/mkfs.vfat -I -S4096 /dev/" + partition
923                                 else:
924                                         cmd = "/usr/sbin/mkfs.vfat -I /dev/" + partition
925                         self.deviceFormatConsole.ePopen(cmd, self.mkfsFinished)
926                 else:
927                         errorMsg = _("Can not format device /dev/%s.\nrefresh partition information failed!")%partition
928                         self.msgWaiting.run_close(False,errorMsg)
929                         
930         def mkfsFinished(self, result, retval, extra_args = None):
931                 print "mkfsFinished!"
932                 partition = self.partition["partition"]
933                 if retval == 0:
934                         cmd = ""
935                         if len(self.unmountedList) == 0:
936                                 self.doMountFinished("NORESULT",0)
937                         for x in self.unmountedList:
938                                 cmd += "mount %s %s;"%(x[0], x[1])
939                                 self.deviceFormatConsole.ePopen(cmd, self.doMountFinished)
940                 else:
941                         text = _("Make filesystem Error /dev/%s.\nPlease check your device.")%partition
942                         self.msgWaiting.run_close(False, text)
943
944         def doMountFinished(self, result, retval, extra_args = None):
945                 print "doMountFinished!"
946                 text = _("Format finished sucessfully.")
947                 self.msgWaiting.run_close(True, text)
948
949         def msgWaitingCB(self, ret, msg):
950                 if ret:
951                         self.session.openWithCallback(self.exit, MessageBox, msg, MessageBox.TYPE_INFO, timeout = 10)
952                 else:
953                         self.session.openWithCallback(self.exit, MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 10)
954
955         def exit(self, ret):
956                 self.close()
957
958 #device format end
959
960 class DeviceInfo():
961         def __init__(self):
962                 self.blockDeviceList = []
963
964         def getBlockDevices(self):
965                 return self.blockDeviceList
966
967         def refresh(self):
968                 self.blockDeviceList = []
969                 self.getBlockDeviceList()
970
971         def getBlockDeviceList(self):
972                 print "get block device Infomations..."
973                 for blockdev in listdir("/sys/block"):
974                         (error, blacklisted, removable, partitions, size, model, vendor) = self.getBlockDeviceInfo(blockdev)
975                         if not blacklisted and not error:
976 #                               print "%s : error %s, blacklisted %s, removable %s, partitions %s, size %s"%(blockdev, error, blacklisted, removable, partitions, size)
977                                 blockDevice = {}
978                                 blockDevice["blockdev"] = blockdev # str
979                                 blockDevice["removable"] = removable # bool [True, False]
980                                 blockDevice["partitions"] = partitions # list
981                                 blockDevice["size"] = size # str
982                                 blockDevice["model"] = model # str
983                                 blockDevice["vendor"] = vendor # str
984                                 self.blockDeviceList.append(blockDevice)
985
986         def getBlockDeviceInfo(self, blockdev):
987                 devpath = "/sys/block/" + blockdev
988                 error = False
989                 removable = False
990                 blacklisted = False
991                 partitions = []
992                 size =""
993                 model = ""
994                 vendor = ""
995                 try:
996                         dev = int(readFile(devpath + "/dev").split(':')[0])
997                         if dev in (7, 31) or blockdev[0:2] != 'sd': # 7: loop, 31 : mtdblock
998                                 blacklisted = True
999                                 return error, blacklisted, removable, partitions, size, model, vendor
1000                         removable = bool(int(readFile(devpath + "/removable")))
1001                         size = str(int(readFile(devpath + "/size").strip())*512)
1002                         model = readFile(devpath + "/device/model")
1003                         vendor = readFile(devpath + "/device/vendor")
1004                         for partition in listdir(devpath):
1005                                 if partition[:len(blockdev)] != blockdev:
1006                                         continue
1007                                 partitions.append(partition)
1008                 except IOError:
1009                         error = True
1010                 return error, blacklisted, removable, partitions, size, model, vendor
1011
1012         def getPartitionInfo(self, partition):
1013                 mountPoint = self.getPartitionMountpoint(partition)
1014                 (uuid , fsType) = self.getPartitionBlkidInfo(partition)
1015                 size_total = self.getPartitionSize(partition)
1016                 size_free = ""
1017                 if mountPoint != "":
1018                         size_free = self.getPartitionFree(mountPoint)   
1019                 partitionInfo = {}
1020                 partitionInfo["partition"] = partition
1021                 partitionInfo["mountpoint"] = mountPoint
1022                 partitionInfo["uuid"] = uuid
1023                 partitionInfo["fstype"] = fsType
1024                 partitionInfo["size"] = size_total
1025                 partitionInfo["free"] = size_free
1026                 return partitionInfo
1027
1028         def getPartitionMountpoint(self, partition):
1029                 mounts = file('/proc/mounts').read().split('\n')
1030                 for x in mounts:
1031                         if not x.startswith('/'):
1032                                 continue
1033                         devpath, mountpoint,  = x.split()[:2]
1034                         if mountpoint.startswith('/autofs'):
1035                                 continue
1036                         if path.basename(devpath) == partition:
1037                                 return mountpoint
1038                 return ""
1039
1040         def getPartitionBlkidInfo(self, partition):
1041                 parttionDev = "/dev/"+str(partition)
1042                 uuid = ""
1043                 partitionType = ""
1044                 cmd = "blkid -c /dev/null "+str(parttionDev)
1045                 try:
1046                         line = popen(cmd).readline().strip()
1047                         if not line.startswith(parttionDev):
1048                                 return (uuid, partitionType)
1049 #                       print "Blikd %s : %s"%(parttionDev, line)
1050                         if line.find(" UUID=") != -1:
1051                                 uuid = line.split(" UUID=")[1].split(' ')[0]
1052                         if line.find(" TYPE=") != -1:
1053                                 partitionType = line.split(" TYPE=")[1].split(' ')[0].strip('"')
1054                 except:
1055                         print "get blkid info error (%s)"%cmd
1056                 return (uuid, partitionType)
1057
1058         def getPartitionSize(self, partition):          
1059                 devpath = "/sys/block/%s/%s"%( str(partition[:3]), str(partition) )
1060                 try:
1061                         size = readFile(devpath + "/size")
1062                         return str(int(size)*512)
1063                 except:
1064                         return ""
1065
1066         def getPartitionFree(self, mountPoint):
1067                 try:
1068                         stat = statvfs(mountPoint)
1069                         size_free = stat.f_bfree*stat.f_bsize
1070                         return size_free
1071                 except:
1072                         return ""
1073
1074         def checkMountPoint(self, check_mountpoint):
1075                 try:
1076                         mounts = file('/proc/mounts').read().split('\n')
1077                         for x in mounts:
1078                                 if not x.startswith('/'):
1079                                         continue
1080                                 devpath, mountpoint  = x.split()[:2]
1081                                 if mountpoint == check_mountpoint:
1082                                         return devpath
1083                 except:
1084                         pass
1085                 return None
1086
1087 deviceinfo = DeviceInfo()
1088
1089 class MountpointBrowser(Screen):
1090         skin="""
1091                 <screen name="MountpointBrowser" position="center,120" size="670,500" title="Select mountpoint">
1092                         <ePixmap pixmap="skin_default/buttons/red.png" position="20,0" size="140,40" alphatest="on" />
1093                         <ePixmap pixmap="skin_default/buttons/green.png" position="180,0" size="140,40" alphatest="on" />
1094                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="340,0" size="140,40" alphatest="on" />
1095                         <ePixmap pixmap="skin_default/buttons/blue.png" position="500,0" size="140,40" alphatest="on" />
1096                         <widget source="key_red" render = "Label" position="20,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#9f1313" transparent="1" />
1097                         <widget source="key_green" render = "Label" position="180,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#1f771f" transparent="1" />
1098                         <widget source="key_yellow" render = "Label" position="340,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#a08500" transparent="1" />
1099                         <widget source="key_blue" render = "Label" position="500,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#18188b" transparent="1" />
1100                         <eLabel position="10,50" size="650,1" backgroundColor="#b3b3b9"/>
1101                         <widget name="filelist" position="10,60" size="650,440" itemHeight="30" scrollbarMode="showOnDemand"/>
1102                 </screen>
1103         """
1104         def __init__(self, session):
1105                 Screen.__init__(self, session)
1106                 self["key_red"] = StaticText(_("Cancel"))
1107                 self["key_green"] = StaticText(_("Select"))
1108                 self["key_yellow"] = StaticText(_("Create directory"))
1109                 self["key_blue"] = StaticText("Delete directory")
1110                 directory = "/media/"
1111                 inhibitDirs = ["/autofs", "/mnt", "/hdd", "/bin", "/boot", "/dev", "/etc", "/home", "/lib", "/proc", "/sbin", "/share", "/sys", "/tmp", "/usr", "/var"]
1112                 self.filelist = FileList(directory, matchingPattern="", inhibitDirs = inhibitDirs)
1113                 self["filelist"] = self.filelist
1114
1115                 self["shortcuts"] = ActionMap(["ColorActions"],
1116                         {
1117                         "red": self.exit,
1118                         "green": self.select,
1119                         "yellow": self.createDirectory,
1120                         "blue": self.deleteDirectory,
1121                         }, -2)
1122
1123                 self["OkCancelActions"] = ActionMap(["OkCancelActions"],
1124                         {
1125                         "cancel": self.exit,
1126                         "ok": self.ok,
1127                         }, -2)
1128
1129         def ok(self):
1130                 if self.filelist.canDescent():
1131                         self.filelist.descent()
1132
1133         def select(self):
1134                 if self["filelist"].getCurrentDirectory() is not None:
1135                         if self.filelist.canDescent() and self["filelist"].getFilename() and self["filelist"].getFilename().startswith(self["filelist"].getCurrentDirectory()):
1136                                 self.filelist.descent()
1137                                 currDir = self["filelist"].getCurrentDirectory()
1138                                 self.close(currDir)
1139                 else:
1140                         self.close(self["filelist"].getFilename())
1141
1142         def createDirectory(self):
1143                 self.session.openWithCallback(self.createDirectoryCB, VirtualKeyBoard, title = (_("Input mount point path.")), text = "")
1144
1145         def createDirectoryCB(self, retval = None):
1146                 newdir=None
1147                 try:
1148                         if retval is not None:
1149                                 newdir = self["filelist"].getCurrentDirectory()+'/'+retval
1150                                 if not path.exists(newdir):
1151                                         os.system("mkdir %s"%newdir)
1152                                 self.filelist.refresh()
1153                 except:
1154                         if newdir:
1155                                 self.session.open(MessageBox, _("Create directory failed!\n%s")%newdir, MessageBox.TYPE_ERROR, timeout = 10)
1156
1157         def deleteDirectory(self):
1158                 delDir=None
1159                 try:
1160                         if self["filelist"].getCurrentDirectory() is not None:
1161                                 if self.filelist.canDescent() and self["filelist"].getFilename() and self["filelist"].getFilename().startswith(self["filelist"].getCurrentDirectory()):
1162                                         delDir = self["filelist"].getFilename()
1163                                         if path.exists(delDir):
1164                                                 os.system("rmdir '%s'"%delDir)
1165                                         if path.exists(delDir):
1166                                                 self.session.open(MessageBox, _("Delete directory failed!\nMaybe directory is not empty."), MessageBox.TYPE_ERROR, timeout = 10)
1167                                         self.filelist.refresh()
1168                 except:
1169                         if delDir:
1170                                 self.session.open(MessageBox, _("Delete directory failed!\n%s")%newdir, MessageBox.TYPE_ERROR, timeout = 10)
1171
1172         def exit(self):
1173                 self.close(False)
1174
1175 class MessageBoxConfirm(MessageBox):
1176         skin =  """
1177                 <screen position="center,center" size="620,10" title="Message">
1178                         <widget name="text" position="65,8" size="420,0" font="Regular;20" />
1179                         <widget name="ErrorPixmap" pixmap="skin_default/icons/input_error.png" position="5,5" size="53,53" alphatest="blend" />
1180                         <widget name="QuestionPixmap" pixmap="skin_default/icons/input_question.png" position="5,5" size="53,53" alphatest="blend" />
1181                         <widget name="InfoPixmap" pixmap="skin_default/icons/input_info.png" position="5,5" size="53,53" alphatest="blend" />
1182                         <widget name="list" position="100,100" size="380,375" transparent="1" />
1183                         <applet type="onLayoutFinish">
1184 # this should be factored out into some helper code, but currently demonstrates applets.
1185 from enigma import eSize, ePoint
1186
1187 orgwidth  = self.instance.size().width()
1188 orgheight = self.instance.size().height()
1189 orgpos    = self.instance.position()
1190 textsize  = self[&quot;text&quot;].getSize()
1191
1192 # y size still must be fixed in font stuff...
1193 textsize = (textsize[0] + 50, textsize[1] + 50)
1194 offset = 0
1195 if self.type == self.TYPE_YESNO:
1196         offset = 60
1197 wsizex = textsize[0] + 60
1198 wsizey = textsize[1] + offset
1199 if (280 &gt; wsizex):
1200         wsizex = 280
1201 wsize = (wsizex, wsizey)
1202
1203 # resize
1204 self.instance.resize(eSize(*wsize))
1205
1206 # resize label
1207 self[&quot;text&quot;].instance.resize(eSize(*textsize))
1208
1209 # move list
1210 listsize = (wsizex, 50)
1211 self[&quot;list&quot;].instance.move(ePoint(0, textsize[1]))
1212 self[&quot;list&quot;].instance.resize(eSize(*listsize))
1213
1214 # center window
1215 newwidth = wsize[0]
1216 newheight = wsize[1]
1217 self.instance.move(ePoint(orgpos.x() + (orgwidth - newwidth)/2, orgpos.y() + (orgheight - newheight)/2))
1218                         </applet>
1219                 </screen>
1220                 """
1221
1222 dmconfigfile = resolveFilename(SCOPE_PLUGINS, "SystemPlugins/DeviceManager/devicemanager.cfg")
1223 class DeviceManagerConfig():
1224         def __init__(self):
1225                 self.configList = []
1226
1227         def getConfigList(self):
1228                 return self.configList
1229
1230         def updateConfigList(self):
1231                 try:
1232                         self.configList = []
1233                         file = open("/proc/mounts")
1234                         mounts = file.readlines()
1235                         file.close()
1236                         for x in mounts:
1237                                 if x.startswith("/dev/sd"):
1238                                         device = x.split()[0].split('/dev/')[1]
1239                                         mountpoint = x.split()[1]
1240                                         if mountpoint.startswith('/autofs'):
1241                                                 continue
1242                                         (uuid, partitionType) = deviceinfo.getPartitionBlkidInfo(device)
1243                                         if uuid != '' and mountpoint != '':
1244                                                 self.configList.append([uuid, mountpoint])
1245                         self.saveConfig()
1246                 except:
1247                         print "updateConfigList failed!"
1248
1249         def loadConfig(self):
1250                 if not fileExists(dmconfigfile):
1251                         os.system("touch %s" % dmconfigfile)
1252                 self.configList = []
1253                 data = file(dmconfigfile).read().split('\n')
1254                 for line in data:
1255                         if line.find(':') != -1:
1256                                 (uuid, mountpoint) = line.split(':')
1257                                 if uuid != '' and mountpoint != '':
1258                                         self.configList.append([uuid, mountpoint])
1259
1260         def saveConfig(self):
1261                 confFile = open(dmconfigfile,'w')
1262                 data = ""
1263                 for line in self.configList:
1264                         data += "%s:%s\n"%(line[0],line[1]) # uuid, mountpoint
1265                 confFile.write(data)
1266                 confFile.close()
1267
1268         def appendConfig(self, uuid, mountpoint):
1269                 for x in self.configList:
1270                         if x[0] == uuid or x[1] == mountpoint:
1271                                 self.configList.remove(x)
1272                 self.configList.append([uuid, mountpoint])
1273
1274         def removeConfig(self, value):
1275                 for x in self.configList:
1276                         if x[0] == value or x[1] == value:
1277                                 self.configList.remove(x)
1278
1279 devicemanagerconfig = DeviceManagerConfig()
1280
1281 devicemanagerhotplugactive = True
1282 def DeviceManagerhotplugDeviceStart(action, device):
1283         global devicemanagerhotplugactive
1284         if devicemanagerhotplugactive:
1285                 DeviceManagerHotplugDevice(action, device)
1286
1287 def DeviceManagerHotplugDevice(action, device):
1288         if not config.plugins.devicemanager.hotplug_enable.value:
1289                 return
1290         print "[DeviceManager Hotplug Device] action : %s, device : %s"%(action, device.device)
1291
1292         try:
1293                 if action == 'add' and device.is_hotplug and len(device.device) == 3:
1294                         if device.device.startswith("sd"):
1295                                 newdevice = "/dev/" + device.device
1296                                 cmd = "sleep 3 && blkid -c /dev/null " + newdevice + "*"
1297                                 data = popen(cmd).read().split('\n')
1298 #                               print "[DeviceManagerHotplugDevice] blkid data : ",data
1299                                 for line in data:
1300                                         uuid = ""
1301                                         partitionType = ""
1302                                         if line.startswith(newdevice):
1303                                                 if line.find(" UUID=") != -1:
1304                                                         uuid = line.split(" UUID=")[1].split(' ')[0]
1305                                                 if line.find(" TYPE=") != -1:
1306                                                         partitionType = line.split(" TYPE=")[1].split(' ')[0].strip('"')
1307                                                 mountdev = line.split(':')[0]
1308                                                 devicemanagerconfig.loadConfig()
1309                                                 configList = devicemanagerconfig.getConfigList()
1310                                                 for c in configList:
1311                                                         if uuid == c[0].strip():
1312                                                                 mountpoint = c[1].strip()
1313                                                                 if not os.path.ismount(mountpoint):
1314                                                                         if partitionType == "ntfs":
1315                                                                                 cmd = "ntfs-3g %s %s"%(mountdev, mountpoint)
1316                                                                         else:
1317                                                                                 cmd = "mount %s %s"%(mountdev, mountpoint)
1318                                                                         print "[DeviceManagerHotplugDevice] try..'%s'"%cmd
1319                                                                         os.system(cmd)
1320
1321                 elif action == 'remove' and device.device is not None and len(device.device) == 3:
1322                         mounts = file('/proc/mounts').read().split('\n')
1323                         for x in mounts:
1324                                 if not x.startswith('/'):
1325                                         continue
1326                                 if x.startswith("/dev/"+device.device):
1327                                         cmd = "umount "+x.split()[0]
1328                                         print "[DeviceManagerHotplugDevice] try.. '%s'"%cmd
1329                                         os.system(cmd)
1330         except:
1331                 print "[DeviceManagerHotplug] hotplugDevice error."
1332
1333 def callBackforDeviceManager(session, callback_result = False):
1334         if callback_result == True:
1335                 session.open(DeviceManager)
1336
1337 def checkMounts(session):
1338         try:
1339                 notMountable_dev = ""
1340                 for blockdev in listdir("/sys/block"):
1341                         devpath = "/sys/block/" + blockdev
1342                         dev = int(readFile(devpath + "/dev").split(':')[0])
1343                         if dev in (7, 31) or blockdev[0:2] != 'sd': # 7: loop, 31 : mtdblock
1344                                 continue
1345                         partitions = []
1346                         notMountable_partitions = []
1347                         for partition in listdir(devpath):
1348                                 if not partition.startswith(blockdev):
1349                                         continue
1350                                 partitions.append(partition)
1351                                 if os.access('/autofs/'+partition,0) is False:
1352                                         notMountable_partitions.append(partition)
1353                         if len(partitions) == 0 or len(notMountable_partitions) != 0:
1354                                 if notMountable_dev != "":
1355                                         notMountable_dev +=  ' '
1356                                 notMountable_dev += blockdev
1357
1358                 if notMountable_dev != "":
1359 #                               print "Not mountable partitions found."
1360                                 InfoText = _("Not mountable devices found.! (%s)\nDo you want to open DeviceManager and do initialize or format this device?\n\n(Open 'Menu->Setup->System -> Harddisk -> DeviceManager'\n and press MENU button to deactivate this check.)"%notMountable_dev)
1361                                 AddNotificationWithCallback(
1362                                                                 boundFunction(callBackforDeviceManager, session), 
1363                                                                 MessageBox, InfoText, timeout = 60, default = False
1364                                 )
1365         except:
1366                 print "checkMounts failed!"
1367
1368 def sessionstart(reason, **kwargs):
1369         if reason == 0:
1370                 if kwargs.has_key("session") and config.plugins.devicemanager.mountcheck_enable.value == True:
1371                         session = kwargs["session"]
1372                         checkMounts(session)
1373                 if config.plugins.devicemanager.hotplug_enable.value:
1374                         harddiskmanager.on_partition_list_change.append(DeviceManagerhotplugDeviceStart)
1375         elif reason == 1:
1376                 if config.plugins.devicemanager.hotplug_enable.value:
1377                         harddiskmanager.on_partition_list_change.remove(DeviceManagerhotplugDeviceStart)
1378
1379 def autostart(reason, **kwargs):
1380         if reason == 0:
1381                 try:
1382 # check at first enigma2 start  
1383                         if not fileExists(dmconfigfile):
1384                                 print "[DeviceManager] autostart : check devices at first start"
1385                                 sda_isremovable = False
1386 #                               sdb_isremovable = False
1387                                 sda_UUID = ""
1388 #                               sdb_UUID = ""
1389                                 os.system("touch %s"%dmconfigfile)
1390 # check sda
1391                                 sda_data = popen("cat /proc/partitions | grep sda1").read()
1392                                 if sda_data != '':
1393                                         sda_UUID = popen("blkid -o value -s UUID /dev/sda1").read().strip('\n')
1394                                         sda_isremovable = bool(int(readFile("/sys/block/sda/removable")))
1395                                         print "sda : %s, %s"%(sda_UUID, sda_isremovable)
1396 # check sdb 
1397 #                               sdb_data = popen("cat /proc/partitions | grep sdb1").read()
1398 #                               if sdb_data != '':
1399 #                                       sdb_UUID = popen("blkid -o value -s UUID /dev/sdb1").read().strip('\n')
1400 #                                       sdb_isremovable = bool(int(readFile("/sys/block/sdb/removable")))
1401 #                                       print "sdb : %s, %s"%(sdb_UUID, sdb_isremovable)
1402                                 cfg = ""
1403                                 if sda_data != '':
1404 #                                       if sdb_data != '':
1405 #                                               if not sda_isremovable:
1406 #                                                       cfg += '"%s":/media/hdd\n'%sda_UUID
1407 #                                                       cfg += '"%s":/media/usb\n'%sdb_UUID
1408 #                                               else:
1409 #                                                       if not sdb_isremovable:
1410 #                                                               cfg += '"%s":/media/hdd\n'%sdb_UUID
1411 #                                                               cfg += '"%s":/media/usb\n'%sda_UUID
1412 #                                                       else:
1413 #                                                               cfg += '"%s":/media/hdd\n'%sda_UUID
1414 #                                                               cfg += '"%s":/media/usb\n'%sdb_UUID
1415 #                                       else:
1416 #                                               cfg += '"%s":/media/hdd\n'%sda_UUID
1417                                         cfg += '"%s":/media/hdd\n'%sda_UUID
1418                                 confFile = open(dmconfigfile,'w')
1419                                 confFile.write(cfg)
1420                                 confFile.close()
1421 #                               if not path.exists("/media/usb"):
1422 #                                               os.system("mkdir -p /media/usb")
1423                                 if not path.exists("/media/hdd"):
1424                                         os.system("mkdir -p /media/hdd")
1425                                 
1426 # check at first enigma2 start - end
1427                         devicemanagerconfig.loadConfig()
1428                         configList = devicemanagerconfig.getConfigList()
1429                         if len(configList) != 0:
1430                                 print "[DeviceManager] automount from device manager configs"
1431                                 cmd = "blkid -c /dev/null /dev/sd*"
1432                                 data = popen(cmd).read().split('\n')
1433                                 for line in data:
1434                                         device = ""
1435                                         uuid = ""
1436                                         filesystem = ""
1437                                         device = line.split(':')[0]
1438                                         if line.find(" UUID=") != -1:
1439                                                 uuid = line.split(" UUID=")[1].split(' ')[0]
1440                                         if line.find(" TYPE=") != -1:
1441                                                 filesystem = line.split(" TYPE=")[1].split(' ')[0].strip('"')
1442                                         for line in configList:
1443                                                 configuuid = line[0].strip()
1444                                                 configmountpoint = line[1].strip()
1445                                                 if configuuid == uuid and path.exists(configmountpoint) and not path.ismount(configmountpoint):
1446                                                         if filesystem == "ntfs":
1447                                                                 cmd = "ntfs-3g %s %s"%(device, configmountpoint)
1448                                                         else:
1449                                                                 cmd = "mount -t %s %s %s"%(filesystem, device, configmountpoint)
1450                                                         print "[DeviceManager] ",cmd
1451                                                         os.system(cmd)
1452                                                         break
1453                 except:
1454                         print "[DeviceManager] autostart failed!"
1455
1456 def menu(menuid, **kwargs):
1457         if menuid == "harddisk":
1458                 return [(_("DeviceManager"), main, "device_manager", 1)]
1459         return []
1460
1461 def main(session, **kwargs):
1462         session.open(DeviceManager)
1463
1464 def Plugins(path, **kwargs):
1465         return [
1466                 PluginDescriptor(name = _("DeviceManager"), description = _("manage block devices of your VU+"), where = PluginDescriptor.WHERE_MENU,fnc=menu),
1467                 PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, needsRestart = True, fnc = sessionstart),
1468                 PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, needsRestart = True, fnc = autostart)
1469                 ]
1470
1471 class MessageBox_2(MessageBox):
1472         def __init__(self, session, text, type = MessageBox.TYPE_YESNO, timeout = -1, close_on_any_key = False, default = True, enable_input = True, msgBoxID = None):
1473                 MessageBox.__init__(self, session, text, type, timeout, close_on_any_key, default, enable_input, msgBoxID)
1474                 self.skinName = "MessageBox"
1475                 self.closeTimer = eTimer()
1476                 self.closeTimer.callback.append(self.msg_close)
1477                 self.devicemanager_ret = False
1478                 self.devicemanager_msg = ""
1479
1480         def msg_close(self):
1481                 self.close(self.devicemanager_ret, self.devicemanager_msg)
1482
1483         def run_close(self, ret, msg=""):
1484                 self.devicemanager_ret = ret
1485                 self.devicemanager_msg = msg
1486                 self.closeTimer.start(100,True)
1487
1488         def createSummary(self):
1489                 return MessageBox_2_Summary
1490
1491 class MessageBox_2_Summary(Screen):
1492         skin="""
1493                 <screen name="MessageBox_2_Summary" position="0,0" size="256,64" id="1">
1494                         <widget source="parent.Text" render="Label" position="0,0" size="256,64" font="Regular;13" halign="center" valign="center" />
1495                 </screen>
1496         """