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