6d5860f4b9b74befe1149848057eaceb7c0de8a5
[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 deviceinfo.isMountable(partition) is False:
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                                 if partitionsize > 2 * 1024 * 1024: # if partiton size larger then 2GB, use FAT32
803                                         cmd += " -F 32"
804
805                 else:
806                         self.createFilesystemFinished(None, -1, (self.device, fulldevicename))
807                         return
808
809                 msg = _("Create filesystem, please wait ...")
810                 msg += _("\nPartition : %s") % (fulldevicename)
811                 msg += _("\nFilesystem : %s") % (self.fstype)
812                 msg += _("\nDisk Size : %s MB") % (self.inputbox_partitionSizeTotal)
813                 msg += _("\nPartition Size : %d %s\n") % (int(self.inputbox_partitionSizeList[self.devicenumber-1]), self.unit)
814                 self.msgWaitingMkfs = self.session.openWithCallback(self.msgWaitingMkfsCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
815                 self.mkfs_cmd = cmd
816                 self.doMkfsTimer.start(500,True)
817
818         def doMkfs(self):
819                 fulldevicename = "/dev/" + self.device + str(self.devicenumber)
820                 self.deviceInitConsole.ePopen(self.mkfs_cmd, self.createFilesystemFinished, (self.device, fulldevicename))
821
822         def createFilesystemFinished(self, result, retval, extra_args = None):
823                 device = extra_args[0]
824                 fulldevicename = extra_args[1]
825                 if retval == 0:
826                         self.msgWaitingMkfs.run_close(True)
827                 else:
828                         errorMsg = _("Creating filesystem Error")
829                         if fulldevicename is not None:
830                                 errorMsg += _(" at /dev/%s")%fulldevicename
831                         self.msgWaitingMkfs.run_close(False, errorMsg)
832
833         def createFilesystemStart(self):
834                 self.createFilesystem(self.newpartitions)
835
836         def msgWaitingCB(self, ret, msg=""):
837                 if ret:
838                         self.createFSStartTimer.start(100,True)
839                 else:
840                         self.success = False
841                         self.msg = msg
842                         self.exitMessageTimer.start(100,True)
843
844         def msgWaitingMkfsCB(self, ret, msg=""):
845                 if self.devicenumber < self.newpartitions:
846                         self.createFSStartTimer.start(100,True)
847                 else:
848                         if ret == True:
849                                 self.success = True
850                                 self.msg = _("Device Initialization finished sucessfully!")
851                                 self.updateDeviceInfo()
852                                 self.exitMessageTimer.start(100,True)
853                         else:
854                                 self.success = False
855                                 self.msg = msg
856                                 self.exitMessageTimer.start(100,True)
857
858         def exitMessage(self):
859                 if self.success:
860                         self.session.openWithCallback(self.exit, MessageBox, self.msg, MessageBox.TYPE_INFO, timeout = 10)
861                 else:
862                         self.session.openWithCallback(self.exit, MessageBox, self.msg, MessageBox.TYPE_ERROR, timeout = 10)
863
864         def updateDeviceInfo(self):
865 # update devicemanager configs
866                 devicemanagerconfig.updateConfigList()
867
868 # Initializing end
869
870 # device check start..
871 class DeviceCheck(Screen):
872         skin = """<screen position="0,0" size="0,0"/>"""
873         def __init__(self, session, partition):
874                 Screen.__init__(self, session)
875                 self.session = session
876                 self.deviceCheckConsole = Console()
877                 self.partition = partition
878                 self.onLayoutFinish.append(self.timerStart)
879                 self.checkStartTimer = eTimer()
880                 self.checkStartTimer.callback.append(self.confirmMessage)
881                 self.umountTimer = eTimer()
882                 self.umountTimer.callback.append(self.doUnmount)
883
884         def timerStart(self):
885                 self.checkStartTimer.start(100,True)
886
887         def confirmMessage(self):
888                 fssize = self.partition["size"]
889                 if long(fssize) > 1024*1024*1024*16:
890                         message = _("Do you really want to check the filesystem?\nThis could take lots of time!")
891                         self.session.openWithCallback(self.confirmed, MessageBox, message)
892                 else:
893                         self.deviceCheckStart()
894
895         def confirmed(self, ret):
896                 print "confirmed : ",ret
897                 if ret:
898                         self.deviceCheckStart()
899                 else:
900                         self.exit()
901
902         def deviceCheckStart(self):
903                 print "deviceCheckStart "
904                 print "partition : ", self.partition
905                 device = self.partition["partition"]
906                 fstype = self.partition["fstype"]
907                 fssize = self.partition["size"]
908                 if device is not None and fstype.startswith("ext"):
909                         msg = _("Check filesystem, please wait ...")
910                         msg += _("\nDevice : /dev/%s")%(device)
911                         msg += _("\nFilesystem : %s")%(fstype)
912                         self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
913                         self.umountTimer.start(500,True)
914                 else:
915                         self.exit()
916
917         def doUnmount(self):
918                 device = self.partition["partition"]
919                 mountpoint = self.partition["mountpoint"]
920                 fstype = self.partition["fstype"]
921                 if mountpoint != "":
922                         self.doUmountFsck(device, mountpoint, fstype)
923                 else:
924                         self.umountFsckFinished("NORESULT", 0, (device, mountpoint, fstype))
925
926         def doUmountFsck(self, device, mountpoint, fstype):
927                 cmd = "umount /dev/%s" % device
928                 self.deviceCheckConsole.ePopen(cmd, self.umountFsckFinished, (device, mountpoint, fstype))
929
930         def umountFsckFinished(self, result, retval, extra_args = None):
931                 device = extra_args[0]
932                 mountpoint = extra_args[1]
933                 fstype = extra_args[2]
934                 if retval == 0:
935                         cmd = "fsck." + fstype + " -f -p /dev/" + device
936                         self.deviceCheckConsole.ePopen(cmd, self.fsckFinished, extra_args)
937                 else:
938                         errorMsg = _("Can not umount device /dev/%s.\nMaybe some files of the filesystem are open")%device
939                         self.msgWaiting.run_close(False,errorMsg)
940                         
941         def fsckFinished(self, result, retval, extra_args = None):
942                 device = extra_args[0]
943                 mountpoint = extra_args[1]
944                 if retval == 0:
945                         text = _("Filesystem check finished sucessfully")
946                         self.msgWaiting.run_close(True, text)
947                 else:
948                         text = _("Error checking disk. The disk or filesystem may be damaged")
949                         self.msgWaiting.run_close(False, text)
950
951         def msgWaitingCB(self, ret, msg):
952                 if ret:
953                         self.session.open(MessageBox, msg, MessageBox.TYPE_INFO, timeout = 10)
954                 else:
955                         self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 10)
956
957                 partition = self.partition["partition"]
958                 mountpoint = self.partition["mountpoint"]
959                 fstype = self.partition["fstype"]
960                 if mountpoint != "":
961                         if fstype == "ntfs":
962                                 cmd = "ntfs-3g /dev/" + partition + " " + mountpoint
963                         else:
964                                 cmd = "mount /dev/" + partition + " " + mountpoint
965                         self.deviceCheckConsole.ePopen(cmd, self.mountPartitionFinished)
966                 else:
967                         self.exit()
968
969         def mountPartitionFinished(self, result, retval, extra_args = None):
970                 self.exit()
971
972         def exit(self):
973                 self.close()
974
975 #device check end
976
977 #device format start
978 class DeviceFormat(Screen):
979         skin = """<screen position="0,0" size="0,0"/>"""
980         def __init__(self, session, partition, newfstype):
981                 Screen.__init__(self, session)
982                 self.session = session
983                 self.deviceFormatConsole = Console()
984                 self.partition = partition
985                 self.newfstype = newfstype
986                 self.unmountedList = []
987                 self.onLayoutFinish.append(self.timerStart)
988                 self.formatStartTimer = eTimer()
989                 self.formatStartTimer.callback.append(self.DeviceFormatStart)
990                 self.setHotplugDisabled = False
991                 self.umountTimer = eTimer()
992                 self.umountTimer.callback.append(self.doUnmount)
993
994         def timerStart(self):
995                 self.formatStartTimer.start(100,True)
996
997         def DeviceFormatStart(self):
998                 devicemanagerhotplug.setHotplugActive(False)
999                 self.setHotplugDisabled = True
1000                 print "DeviceFormatStart : ", self.partition,
1001                 print "Filesystem : ",self.newfstype
1002                 device = self.partition["partition"]
1003                 devicepath = "/dev/"+device
1004                 fssize = self.partition["size"]
1005                 newfstype = self.newfstype
1006                 msg = _("Format filesystem, please wait ...")
1007                 msg += _("\nDevice : %s")%(devicepath)
1008                 msg += _("\nFilesystem : %s")%(newfstype)
1009                 msg += _("\nSize : %s")%(byteConversion(fssize))
1010                 self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox_2.TYPE_INFO, enable_input = False, msgBoxID = None)
1011                 self.umountTimer.start(500,True)
1012
1013         def doUnmount(self):
1014                 mountpoint = self.partition["mountpoint"]
1015                 if mountpoint != "":
1016                         self.doumountPartition()
1017                 else:
1018                         self.umountPartitionFinished("NORESULT", 0)
1019
1020         def doumountPartition(self):
1021                 oldfstype = self.partition["fstype"]
1022                 newfstype = self.newfstype
1023
1024                 if newfstype == oldfstype:
1025                         device = self.partition["partition"]
1026                 else:
1027                         device = self.partition["partition"][:3]
1028                 cmd = ""
1029                 mounts = file('/proc/mounts','r')
1030                 for line in mounts.readlines():
1031                         if line.startswith("/dev/%s"%device):
1032                                 cmd += "umount %s;"%line.split()[0]
1033                                 self.unmountedList.append([line.split()[0], line.split()[1]])
1034                 self.deviceFormatConsole.ePopen(cmd, self.umountPartitionFinished)
1035
1036         def umountPartitionFinished(self, result, retval, extra_args = None):
1037                 partition = self.partition["partition"]
1038                 oldfstype = self.partition["fstype"]
1039                 newfstype = self.newfstype
1040                 if retval == 0:
1041                         if oldfstype == newfstype:
1042                                 self.changePartitionIDFinished("NORESULT", 0)
1043                         else:
1044                                 cmd = "sfdisk --change-id /dev/%s %s" % (partition[:3], partition[3:])
1045                                 if newfstype[:3] == "ext":
1046                                         cmd += " 83"
1047                                 else:
1048                                         cmd += " c"
1049                                 self.deviceFormatConsole.ePopen(cmd, self.changePartitionIDFinished)
1050                 else:
1051                         errorMsg = _("Can not umount device /dev/%s.\nMaybe some files of the filesystem are open")%partition[:3]
1052                         self.msgWaiting.run_close(False,errorMsg)
1053
1054         def changePartitionIDFinished(self, result, retval, extra_args = None):
1055                 device = self.partition["partition"][:3]
1056                 mountpoint = self.partition["mountpoint"]
1057                 oldfstype = self.partition["fstype"]
1058                 newfstype = self.newfstype
1059                 if retval == 0:
1060                         if oldfstype == newfstype:
1061                                 self.refreshPartitionFinished("NORESULT", 0)
1062                         else:
1063                                 cmd = "sfdisk -R /dev/%s; sleep 5"%(device)
1064                                 self.deviceFormatConsole.ePopen(cmd, self.refreshPartitionFinished)
1065                 else:
1066                         if result and result.find("Use GNU Parted") > 0:
1067                                 print "[DeviceManager] /dev/%s use GNU Parted!" % device
1068                                 self.refreshPartitionFinished("NORESULT", 0)
1069                         else:
1070                                 errorMsg = _("Can not change the partition ID for %s")%device
1071                                 self.msgWaiting.run_close(False,errorMsg)
1072
1073         def refreshPartitionFinished(self, result, retval, extra_args = None):
1074                 print "refreshPartitionFinished!"
1075                 partition = self.partition["partition"]
1076                 mountpoint = self.partition["mountpoint"]
1077                 size = int(self.partition["size"])/1024/1024
1078                 oldfstype = self.partition["fstype"]
1079                 newfstype = self.newfstype
1080                 if retval == 0:
1081                         if newfstype == "ext4":
1082                                 cmd = "/sbin/mkfs.ext4 -F "
1083                                 if size > 2 * 1024:
1084                                         cmd += "-T largefile "
1085                                 cmd += "-O extent,flex_bg,large_file,uninit_bg -m1 /dev/" + partition
1086                         elif newfstype == "ext3":
1087                                 cmd = "/sbin/mkfs.ext3 -F "
1088                                 if size > 2 * 1024:
1089                                         cmd += "-T largefile "
1090                                 cmd += "-m0 /dev/" + partition
1091                         elif newfstype == "ext2":
1092                                 cmd = "/sbin/mkfs.ext2 -F "
1093                                 if size > 2 * 1024:
1094                                         cmd += "-T largefile "
1095                                 cmd += "-m0 /dev/" + partition
1096                         elif newfstype == "vfat":
1097                                 if size > 4 * 1024 * 1024:
1098                                         cmd = "/usr/sbin/mkfs.vfat -I -S4096 /dev/" + partition
1099                                 else:
1100                                         cmd = "/usr/sbin/mkfs.vfat -I /dev/" + partition
1101                                         if size > 2 * 1024: # if partiton size larger then 2GB, use FAT32
1102                                                 cmd += " -F 32"
1103                         self.deviceFormatConsole.ePopen(cmd, self.mkfsFinished)
1104                 else:
1105                         errorMsg = _("Can not format device /dev/%s.\nrefresh partition information failed!")%partition
1106                         self.msgWaiting.run_close(False,errorMsg)
1107                         
1108         def mkfsFinished(self, result, retval, extra_args = None):
1109                 print "mkfsFinished!"
1110                 partition = self.partition["partition"]
1111                 if retval == 0:
1112                         cmd = ""
1113                         if len(self.unmountedList) == 0:
1114                                 self.doMountFinished("NORESULT",0)
1115                         for x in self.unmountedList:
1116                                 cmd += "mount %s %s;"%(x[0], x[1])
1117                                 self.deviceFormatConsole.ePopen(cmd, self.doMountFinished)
1118                 else:
1119                         text = _("Make filesystem Error /dev/%s.\nPlease check your device.")%partition
1120                         self.msgWaiting.run_close(False, text)
1121
1122         def doMountFinished(self, result, retval, extra_args = None):
1123                 print "doMountFinished!"
1124                 text = _("Format finished sucessfully.")
1125                 self.msgWaiting.run_close(True, text)
1126
1127         def msgWaitingCB(self, ret, msg):
1128                 if ret:
1129                         self.session.openWithCallback(self.exit, MessageBox, msg, MessageBox.TYPE_INFO, timeout = 10)
1130                 else:
1131                         self.session.openWithCallback(self.exit, MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 10)
1132
1133         def exit(self, ret):
1134                 if self.setHotplugDisabled == True:
1135                         devicemanagerhotplug.setHotplugActive(True)
1136                         self.setHotplugDisabled = False
1137                 self.close()
1138
1139 #device format end
1140
1141 class DeviceInfo():
1142         def __init__(self):
1143                 self.blockDeviceList = []
1144
1145         def getBlockDevices(self):
1146                 return self.blockDeviceList
1147
1148         def refresh(self):
1149                 self.blockDeviceList = []
1150                 self.getBlockDeviceList()
1151
1152         def getBlockDeviceList(self):
1153                 print "get block device Infomations..."
1154                 for blockdev in listdir("/sys/block"):
1155                         (error, blacklisted, removable, partitions, size, model, vendor) = self.getBlockDeviceInfo(blockdev)
1156                         if not blacklisted and not error:
1157 #                               print "%s : error %s, blacklisted %s, removable %s, partitions %s, size %s"%(blockdev, error, blacklisted, removable, partitions, size)
1158                                 blockDevice = {}
1159                                 blockDevice["blockdev"] = blockdev # str
1160                                 blockDevice["removable"] = removable # bool [True, False]
1161                                 blockDevice["partitions"] = partitions # list
1162                                 blockDevice["size"] = size # str
1163                                 blockDevice["model"] = model # str
1164                                 blockDevice["vendor"] = vendor # str
1165                                 self.blockDeviceList.append(blockDevice)
1166
1167         def SortPartList(self, partList):
1168                 length = len(partList)-1
1169                 sorted = False
1170                 while sorted is False:
1171                         sorted = True
1172                         for idx in range(length):
1173                                 if int(partList[idx][3:]) > int(partList[idx+1][3:]):
1174                                         sorted = False
1175                                         partList[idx] , partList[idx+1] = partList[idx+1], partList[idx]
1176
1177         def getBlockDeviceInfo(self, blockdev):
1178                 devpath = "/sys/block/" + blockdev
1179                 error = False
1180                 removable = False
1181                 blacklisted = False
1182                 partitions = []
1183                 size =""
1184                 model = ""
1185                 vendor = ""
1186                 try:
1187                         dev = int(readFile(devpath + "/dev").split(':')[0])
1188                         if dev in (7, 31) or blockdev[0:2] != 'sd': # 7: loop, 31 : mtdblock
1189                                 blacklisted = True
1190                                 return error, blacklisted, removable, partitions, size, model, vendor
1191                         removable = bool(int(readFile(devpath + "/removable")))
1192                         size = str(int(readFile(devpath + "/size").strip())*512)
1193                         model = readFile(devpath + "/device/model")
1194                         vendor = readFile(devpath + "/device/vendor")
1195                         for partition in listdir(devpath):
1196                                 if partition[:len(blockdev)] != blockdev:
1197                                         continue
1198                                 partitions.append(partition)
1199                         self.SortPartList(partitions)
1200
1201                 except IOError:
1202                         error = True
1203                 return error, blacklisted, removable, partitions, size, model, vendor
1204
1205         def getPartitionInfo(self, partition):
1206                 mountPoint = self.getPartitionMountpoint(partition)
1207                 (uuid , fsType) = self.getPartitionBlkidInfo(partition)
1208                 size_total = self.getPartitionSize(partition)
1209                 size_free = ""
1210                 if mountPoint != "":
1211                         size_free = self.getPartitionFree(mountPoint)   
1212                 partitionInfo = {}
1213                 partitionInfo["partition"] = partition
1214                 partitionInfo["mountpoint"] = mountPoint
1215                 partitionInfo["uuid"] = uuid
1216                 partitionInfo["fstype"] = fsType
1217                 partitionInfo["size"] = size_total
1218                 partitionInfo["free"] = size_free
1219                 return partitionInfo
1220
1221         def getPartitionMountpoint(self, partition):
1222                 mounts = file('/proc/mounts').read().split('\n')
1223                 for x in mounts:
1224                         if not x.startswith('/'):
1225                                 continue
1226                         devpath, mountpoint,  = x.split()[:2]
1227                         if mountpoint.startswith('/autofs'):
1228                                 continue
1229                         if path.basename(devpath) == partition:
1230                                 return mountpoint
1231                 return ""
1232
1233         def getPartitionBlkidInfo(self, partition):
1234                 parttionDev = "/dev/"+str(partition)
1235                 uuid = ""
1236                 partitionType = ""
1237                 cmd = "blkid -c /dev/null "+str(parttionDev)
1238                 try:
1239                         line = popen(cmd).readline().strip()
1240                         if not line.startswith(parttionDev):
1241                                 return (uuid, partitionType)
1242 #                       print "Blikd %s : %s"%(parttionDev, line)
1243                         if line.find(" UUID=") != -1:
1244                                 uuid = line.split(" UUID=")[1].split(' ')[0]
1245                         if line.find(" TYPE=") != -1:
1246                                 partitionType = line.split(" TYPE=")[1].split(' ')[0].strip('"')
1247                 except:
1248                         print "get blkid info error (%s)"%cmd
1249                 return (uuid, partitionType)
1250
1251         def getPartitionSize(self, partition):          
1252                 devpath = "/sys/block/%s/%s"%( str(partition[:3]), str(partition) )
1253                 try:
1254                         size = readFile(devpath + "/size")
1255                         return str(int(size)*512)
1256                 except:
1257                         return ""
1258
1259         def getPartitionFree(self, mountPoint):
1260                 try:
1261                         stat = statvfs(mountPoint)
1262                         size_free = stat.f_bfree*stat.f_bsize
1263                         return size_free
1264                 except:
1265                         return ""
1266
1267         def checkMountPoint(self, check_mountpoint):
1268                 res = []
1269                 try:
1270                         mounts = file('/proc/mounts').read().split('\n')
1271                         for x in mounts:
1272                                 if not x.startswith('/'):
1273                                         continue
1274                                 devpath, mountpoint  = x.split()[:2]
1275                                 if mountpoint == check_mountpoint:
1276                                         res.append(devpath)
1277                 except:
1278                         pass
1279                 return res
1280
1281         def checkMountDev(self, device):
1282                 res = []
1283                 try:
1284                         mounts = file('/proc/mounts').read().split('\n')
1285                         for x in mounts:
1286                                 if not x.startswith('/'):
1287                                         continue
1288                                 devpath, mountpoint  = x.split()[:2]
1289                                 if devpath == device:
1290                                         res.append(mountpoint)
1291                 except:
1292                         pass
1293                 return res
1294
1295         def isMounted(self, devpath, mountpoint):
1296                 try:
1297                         mounts = file('/proc/mounts').readlines()
1298                         for x in mounts:
1299                                 if not x.startswith('/'):
1300                                         continue
1301                                 _devpath, _mountpoint  = x.split()[:2]
1302                                 if devpath == _devpath and mountpoint == _mountpoint:
1303                                         return True
1304                 except:
1305                         pass
1306                 return False
1307
1308         def isMounted_anymp(self, devpath):
1309                 try:
1310                         mounts = open('/proc/mounts', 'r').readlines()
1311                         for x in mounts:
1312                                 if not x.startswith('/'):
1313                                         continue
1314                                 _devPart, _mountpoint  = x.split()[:2]
1315                                 if devpath == _devPart:
1316                                         return True
1317                 except:
1318                         pass
1319                 return False
1320
1321         # check partition type is extended or swap.
1322         def checkSwapExtended(self, partition):
1323                 blockName = partition[:-1]
1324                 partNum = partition[-1]
1325                 data = os.popen("parted /dev/%s print" % blockName).readlines()
1326                 for x in data:
1327                         info = x.strip().split()
1328
1329                         if len(info) > 0 and info[0] == str(partNum):
1330                                 if len(info) >= 5 and info[4].find('extended') != -1: # check Type is extended
1331                                         return True
1332                                 elif len(info) >= 6 and info[5].find('swap') != -1: # check File System is swap
1333                                         return True
1334
1335                 return False
1336
1337         def isMountable(self, partition):
1338                 if self.checkSwapExtended(partition):
1339                         return False
1340
1341                 try:
1342                         if self.isMounted_anymp('/dev/'+partition):
1343                                 return True
1344
1345                         elif os.access('/autofs/'+partition, 0):
1346                                 return True
1347                 except:
1348                         pass
1349                 return False
1350
1351         def isFstabAutoMounted(self, uuid, devpath, mountpoint):
1352 #               print " >> isFstabMounted, uuid : %s, devpath : %s, mountpoint : %s"%(uuid, devpath, mountpoint)
1353                 if mountpoint[-1] == '/':
1354                         mountpoint = mountpoint[:-1]
1355                 data = file('/etc/fstab').read().split('\n')
1356                 for line in data:
1357                         if not line.startswith('/'):
1358                                 continue
1359                         dev, mp, ms = line.split()[0:3]
1360                         if uuid is not None and dev.startswith('UUID'):
1361                                 if dev.split('=')[1] == uuid.strip("\"") and mp == mountpoint and ms == 'auto':
1362 #                                       print " >> line : ", line
1363                                         return True
1364                         elif dev == devpath and mp == mountpoint and ms == 'auto':
1365 #                               print " >> line : ", line
1366                                 return True
1367                 return False
1368
1369         def umountByMountpoint(self, mountpoint):
1370                 if mountpoint is None:
1371                         return False
1372                 try:
1373                         if path.ismount(mountpoint):
1374                                 cmd = "umount " + mountpoint
1375                                 print "[DeviceManager] ", cmd
1376                                 os.system(cmd)
1377                 except:
1378                         print "Umount by mountpoint failed!"
1379                 if not path.ismount(mountpoint):
1380                         return True
1381                 return False
1382
1383         def umountByDevpath(self, devpath):
1384                 cmd = "umount " + devpath
1385                 print "[DeviceManager] ", cmd
1386                 os.system(cmd)
1387
1388 deviceinfo = DeviceInfo()
1389
1390 class MountpointBrowser(Screen):
1391         skin="""
1392                 <screen name="MountpointBrowser" position="center,120" size="670,500" title="Select mountpoint">
1393                         <ePixmap pixmap="skin_default/buttons/red.png" position="20,0" size="140,40" alphatest="on" />
1394                         <ePixmap pixmap="skin_default/buttons/green.png" position="180,0" size="140,40" alphatest="on" />
1395                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="340,0" size="140,40" alphatest="on" />
1396                         <ePixmap pixmap="skin_default/buttons/blue.png" position="500,0" size="140,40" alphatest="on" />
1397                         <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" />
1398                         <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" />
1399                         <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" />
1400                         <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" />
1401                         <eLabel position="10,50" size="650,1" backgroundColor="#b3b3b9"/>
1402                         <widget name="filelist" position="10,60" size="650,440" itemHeight="30" scrollbarMode="showOnDemand"/>
1403                 </screen>
1404         """
1405         def __init__(self, session):
1406                 Screen.__init__(self, session)
1407                 self["key_red"] = StaticText(_("Cancel"))
1408                 self["key_green"] = StaticText(_("Select"))
1409                 self["key_yellow"] = StaticText(_("Create directory"))
1410                 self["key_blue"] = StaticText("Delete directory")
1411                 directory = "/media/"
1412                 inhibitDirs = ["/autofs", "/mnt", "/hdd", "/bin", "/boot", "/dev", "/etc", "/home", "/lib", "/proc", "/sbin", "/share", "/sys", "/tmp", "/usr", "/var"]
1413                 self.filelist = FileList(directory, matchingPattern="", inhibitDirs = inhibitDirs)
1414                 self["filelist"] = self.filelist
1415
1416                 self["shortcuts"] = ActionMap(["ColorActions"],
1417                         {
1418                         "red": self.exit,
1419                         "green": self.select,
1420                         "yellow": self.createDirectory,
1421                         "blue": self.deleteDirectory,
1422                         }, -2)
1423
1424                 self["OkCancelActions"] = ActionMap(["OkCancelActions"],
1425                         {
1426                         "cancel": self.exit,
1427                         "ok": self.ok,
1428                         }, -2)
1429
1430         def ok(self):
1431                 if self.filelist.canDescent():
1432                         self.filelist.descent()
1433
1434         def select(self):
1435                 if self["filelist"].getCurrentDirectory() is not None:
1436                         if self.filelist.canDescent() and self["filelist"].getFilename() and self["filelist"].getFilename().startswith(self["filelist"].getCurrentDirectory()):
1437                                 self.filelist.descent()
1438                                 currDir = self["filelist"].getCurrentDirectory()
1439                                 self.close(currDir)
1440                 else:
1441                         self.close(self["filelist"].getFilename())
1442
1443         def createDirectory(self):
1444                 self.session.openWithCallback(self.createDirectoryCB, VirtualKeyBoard, title = (_("Input mount point path.")), text = "")
1445
1446         def createDirectoryCB(self, retval = None):
1447                 newdir=None
1448                 try:
1449                         if retval is not None:
1450                                 newdir = self["filelist"].getCurrentDirectory()+'/'+retval
1451                                 if not path.exists(newdir):
1452                                         os.system("mkdir %s"%newdir)
1453                                 self.filelist.refresh()
1454                 except:
1455                         if newdir:
1456                                 self.session.open(MessageBox, _("Create directory failed!\n%s")%newdir, MessageBox.TYPE_ERROR, timeout = 10)
1457
1458         def deleteDirectory(self):
1459                 delDir=None
1460                 try:
1461                         if self["filelist"].getCurrentDirectory() is not None:
1462                                 if self.filelist.canDescent() and self["filelist"].getFilename() and self["filelist"].getFilename().startswith(self["filelist"].getCurrentDirectory()):
1463                                         delDir = self["filelist"].getFilename()
1464                                         if path.exists(delDir):
1465                                                 os.system("rmdir '%s'"%delDir)
1466                                         if path.exists(delDir):
1467                                                 self.session.open(MessageBox, _("Delete directory failed!\nMaybe directory is not empty."), MessageBox.TYPE_ERROR, timeout = 10)
1468                                         self.filelist.refresh()
1469                 except:
1470                         if delDir:
1471                                 self.session.open(MessageBox, _("Delete directory failed!\n%s")%newdir, MessageBox.TYPE_ERROR, timeout = 10)
1472
1473         def exit(self):
1474                 self.close(False)
1475
1476 class MessageBoxConfirm(MessageBox):
1477         skin =  """
1478                 <screen position="center,center" size="620,10" title="Message">
1479                         <widget name="text" position="65,8" size="420,0" font="Regular;20" />
1480                         <widget name="ErrorPixmap" pixmap="skin_default/icons/input_error.png" position="5,5" size="53,53" alphatest="blend" />
1481                         <widget name="QuestionPixmap" pixmap="skin_default/icons/input_question.png" position="5,5" size="53,53" alphatest="blend" />
1482                         <widget name="InfoPixmap" pixmap="skin_default/icons/input_info.png" position="5,5" size="53,53" alphatest="blend" />
1483                         <widget name="list" position="100,100" size="380,375" transparent="1" />
1484                         <applet type="onLayoutFinish">
1485 # this should be factored out into some helper code, but currently demonstrates applets.
1486 from enigma import eSize, ePoint
1487
1488 orgwidth  = self.instance.size().width()
1489 orgheight = self.instance.size().height()
1490 orgpos    = self.instance.position()
1491 textsize  = self[&quot;text&quot;].getSize()
1492
1493 # y size still must be fixed in font stuff...
1494 textsize = (textsize[0] + 50, textsize[1] + 50)
1495 offset = 0
1496 if self.type == self.TYPE_YESNO:
1497         offset = 60
1498 wsizex = textsize[0] + 60
1499 wsizey = textsize[1] + offset
1500 if (280 &gt; wsizex):
1501         wsizex = 280
1502 wsize = (wsizex, wsizey)
1503
1504 # resize
1505 self.instance.resize(eSize(*wsize))
1506
1507 # resize label
1508 self[&quot;text&quot;].instance.resize(eSize(*textsize))
1509
1510 # move list
1511 listsize = (wsizex, 50)
1512 self[&quot;list&quot;].instance.move(ePoint(0, textsize[1]))
1513 self[&quot;list&quot;].instance.resize(eSize(*listsize))
1514
1515 # center window
1516 newwidth = wsize[0]
1517 newheight = wsize[1]
1518 self.instance.move(ePoint(orgpos.x() + (orgwidth - newwidth)/2, orgpos.y() + (orgheight - newheight)/2))
1519                         </applet>
1520                 </screen>
1521                 """
1522
1523 dmconfigfile = resolveFilename(SCOPE_PLUGINS, "SystemPlugins/DeviceManager/devicemanager.cfg")
1524 class DeviceManagerConfig():
1525         def __init__(self):
1526                 self.configList = []
1527
1528         def getConfigList(self):
1529                 return self.configList
1530
1531         def updateConfigList(self):
1532                 try:
1533                         self.configList = []
1534                         file = open("/proc/mounts")
1535                         mounts = file.readlines()
1536                         file.close()
1537                         for x in mounts:
1538                                 if x.startswith("/dev/sd"):
1539                                         device = x.split()[0].split('/dev/')[1]
1540                                         mountpoint = x.split()[1]
1541                                         if mountpoint.startswith('/autofs'):
1542                                                 continue
1543                                         (uuid, partitionType) = deviceinfo.getPartitionBlkidInfo(device)
1544                                         if uuid != '' and mountpoint != '':
1545                                                 self.configList.append([uuid, mountpoint])
1546                         self.saveConfig()
1547                 except:
1548                         print "updateConfigList failed!"
1549
1550         def loadConfig(self):
1551                 if not fileExists(dmconfigfile):
1552                         os.system("touch %s" % dmconfigfile)
1553                 self.configList = []
1554                 data = file(dmconfigfile).read().split('\n')
1555                 for line in data:
1556                         if line.find(':') != -1:
1557                                 (uuid, mountpoint) = line.split(':')
1558                                 if uuid != '' and mountpoint != '':
1559                                         self.configList.append([uuid, mountpoint])
1560
1561         def saveConfig(self):
1562                 confFile = open(dmconfigfile,'w')
1563                 data = ""
1564                 for line in self.configList:
1565                         data += "%s:%s\n"%(line[0],line[1]) # uuid, mountpoint
1566                 confFile.write(data)
1567                 confFile.close()
1568
1569         def appendConfig(self, uuid, mountpoint):
1570                 for x in self.configList:
1571                         if x[0] == uuid or x[1] == mountpoint:
1572                                 self.configList.remove(x)
1573                 self.configList.append([uuid, mountpoint])
1574
1575         def removeConfig(self, value):
1576                 for x in self.configList:
1577                         if x[0] == value or x[1] == value:
1578                                 self.configList.remove(x)
1579
1580 devicemanagerconfig = DeviceManagerConfig()
1581
1582 class deviceManagerHotplug:
1583         def __init__(self):
1584                 self.hotplugActive = True
1585
1586         def setHotplugActive(self,value=True):
1587                 if value:
1588                         self.hotplugActive = True
1589                 else:
1590                         self.hotplugActive = False
1591
1592         def printDebug(self):
1593                 for p in harddiskmanager.partitions:
1594                         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)
1595
1596         def doMount(self, uuid, devpath, mountpoint, filesystem):
1597 # check current device mounted on another mountpoint.
1598                 mp_list = []
1599                 mp_list = deviceinfo.checkMountDev(devpath)
1600                 for mp in mp_list:
1601                         if mp != mountpoint and path.ismount(mp):
1602                                 deviceinfo.umountByMountpoint(mp)
1603 # check another device mounted on configmountpoint
1604                 devpath_list = []
1605                 devpath_list = deviceinfo.checkMountPoint(mountpoint)
1606                 for devpath_ in devpath_list:
1607                         if devpath_ != devpath:
1608                                 print "[DeviceManager] Mount Failed. (Another device is already mounted)"
1609                                 return
1610 # do mount
1611 #               print "[DeviceManager] doMount"
1612                 if not path.exists(mountpoint):
1613                         os.system("mkdir %s"%mountpoint)
1614                 if path.exists(mountpoint):
1615                         if not path.ismount(mountpoint):
1616                                 if filesystem == "ntfs":
1617                                         cmd = "ntfs-3g %s %s"%(devpath, mountpoint)
1618                                 elif filesystem is None:
1619                                         cmd = "mount %s %s"%(devpath, mountpoint)
1620                                 else:
1621                                         cmd = "mount -t %s %s %s"%(filesystem, devpath, mountpoint)
1622                                 print "[DeviceManager] cmd : %s"%cmd
1623                                 os.system(cmd)
1624                                 if not deviceinfo.isMounted(devpath, mountpoint):
1625                                         print "[DeviceManager] %s doMount failed!"%devpath
1626                                         return
1627                                 else:
1628 # Update partition Info, add
1629                                         self.addPartitionAutofsMountpoint(devpath, mountpoint)
1630
1631         def doUmount(self, device, mountpoint):
1632                 devpath = "/dev/"+device
1633                 mountpoints = deviceinfo.checkMountDev(devpath)
1634                 if len(mountpoints) == 0:
1635                         return
1636                 for mp in mountpoints:
1637                         cmd = "umount %s"%devpath
1638                         print "[DeviceManager] cmd : %s"%cmd
1639                         os.system(cmd)
1640
1641         def addHotPlugDevice(self, partition):
1642                 device = partition.device
1643                 devpath = "/dev/"+device
1644 # get BlkidInfo
1645                 (uuid, filesystem) = deviceinfo.getPartitionBlkidInfo(device)
1646                 if uuid == "":
1647 # retry..
1648                         os.system("sleep 1")
1649                         (uuid, filesystem) = deviceinfo.getPartitionBlkidInfo(device)
1650                 if uuid == "":
1651                         print "[DeviceManagerHotplug] getBlkidInfo failed!"
1652                         return
1653 # get configList
1654                 devicemanagerconfig.loadConfig()
1655                 configList = devicemanagerconfig.getConfigList()
1656                 mountpoint = None
1657                 for line in configList:
1658                         if uuid == line[0].strip():
1659                                 mountpoint = line[1].strip()
1660                                 break
1661                 if mountpoint is None:
1662                         return
1663 # do mount
1664                 if deviceinfo.isMounted(devpath, mountpoint):
1665                         pass
1666 #                       print "[DeviceManagerHotplug] already mounted"
1667                 else:
1668                         self.doMount(uuid, devpath, mountpoint, filesystem)
1669
1670         def removeHotplugDevice(self, partition):
1671                 self.doUmount(partition.device, partition.mountpoint)
1672
1673         def getHotplugAction(self, action, partition):
1674                 if not self.hotplugActive or not config.plugins.devicemanager.hotplug_enable.value:
1675                         return
1676                 if partition.device is None or not partition.device.startswith("sd"):
1677                         return
1678                 print "[DeviceManagerHotplug] action : %s, device : %s"%(action, partition.device)
1679
1680                 if action == 'add':
1681                         self.addHotPlugDevice(partition)
1682                 elif action == 'remove':
1683                         self.removeHotplugDevice(partition)
1684
1685         def addPartitionAutofsMountpoint(self, devpath, mountpoint):
1686                 device = path.basename(devpath)
1687                 autofsMountpoint = harddiskmanager.getAutofsMountpoint(device)
1688 # check already appended to partition list
1689                 for x in harddiskmanager.partitions:
1690                         if x.mountpoint == autofsMountpoint or x.mountpoint == mountpoint:
1691                                 return
1692 #
1693                 from Components.Harddisk import Partition
1694                 physdev = path.realpath('/sys/block/' + device[:3] + '/device')[4:]
1695                 description = harddiskmanager.getUserfriendlyDeviceName(device, physdev)
1696                 p = Partition(mountpoint = autofsMountpoint, description = description, force_mounted = True, device = device)
1697                 harddiskmanager.partitions.append(p)
1698                 harddiskmanager.on_partition_list_change("add", p)
1699
1700         def autoMountOnStartup(self):
1701                 devicemanagerconfig.loadConfig()
1702                 configList = devicemanagerconfig.getConfigList()
1703 # get blkid info
1704                 blkiddata = []
1705                 data = os.popen("blkid -c /dev/NULL /dev/sd*").readlines()
1706                 for line in data:
1707                         devpath = uuid = filesystem = ""
1708                         devpath = line.split(':')[0]
1709                         if line.find(" UUID=") != -1:
1710                                 uuid = line.split(" UUID=")[1].split(' ')[0]
1711                         if line.find(" TYPE=") != -1:
1712                                 filesystem = line.split(" TYPE=")[1].split(' ')[0].strip('"')
1713                         blkiddata.append((devpath, uuid, filesystem))
1714 # check configList
1715                 for c in configList:
1716                         uuid_cfg = c[0].strip()
1717                         mountpoint_cfg = c[1].strip()
1718                         for (devpath, uuid, filesystem) in blkiddata:
1719                                 if uuid_cfg == uuid:
1720 # do mount
1721                                         if deviceinfo.isMounted(devpath, mountpoint_cfg):
1722 #                                               print "[Devicemanager startup] already mounted"
1723                                                 self.addPartitionAutofsMountpoint(devpath, mountpoint_cfg)
1724                                         else:
1725 #                                               print "[autoMountOnStartup] do mount(%s %s %s)"%(devpath, configmountpoint, filesystem)
1726                                                 self.doMount(uuid, devpath, mountpoint_cfg, filesystem)
1727
1728         def umountOnShutdown(self):
1729                 devicemanagerconfig.loadConfig()
1730                 configList = devicemanagerconfig.getConfigList()
1731 # get mount info
1732                 mounts = []
1733                 data = file('/proc/mounts').read().split('\n')
1734                 for x in data:
1735                         if not x.startswith('/dev/sd'):
1736                                 continue
1737                         devpath, mountpoint  = x.split()[:2]
1738                         mounts.append((path.basename(devpath), mountpoint))
1739 # get blkid info
1740                 data = self.getBlkidInfo()
1741 # check configList
1742                 for c in configList:
1743                         uuid_cfg = c[0].strip()
1744                         mountpoint_cfg = c[1].strip()
1745                         device_cfg = None
1746                         if uuid_cfg in data.keys():
1747                                 device_cfg = data[uuid_cfg]
1748                         if device_cfg is None:
1749                                 continue
1750                         for (device, mountpoint) in mounts:
1751                                 if device_cfg == device:
1752                                         if not deviceinfo.isFstabAutoMounted(uuid_cfg, "/dev/"+device_cfg, mountpoint_cfg):
1753                                                 self.doUmount(device, mountpoint)
1754
1755         def getBlkidInfo(self):
1756                 data = {}
1757                 blkid_data = os.popen("blkid -c /dev/NULL /dev/sd*").read()
1758                 for line in blkid_data.split('\n'):
1759 #                       print "[DeviceManager] getBlkidInfo line : ",line
1760                         device = uuid = ""
1761                         device = path.basename(line.split(':')[0])
1762                         if line.find(" UUID=") != -1:
1763                                 blkid_uuid = line.split(" UUID=")[1].split(' ')[0]
1764                                 data[blkid_uuid] = device
1765                 return data
1766
1767 devicemanagerhotplug = deviceManagerHotplug()
1768
1769 def DeviceManagerhotplugDeviceStart(action, device):
1770         devicemanagerhotplug.getHotplugAction(action, device)
1771
1772 def callBackforDeviceManager(session, callback_result = False):
1773         if callback_result == True:
1774                 session.open(DeviceManager)
1775
1776 def checkMounts(session):
1777         try:
1778                 noMountable_dev = ""
1779                 for blockdev in listdir("/sys/block"):
1780                         devpath = "/sys/block/" + blockdev
1781                         dev = int(readFile(devpath + "/dev").split(':')[0])
1782                         if dev in (7, 31) or blockdev[0:2] != 'sd': # 7: loop, 31 : mtdblock
1783                                 continue
1784                         partitions = []
1785                         noMountable_partitions = []
1786                         for partition in listdir(devpath):
1787                                 if not partition.startswith(blockdev):
1788                                         continue
1789
1790                                 if deviceinfo.checkSwapExtended(partition):
1791                                         continue
1792
1793                                 partitions.append(partition)
1794
1795                                 if deviceinfo.isMounted_anymp('/dev/' + partition):
1796                                         continue
1797
1798                                 if os.access('/autofs/'+partition, 0) is False:
1799                                         noMountable_partitions.append(partition)
1800
1801                         if len(partitions) == 0 or len(noMountable_partitions) != 0:
1802                                 if noMountable_dev != "":
1803                                         noMountable_dev +=  ' '
1804                                 noMountable_dev += blockdev
1805
1806                 if noMountable_dev != "":
1807                                 print "Umountable partitions found."
1808                                 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
1809                                 AddNotificationWithCallback(
1810                                                                 boundFunction(callBackforDeviceManager, session), 
1811                                                                 MessageBox, InfoText, timeout = 60, default = False
1812                                 )
1813         except:
1814                 print "checkMounts failed!"
1815
1816 def sessionstart(reason, **kwargs):
1817         if reason == 0:
1818                 if kwargs.has_key("session") and config.plugins.devicemanager.mountcheck_enable.value == True:
1819                         session = kwargs["session"]
1820                         checkMounts(session)
1821                 if config.plugins.devicemanager.hotplug_enable.value:
1822                         harddiskmanager.on_partition_list_change.append(DeviceManagerhotplugDeviceStart)
1823         elif reason == 1:
1824                 if config.plugins.devicemanager.hotplug_enable.value:
1825                         harddiskmanager.on_partition_list_change.remove(DeviceManagerhotplugDeviceStart)
1826
1827 def autostart(reason, **kwargs):
1828         if reason == 0:
1829                 try:
1830 # check at first enigma2 start  
1831                         if not fileExists(dmconfigfile):
1832                                 print "[DeviceManager] autostart : check devices at first start"
1833                                 sda_isremovable = False
1834                                 sda_UUID = ""
1835                                 os.system("touch %s"%dmconfigfile)
1836 # check sda
1837                                 sda_data = popen("cat /proc/partitions | grep sda1").read()
1838                                 if sda_data != '':
1839                                         sda_UUID = popen("blkid -o value -s UUID /dev/sda1").read().strip('\n')
1840                                         sda_isremovable = bool(int(readFile("/sys/block/sda/removable")))
1841                                         print "sda : %s, %s"%(sda_UUID, sda_isremovable)
1842                                 cfg = ""
1843                                 if sda_data != '':
1844                                         cfg += '"%s":/media/hdd\n'%sda_UUID
1845                                 confFile = open(dmconfigfile,'w')
1846                                 confFile.write(cfg)
1847                                 confFile.close()
1848                                 if not path.exists("/media/hdd"):
1849                                         os.system("mkdir -p /media/hdd")
1850 # auto mount
1851                         devicemanagerhotplug.autoMountOnStartup()
1852                 except:
1853                         print "[DeviceManager] autostart failed!"
1854         elif reason == 1:
1855                 devicemanagerhotplug.umountOnShutdown()
1856
1857 def menu(menuid, **kwargs):
1858         if menuid == "system":
1859                 return [(_("DeviceManager"), main, "device_manager", 50)]
1860         return []
1861
1862 def main(session, **kwargs):
1863         session.open(DeviceManager)
1864
1865 def Plugins(path, **kwargs):
1866         return [
1867                 PluginDescriptor(name = _("DeviceManager"), description = _("manage block devices of your VU+"), where = PluginDescriptor.WHERE_MENU,fnc=menu),
1868                 PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, needsRestart = True, fnc = sessionstart),
1869                 PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, needsRestart = True, fnc = autostart)
1870                 ]
1871
1872 class MessageBox_2(MessageBox):
1873         def __init__(self, session, text, type = MessageBox.TYPE_YESNO, timeout = -1, close_on_any_key = False, default = True, enable_input = True, msgBoxID = None):
1874                 MessageBox.__init__(self, session, text, type, timeout, close_on_any_key, default, enable_input, msgBoxID)
1875                 self.skinName = "MessageBox"
1876                 self.closeTimer = eTimer()
1877                 self.closeTimer.callback.append(self.msg_close)
1878                 self.devicemanager_ret = False
1879                 self.devicemanager_msg = ""
1880
1881         def msg_close(self):
1882                 self.close(self.devicemanager_ret, self.devicemanager_msg)
1883
1884         def run_close(self, ret, msg=""):
1885                 self.devicemanager_ret = ret
1886                 self.devicemanager_msg = msg
1887                 self.closeTimer.start(100,True)
1888
1889         def createSummary(self):
1890                 return MessageBox_2_Summary
1891
1892 class MessageBox_2_Summary(Screen):
1893         skin="""
1894                 <screen name="MessageBox_2_Summary" position="0,0" size="256,64" id="1">
1895                         <widget source="parent.Text" render="Label" position="0,0" size="256,64" font="Regular;13" halign="center" valign="center" />
1896                 </screen>
1897         """
1898