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