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