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, CheckSfdiskVer, enableUdevEvent
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
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 _
34 config.plugins.devicemanager = ConfigSubsection()
35 config.plugins.devicemanager.mountcheck_enable = ConfigEnableDisable(default=True)
37 def readFile(filename):
39 data = file.read().strip()
43 def byteConversion(byte):
44 if type(byte) == str and len(byte) == 0:
46 if type(byte) != long:
48 if byte > 1024*1024*1024:
49 int_part = byte/1024/1024/1024
50 dec_part = byte%(1024*1024*1024)/(1024*1024)
51 return "%d.%d GB"%(int_part, dec_part)
53 int_part = byte/1024/1024
54 dec_part = byte%(1024*1024)/1024
55 return "%d.%d MB"%(int_part, dec_part)
57 def checkStrValue(value , empty = ""):
58 if type(value) != str or len(value) == 0:
62 class DeviceManagerConfiguration(Screen, ConfigListScreen):
63 def __init__(self,session):
64 self.session = session
65 Screen.__init__(self,session)
66 self.skinName = "Setup"
67 self.createConfigList()
68 ConfigListScreen.__init__(self, self.list, session = self.session)
69 self["key_red"] = StaticText(_("Cancel"))
70 self["key_green"] = StaticText(_("OK"))
71 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
74 "cancel": self.keyCancel,
75 "red": self.keyCancel,
76 "green": self.keySave,
78 self.onShown.append(self.setWindowTitle)
80 def setWindowTitle(self):
81 self.setTitle(_("DeviceManager configuration"))
83 def createConfigList(self):
85 self.list.append(getConfigListEntry(_("Enable mount check for HDD : "), config.plugins.devicemanager.mountcheck_enable))
86 self.list.append(getConfigListEntry(_("Harddisk standby after : "), config.usage.hdd_standby))
88 class DeviceManager(Screen):
90 <screen position="center,center" size="590,350" title="DeviceManager">
91 <ePixmap pixmap="skin_default/buttons/red.png" position="20,0" size="140,40" alphatest="on" />
92 <ePixmap pixmap="skin_default/buttons/green.png" position="160,0" size="140,40" alphatest="on" />
93 <ePixmap pixmap="skin_default/buttons/yellow.png" position="300,0" size="140,40" alphatest="on" />
94 <ePixmap pixmap="skin_default/buttons/blue.png" position="440,0" size="140,40" alphatest="on" />
95 <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" />
96 <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" />
97 <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" />
98 <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" />
99 <ePixmap pixmap="skin_default/div-h.png" position="0,48" size="590,2" alphatest="on" />
100 <widget source="menu" render="Listbox" position="0,48" size="590,350" scrollbarMode="showOnDemand">
101 <convert type="TemplatedMultiContent">
104 MultiContentEntryText(pos = (50, 0), size = (510, 30), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 0), # index 0 is vendor - model
105 MultiContentEntryText(pos = (50, 32), size = (120, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1), # index 1 is Device
106 MultiContentEntryText(pos = (170, 32), size = (120, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2), # index 2 is Size
107 MultiContentEntryText(pos = (290, 32), size = (120, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 3), # index 3 is Partitions
108 MultiContentEntryText(pos = (410, 32), size = (130, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 4), # index 4 is Removable
109 MultiContentEntryPixmapAlphaTest(pos = (0, 52), size = (590, 2), png = 5), # png 5 is the div pixmap
112 MultiContentEntryText(pos = (50, 0), size = (500, 30), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 0), # index 1 is Partition
113 MultiContentEntryText(pos = (50, 32), size = (500, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1), # index 2 is Mounted on
114 MultiContentEntryText(pos = (50, 54), size = (500, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2), # index 3 UUID
115 MultiContentEntryText(pos = (50, 76), size = (130, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 3), # index 4 Type
116 MultiContentEntryText(pos = (180, 76), size = (130, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 4), # index 5 Size_total
117 MultiContentEntryText(pos = (310, 76), size = (190, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 5), # index 6 Size_free
118 MultiContentEntryPixmapAlphaTest(pos = (0, 96), size = (590, 2), png = 6), # png 6 is the div pixmap
121 MultiContentEntryPixmapAlphaTest(pos = (10, 7), size = (30, 30), png = 0), # index 0: picture
122 MultiContentEntryText(pos = (40, 0), size = (500, 30), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1), # index 1 name
123 MultiContentEntryText(pos = (40, 32), size = (500, 20), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2), # index 2 path
124 MultiContentEntryPixmapAlphaTest(pos = (0, 52), size = (590, 2), png = 5), # index 5 is the div pixmap
127 "fonts": [gFont("Regular", 22),gFont("Regular", 16),gFont("Regular", 28)],
135 def __init__(self, session):
136 Screen.__init__(self, session)
137 self.session = session
138 self.currList = "default"
139 self.currDevice = None
140 self.currPartition = None
141 self.defaultMountPoint = "/media/hdd"
143 self["menu"] = List(self.deviceList)
144 self["key_red"] = Label(_("Close"))
145 self["key_green"] = Label(" ")
146 self["key_yellow"] = Label(" ")
147 self["key_blue"] = Label(" ")
149 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions", "MenuActions" ],
152 "cancel": self.keyCancel,
153 "red": self.keyCancel,
155 "yellow": self.keyYellow,
156 "blue": self.keyBlue,
157 "menu": self.keyMenu,
159 self.DeviceManagerConsole = Console()
161 if not self.selectionChanged in self["menu"].onSelectionChanged:
162 self["menu"].onSelectionChanged.append(self.selectionChanged)
163 self.onLayoutFinish.append(self.showDeviceList)
164 self.onLayoutFinish.append(self.addPartitionListChange)
165 self.onClose.append(self.removePartitionListChange)
166 self.onChangedEntry = []
167 self.blockDevices = {}
169 def addPartitionListChange(self):
170 harddiskmanager.on_partition_list_change.append(self.partitionListChanged)
172 def removePartitionListChange(self):
173 harddiskmanager.on_partition_list_change.remove(self.partitionListChanged)
175 def partitionListChanged(self, action, device):
176 print "[Device manager] hotplug partitionListChanged"
177 if self.currList != "default" and device.device[:3] != self.currDevice["blockdev"]:
179 self.showDeviceList()
182 self.icon_button_green = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/buttons/button_green.png"))
183 self.divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
185 def selectionChanged(self):
186 if self.currList == "partitions":
187 currentPartition = self.getCurrentPartition()
188 if currentPartition is not None:
189 if currentPartition["mountpoint"] != "":
190 self["key_green"].setText(_("Umount"))
192 self["key_green"].setText(_("Mount"))
194 if currentPartition["fstype"] == "":
195 self["key_blue"].setText("")
196 elif currentPartition["fstype"][:3] == "ext":
197 self["key_blue"].setText(_("Check"))
199 self["key_blue"].setText("")
201 def showDeviceList(self):
203 self["key_red"].setText(_("Close"))
204 self["key_green"].setText(_("Ok"))
205 self["key_yellow"].setText(" ")
206 self["key_blue"].setText(_("Initialize"))
208 for device in deviceinfo.getBlockDevices():
210 "%s - %s"%(device["vendor"], device["model"]), # vendor : str, model : str, index 0
211 _("device : %s")%(device["blockdev"]), # str
212 _("Size : %s")%(byteConversion(device["size"])), # str, bytes
213 _("Partitions : %s")%(len(device["partitions"])), # list
214 _("Removable : %s")%(device["removable"] and 'Yes' or 'No'), # bool [True, False]
218 # print "[DeviceManager] deviceEntry : ", deviceEntry
219 self.deviceList.append(deviceEntry)
220 self.currList = "default"
221 self["menu"].style = "default"
222 self["menu"].setList(self.deviceList)
224 def showPartitionList(self):
225 if self.currDevice is None:
228 for partition in self.currDevice["partitions"]:
229 partitionInfo = deviceinfo.getPartitionInfo(partition)
231 _("Partition : /dev/%s")%partition, # index 0
232 _("Mounted on : %s")%checkStrValue(partitionInfo["mountpoint"], _("not mounted")),
233 _("UUID : %s")%checkStrValue(partitionInfo["uuid"], _("unknown")),
234 _("Type : %s")%checkStrValue(partitionInfo["fstype"], _("unknown")),
235 _("Size : %s")%checkStrValue(byteConversion(partitionInfo["size"]), _("unknown")),
236 _("Free : %s")%checkStrValue(byteConversion(partitionInfo["free"]), _("unknown")),
237 self.divpng, # index 6
238 partitionInfo, # index 7
240 # print "[DeviceManager] partitionEntry : ",partitionEntry
241 partitionList.append(partitionEntry)
242 if len(partitionList) != 0:
243 self["key_red"].setText(_("Devices"))
244 self["key_green"].setText(_("Mount"))
245 self["key_yellow"].setText(_("Format"))
246 self["key_blue"].setText(_("Check"))
247 self.currList = "partitions"
248 self["menu"].style = "partitions"
249 self["menu"].setList(partitionList)
250 self.selectionChanged()
252 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)
254 def showMountPointSetup(self):
255 if self.currDevice is None or self.currPartition is None:
257 partition = self.currPartition["partition"]
258 if deviceinfo.isMountable(partition) is False:
259 self.session.open(MessageBox, _("This partition is not mountable.\nYou need to check or format this partition."), MessageBox.TYPE_ERROR, timeout = 10)
261 self["key_red"].setText(_("Partitions"))
262 self["key_green"].setText(_("Ok"))
263 self["key_yellow"].setText("")
264 self["key_blue"].setText("")
265 self.mountPointList = []
266 currentMountPoint = self.currPartition["mountpoint"]
267 if currentMountPoint == "":
268 currentMountPoint = "'not mounted'"
269 defaultMountPoint = self.getDefaultMountPoint()
270 autoMountPoint = self.getAutoMountPoint()
271 defaultMountPointEntry = (self.icon_button_green, _("Set up Default Mount Point"), _("Mount Point : %s ->%s")%(currentMountPoint, defaultMountPoint), "default", defaultMountPoint, self.divpng)
272 autoMountPointEntry = (self.icon_button_green, _("Automatically set up a Mount Point"), _("Mount Point : %s -> %s")%(currentMountPoint, autoMountPoint), "auto", autoMountPoint, self.divpng)
273 manuallyMountPointEntry = (self.icon_button_green, _("User manually Set up a Mount Point"), _("Mount Point : click ok button on here."), "manual", "", self.divpng)
274 if not path.ismount(defaultMountPoint):
275 self.mountPointList.append(defaultMountPointEntry)
276 self.mountPointList.append(autoMountPointEntry)
277 self.mountPointList.append(manuallyMountPointEntry)
278 self.currList = "mountpoint"
279 self["menu"].style = "mountpoint"
280 self["menu"].setList(self.mountPointList)
282 def getCurrentDevice(self):
284 return self["menu"].getCurrent()[6]
288 def getCurrentPartition(self):
290 return self["menu"].getCurrent()[7]
296 if self.currList == "default":
297 self.currDevice = self.getCurrentDevice()
298 if self.currDevice is not None:
299 if len(self.currDevice["partitions"]) == 0:
300 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)
302 self.showPartitionList()
304 self.session.open(MessageBox, _("Device not found."), MessageBox.TYPE_ERROR, timeout = 10)
305 elif self.currList == "partitions":
306 currentPartition = self.getCurrentPartition()
307 if currentPartition is not None:
308 currMountPoint = currentPartition["mountpoint"]
309 currUuid = currentPartition["uuid"]
310 if currMountPoint == "":
311 self.currPartition = currentPartition
312 self.showMountPointSetup()
314 self.doUmount(currMountPoint, self.showPartitionList)
316 self.session.open(MessageBox, _("Partition info is not found."), MessageBox.TYPE_ERROR, timeout = 10)
317 elif self.currList == "mountpoint":
318 # self["menu"].getCurrent() : (green_button, "menu description", "mount point description, "default", mountpoint, self.divpng)
319 currEntry = self["menu"].getCurrent()[3]
320 if currEntry == "default":
321 # print "Setup mountpoint default!"
322 self.doMount(self.currPartition, self["menu"].getCurrent()[4])
323 elif currEntry == "auto":
324 # print "Setup mountpoint automatically!"
325 self.doMount(self.currPartition, self["menu"].getCurrent()[4])
327 # print "Setup mountpoint manually!"
328 self.session.openWithCallback(self.MountpointBrowserCB, MountpointBrowser)
334 if self.DeviceManagerConsole is not None:
335 if len(self.DeviceManagerConsole.appContainers):
336 for name in self.DeviceManagerConsole.appContainers.keys():
337 self.DeviceManagerConsole.kill(name)
338 if self.currList == "partitions":
339 self.currDevice = None
340 self.showDeviceList()
341 elif self.currList == "mountpoint":
342 self.currPartition = None
343 self.showPartitionList()
344 else: # currList = "default"
348 if self.currList == "partitions":
349 self.choiceBoxFstype()
352 if self.currList == "default":
353 device = self.getCurrentDevice()
354 if device is not None:
355 self.session.openWithCallback(self.deviceInitCB, DeviceInit, device["blockdev"], device["size"])
357 self.session.open(MessageBox, _("Device not found."), MessageBox.TYPE_ERROR, timeout = 10)
358 elif self.currList == "partitions":
359 partition = self.getCurrentPartition()
360 if partition is not None:
361 self.session.openWithCallback(self.deviceCheckCB, DeviceCheck, partition)
363 self.session.open(MessageBox, _("Partition info is not found."), MessageBox.TYPE_ERROR, timeout = 10)
366 self.session.open(DeviceManagerConfiguration)
368 def deviceInitCB(self, ret = True):
369 self.showDeviceList()
371 def deviceCheckCB(self, ret = True):
372 self.showPartitionList()
374 def deviceFormatCB(self, ret = True):
375 self.showPartitionList()
377 def choiceBoxFstype(self):
379 menu.append((_("ext2 - recommended for USB flash memory"), "ext2"))
380 menu.append((_("ext3 - recommended for harddisks"), "ext3"))
381 menu.append((_("ext4 - experimental"), "ext4"))
382 menu.append((_("vfat - for USB flash memory"), "vfat"))
383 self.session.openWithCallback(self.choiceBoxFstypeCB, ChoiceBox, title=_("Choice filesystem."), list=menu)
385 def choiceBoxFstypeCB(self, choice):
389 partition = self.getCurrentPartition()
390 if partition is not None:
391 self.session.openWithCallback(self.deviceFormatCB, DeviceFormat, partition, choice[1])
393 self.session.open(MessageBox, _("Partition info is not found."), MessageBox.TYPE_ERROR, timeout = 10)
395 # about mount funcs..
396 def doUmount(self, mountpoint, callback):
397 cmd = "umount %s"%mountpoint
398 print "[DeviceManager] cmd : %s"%cmd
400 if not path.ismount(mountpoint):
403 self.session.open(MessageBox, _("Can't umount %s. \nMaybe device or resource busy.")%mountpoint, MessageBox.TYPE_ERROR, timeout = 10)
406 def getDefaultMountPoint(self):
407 return self.defaultMountPoint
409 def getAutoMountPoint(self):
410 mountPoint = "/media/"+self.currDevice["model"]
411 mountPoint = mountPoint.replace(' ','-')
412 if path.ismount(mountPoint):
415 mountPoint_fix = mountPoint+str(partnum)
416 if not path.ismount(mountPoint_fix):
419 mountPoint = mountPoint_fix
422 def doMount(self, partition, mountpoint):
424 # check mountpoint is in partition list.
425 if mountpoint != self.getDefaultMountPoint():
426 for p in harddiskmanager.partitions:
427 if p.mountpoint == mountpoint:
428 self.session.open(MessageBox, _("Can not use this mount point.(%s) \nPlease select another mount point.")%mountpoint, MessageBox.TYPE_ERROR, timeout = 10)
431 device = partition["partition"]
432 filesystem = partition["fstype"]
433 uuid = partition["uuid"]
434 if mountpoint.endswith("/"):
435 mountpoint = retval[:-1]
436 if mountpoint.find(' ') != -1:
437 mountpoint = mountpoint.replace(' ','-')
438 devpath = "/dev/"+device
439 if deviceinfo.isMounted(devpath, mountpoint):
440 print "[DeviceManager] '%s -> %s' is already mounted."%(devpath, mountpoint)
443 # check current device mounted on another mountpoint.
444 mp_list = deviceinfo.checkMountDev(devpath)
446 if mp != mountpoint and path.ismount(mp):
447 deviceinfo.umountByMountpoint(mp)
448 # check another device mounted on configmountpoint
449 devpath_list = deviceinfo.checkMountPoint(mountpoint)
450 for devpath_ in devpath_list:
451 if devpath_ != devpath:
452 self.session.open(MessageBox, _("Mount Failed!\nCurrent path is already mounted by \"%s\"")%devpath_list[0], MessageBox.TYPE_ERROR, timeout = 10)
455 print "[DeviceManagerHotplugDevice] doMount"
456 if not path.exists(mountpoint):
457 os.system("mkdir %s"%mountpoint)
458 if path.exists(mountpoint):
459 if not path.ismount(mountpoint):
460 if filesystem == "ntfs":
461 cmd = "ntfs-3g %s %s"%(devpath, mountpoint)
462 elif filesystem is None:
463 cmd = "mount %s %s"%(devpath, mountpoint)
465 cmd = "mount -t %s %s %s"%(filesystem, devpath, mountpoint)
466 print "[DeviceManager] cmd : %s"%cmd
467 self.DeviceManagerConsole.ePopen(cmd, self.doMountFinished, (devpath, mountpoint) )
469 self.session.open(MessageBox, _("Mount Failed!\n(%s -> %s)")%(device, mountpoint), MessageBox.TYPE_ERROR, timeout = 10)
471 def doMountFinished(self, result, retval, extra_args = None):
472 (devpath, mountpoint) = extra_args
474 if not deviceinfo.isMounted(devpath, mountpoint):
475 # print "[DeviceManager] %s doMount failed!"%devpath
476 self.session.open(MessageBox, _("Mount Failed!\n(%s -> %s)")%(devpath, mountpoint), MessageBox.TYPE_ERROR, timeout = 10)
479 # make movie directory
480 if mountpoint == "/media/hdd":
481 movieDir = mountpoint + "/movie"
482 if not pathExists(movieDir):
483 print "[DeviceManager] make dir %s"%movieDir
484 os.makedirs(movieDir)
485 self.showPartitionList()
486 # update current mount state ,devicemanager.cfg
489 def MountpointBrowserCB(self, retval = None):
490 if retval and retval is not None:
491 mountPoint = retval.strip().replace(' ','')
492 if retval.endswith("/"):
493 mountPoint = retval[:-1]
494 print "Mount point from MountpointBrowser : %s"%mountPoint
495 if not path.exists(mountPoint):
496 self.session.open(MessageBox, _("Mount Point is not writeable.\nPath : %s")%mountPoint, MessageBox.TYPE_ERROR, timeout = 10)
499 self.doMount(self.currPartition, mountPoint)
502 # Initializing Start...
503 class DeviceInit(Screen):
504 skin = """<screen position="0,0" size="0,0"/>"""
505 def __init__(self, session, device, devicesize):
506 Screen.__init__(self, session)
507 self.session = session
508 self.deviceInitConsole = Console()
510 self.devicesize = int(devicesize)
511 self.inputbox_partitions = 1
512 self.inputbox_partitionSizeList = []
513 self.inputbox_partitionSizeTotal = int(self.devicesize/1024/1024)
514 self.msgWaiting = None
515 self.msgWaitingMkfs = None
516 self.devicenumber = 0
517 self.newpartitions = 0
518 self.onLayoutFinish.append(self.timerStart)
519 self.initStartTimer = eTimer()
520 self.initStartTimer.callback.append(self.confirmMessage)
521 self.createFSStartTimer = eTimer()
522 self.createFSStartTimer.callback.append(self.createFilesystemStart)
523 self.exitMessageTimer = eTimer()
524 self.exitMessageTimer.callback.append(self.exitMessage)
528 self.doMkfsTimer = eTimer()
529 self.doMkfsTimer.callback.append(self.doMkfs)
530 self.doInitializeTimer = eTimer()
531 self.doInitializeTimer.callback.append(self.doInitialize)
533 self.partitionType = "MBR"
535 self.inputbox_partitionSizeRemain = self.inputbox_partitionSizeTotal
537 self.onClose.append(enableUdevEvent)
539 def timerStart(self):
540 enableUdevEvent(False)
541 self.initStartTimer.start(100,True)
543 def confirmMessage(self):
544 message = _("Do you really want to initialize the device?\nAll data on the device will be lost!")
545 self.session.openWithCallback(self.confirmed, MessageBox, message)
547 def confirmed(self, ret):
549 self.InitializeStart()
553 def exit(self, ret = True):
556 def unmountAll(self, device):
557 mounts = file('/proc/mounts').read().split('\n')
561 if not line.startswith("/dev/" + device):
563 cmd += "umount %s ;"% line.split()[0]
564 print "[DeviceManager] %s"%cmd
567 mounts = file('/proc/mounts').read().split('\n')
569 if line.startswith("/dev/" + device):
573 def InitializeStart(self):
574 if self.devicesize >= ( 2.2 * 1000 * 1000 * 1000 * 1000 ): # 2.2TB
575 self.partitionType = "GPT"
577 self.inputbox_partitionSizeRemain = 100
580 self.InputPartitionSize_step1()
582 def InputPartitionSize_step1(self):
583 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)
585 def InputPartitionSize_step1_CB(self, ret):
586 if ret is not None and int(ret) in range(1,self.maxPartNum+1): # MBR 1~4, GPT 1~20
587 self.inputbox_partitions = int(ret)
588 self.InputPartitionSize_step2()
590 self.session.openWithCallback(self.exit, MessageBox, _("The number you entered is wrong!"), MessageBox.TYPE_ERROR, timeout = 10)
592 def InputPartitionSize_step2(self):
593 current_partition = len(self.inputbox_partitionSizeList)+1
594 if self.inputbox_partitionSizeRemain == 0:
595 self.choiceBoxFstype()
596 elif current_partition == self.inputbox_partitions:
597 self.inputbox_partitionSizeList.append(str(self.inputbox_partitionSizeRemain))
598 self.choiceBoxFstype()
600 text = str(int(self.inputbox_partitionSizeRemain/(self.inputbox_partitions-len(self.inputbox_partitionSizeList) )))
601 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)
603 def InputPartitionSize_step2_CB(self, ret):
605 if self.inputbox_partitionSizeRemain < int(ret) or int(ret) == 0:
606 self.InputPartitionSize_step2()
608 self.inputbox_partitionSizeList.append(str(ret))
609 self.inputbox_partitionSizeRemain -= int(ret)
610 self.InputPartitionSize_step2()
612 self.session.openWithCallback(self.exit ,MessageBox, _("The number you entered is wrong!"), MessageBox.TYPE_ERROR, timeout = 10)
614 def choiceBoxFstype(self):
616 menu.append((_("ext2 - recommended for USB flash memory"), "ext2"))
617 menu.append((_("ext3 - recommended for harddisks"), "ext3"))
618 menu.append((_("ext4 - experimental"), "ext4"))
619 menu.append((_("vfat - for USB flash memory"), "vfat"))
620 self.session.openWithCallback(self.choiceBoxFstypeCB, ChoiceBox, title=_("Choice filesystem."), list=menu)
622 def choiceBoxFstypeCB(self, choice):
626 self.fstype = choice[1]
627 if self.fstype not in ["ext2", "ext3", "ext4", "vfat"]:
630 self.initInitializeConfirm()
632 def initInitializeConfirm(self):
633 # print self.inputbox_partitionSizeList
635 for index in range(len(self.inputbox_partitionSizeList)):
636 print "partition %d : %s %s"%(index+1, str(self.inputbox_partitionSizeList[index]), self.unit)
637 partitionsInfo += "partition %d : %s %s\n"%(index+1, str(self.inputbox_partitionSizeList[index]), self.unit)
638 partitionsInfo += "filesystem type : %s"%(self.fstype)
639 self.session.openWithCallback(self.initInitializeConfirmCB, MessageBoxConfirm, _("%s\nStart Device Inititlization?") % partitionsInfo , MessageBox.TYPE_YESNO)
641 def initInitializeConfirmCB(self,ret):
643 self.initInitialize()
647 def initInitialize(self):
648 if not self.unmountAll(self.device):
649 self.session.openWithCallback(self.exit, MessageBox, _("umounting failed!Maybe some files in mount point are open"), MessageBox.TYPE_ERROR, timeout = 10)
651 msg = _("InitInitializing, please wait ...")
652 msg += _("\nDevice : %s")%self.device
653 msg += _("\nSize : %s MB\n")%self.inputbox_partitionSizeTotal
654 for index in range(len(self.inputbox_partitionSizeList)):
655 msg += _("\npartition %d : %s %s")%(index+1, str(self.inputbox_partitionSizeList[index]), self.unit)
656 self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
657 self.doInitializeTimer.start(500,True)
659 def doInitialize(self):
660 def CheckPartedVer():
661 cmd = 'parted --version'
662 lines = os.popen(cmd).readlines()
664 if l.find("parted (GNU parted)") != -1:
665 ver = l.split()[3].strip()
670 print "[DeviceManager] check parted version Failed!"
674 partitions = len(self.inputbox_partitionSizeList) # get num of partition
678 partedVer = CheckPartedVer()
679 if partedVer >= 2.1: # align option is supported in version 2.1 or later
680 setAlign = "--align optimal"
681 if self.devicesize < 1024 * 1000 * 1000: # 1GB
686 if self.partitionType == "GPT": # partition type is GPT
692 cmd = 'parted %s /dev/%s --script mklabel %s mkpart primary 0%% 100%%' % (setAlign, self.device, parttype)
693 else: # has multiple partitions
695 for p in range(partitions):
698 p_end = int( (long(self.inputbox_partitionSizeList[p]) * 100) / self.inputbox_partitionSizeTotal )
700 elif p > 0 and partitions > (p + 1):
702 p_end = int( (long(self.inputbox_partitionSizeList[p]) * 100) / self.inputbox_partitionSizeTotal )+ p_start
704 elif partitions == (p + 1):
713 set += 'mkpart primary ext2 %d%% %d%% ' % (p_start, p_end)
714 cmd = 'parted %s /dev/%s --script mklabel %s %s' % (setAlign, self.device, parttype, set)
716 self.deviceInitConsole.ePopen(cmd, self.initInitializeFinished)
718 def initInitializeFinished(self, result, retval, extra_args = None):
720 if self.partitionType == "MBR":
721 sfdiskVer = CheckSfdiskVer()
722 if sfdiskVer < 2.26: # sfdisk -R option is deprecated at sfdiskVer >= 2.26
723 cmd = 'sfdisk -R /dev/%s; sleep 5' % (self.device)
724 elif path.exists('/usr/sbin/partprobe'):
725 cmd = 'partprobe /dev/%s; sleep 5' % (self.device)
726 elif path.exists('/usr/sbin/partx'):
727 cmd = 'partx -u /dev/%s; sleep 5' % (self.device)
729 cmd = 'sfdisk -R /dev/%s; sleep 5' % (self.device)
732 self.deviceInitConsole.ePopen(cmd, self.initInitializingRefreshFinished)
734 errorMsg = "initInitializing device Error at /dev/%s"%self.device
735 self.msgWaiting.run_close(False, errorMsg)
737 def initInitializingRefreshFinished(self, result, retval, extra_args = None):
738 cmd = "/bin/umount /dev/%s*" % (self.device)
739 self.deviceInitConsole.ePopen(cmd, self.initInitializingUmountFinished)
741 def initInitializingUmountFinished(self, result, retval, extra_args = None):
742 partitions = open("/proc/partitions")
743 self.devicenumber = 0
744 self.newpartitions = 0
745 for part in partitions:
746 res = re.sub("\s+", " ", part).strip().split(" ")
747 if res and len(res) == 4 and res[3][:3] == self.device:
748 if len(res[3]) > 3 and res[3][:2] == "sd":
749 self.newpartitions += 1
751 partNum = len(self.inputbox_partitionSizeList) # get num of partition
752 if self.newpartitions != partNum:
753 errorMsg = "Partitioning device Error at /dev/%s"%self.device
754 self.msgWaiting.run_close(False, errorMsg)
756 self.msgWaiting.run_close(True)
757 # self.createFilesystem(self.newpartitions)
759 def createFilesystem(self, newpartitions):
760 self.devicenumber = self.devicenumber + 1
761 fulldevicename = "/dev/" + self.device + str(self.devicenumber)
762 shortdevicename = self.device + str(self.devicenumber)
764 partitions = open("/proc/partitions")
765 for part in partitions:
766 res = re.sub("\s+", " ", part).strip().split(" ")
767 if res and len(res) == 4:
768 if res[3] == shortdevicename:
769 partitionsize = int(res[2])
773 if self.fstype == "ext4":
774 cmd = "mkfs.ext4 -F "
775 if partitionsize > 2 * 1024 * 1024: # 2GB
776 cmd += "-T largefile "
777 cmd += "-O extent,flex_bg,large_file,uninit_bg -m1 " + fulldevicename
778 elif self.fstype == "ext3":
779 cmd = "mkfs.ext3 -F "
780 if partitionsize > 2 * 1024 * 1024:
781 cmd += "-T largefile "
782 cmd += "-m0 " + fulldevicename
783 elif self.fstype == "ext2":
784 cmd = "mkfs.ext2 -F "
785 if partitionsize > 2 * 1024 * 1024:
786 cmd += "-T largefile "
787 cmd += "-m0 " + fulldevicename
788 elif self.fstype == "vfat":
789 if partitionsize > 4 * 1024 * 1024 * 1024:
790 cmd = "mkfs.vfat -I -S4096 " + fulldevicename
792 cmd = "mkfs.vfat -I " + fulldevicename
793 if partitionsize > 2 * 1024 * 1024: # if partiton size larger then 2GB, use FAT32
797 self.createFilesystemFinished(None, -1, (self.device, fulldevicename))
800 msg = _("Create filesystem, please wait ...")
801 msg += _("\nPartition : %s") % (fulldevicename)
802 msg += _("\nFilesystem : %s") % (self.fstype)
803 msg += _("\nDisk Size : %s MB") % (self.inputbox_partitionSizeTotal)
804 msg += _("\nPartition Size : %d %s\n") % (int(self.inputbox_partitionSizeList[self.devicenumber-1]), self.unit)
805 self.msgWaitingMkfs = self.session.openWithCallback(self.msgWaitingMkfsCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
807 self.doMkfsTimer.start(500,True)
810 fulldevicename = "/dev/" + self.device + str(self.devicenumber)
811 self.deviceInitConsole.ePopen(self.mkfs_cmd, self.createFilesystemFinished, (self.device, fulldevicename))
813 def createFilesystemFinished(self, result, retval, extra_args = None):
814 device = extra_args[0]
815 fulldevicename = extra_args[1]
817 self.msgWaitingMkfs.run_close(True)
819 errorMsg = _("Creating filesystem Error")
820 if fulldevicename is not None:
821 errorMsg += _(" at /dev/%s")%fulldevicename
822 self.msgWaitingMkfs.run_close(False, errorMsg)
824 def createFilesystemStart(self):
825 self.createFilesystem(self.newpartitions)
827 def msgWaitingCB(self, ret, msg=""):
829 self.createFSStartTimer.start(100,True)
833 self.exitMessageTimer.start(100,True)
835 def msgWaitingMkfsCB(self, ret, msg=""):
836 if self.devicenumber < self.newpartitions:
837 self.createFSStartTimer.start(100,True)
841 self.msg = _("Device Initialization finished sucessfully!")
842 self.exitMessageTimer.start(100,True)
846 self.exitMessageTimer.start(100,True)
848 def exitMessage(self):
850 self.session.openWithCallback(self.exit, MessageBox, self.msg, MessageBox.TYPE_INFO, timeout = 10)
852 self.session.openWithCallback(self.exit, MessageBox, self.msg, MessageBox.TYPE_ERROR, timeout = 10)
856 # device check start..
857 class DeviceCheck(Screen):
858 skin = """<screen position="0,0" size="0,0"/>"""
859 def __init__(self, session, partition):
860 Screen.__init__(self, session)
861 self.session = session
862 self.deviceCheckConsole = Console()
863 self.partition = partition
864 self.onLayoutFinish.append(self.timerStart)
865 self.checkStartTimer = eTimer()
866 self.checkStartTimer.callback.append(self.confirmMessage)
867 self.umountTimer = eTimer()
868 self.umountTimer.callback.append(self.doUnmount)
870 def timerStart(self):
871 self.checkStartTimer.start(100,True)
873 def confirmMessage(self):
874 fssize = self.partition["size"]
875 if long(fssize) > 1024*1024*1024*16:
876 message = _("Do you really want to check the filesystem?\nThis could take lots of time!")
877 self.session.openWithCallback(self.confirmed, MessageBox, message)
879 self.deviceCheckStart()
881 def confirmed(self, ret):
882 print "confirmed : ",ret
884 self.deviceCheckStart()
888 def deviceCheckStart(self):
889 print "deviceCheckStart "
890 print "partition : ", self.partition
891 device = self.partition["partition"]
892 fstype = self.partition["fstype"]
893 fssize = self.partition["size"]
894 if device is not None and fstype.startswith("ext"):
895 msg = _("Check filesystem, please wait ...")
896 msg += _("\nDevice : /dev/%s")%(device)
897 msg += _("\nFilesystem : %s")%(fstype)
898 self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox.TYPE_INFO, enable_input = False)
899 self.umountTimer.start(500,True)
904 device = self.partition["partition"]
905 mountpoint = self.partition["mountpoint"]
906 fstype = self.partition["fstype"]
908 self.doUmountFsck(device, mountpoint, fstype)
910 self.umountFsckFinished("NORESULT", 0, (device, mountpoint, fstype))
912 def doUmountFsck(self, device, mountpoint, fstype):
913 cmd = "umount /dev/%s" % device
914 self.deviceCheckConsole.ePopen(cmd, self.umountFsckFinished, (device, mountpoint, fstype))
916 def umountFsckFinished(self, result, retval, extra_args = None):
917 device = extra_args[0]
918 mountpoint = extra_args[1]
919 fstype = extra_args[2]
921 cmd = "fsck." + fstype + " -f -p /dev/" + device
922 self.deviceCheckConsole.ePopen(cmd, self.fsckFinished, extra_args)
924 errorMsg = _("Can not umount device /dev/%s.\nMaybe some files of the filesystem are open")%device
925 self.msgWaiting.run_close(False,errorMsg)
927 def fsckFinished(self, result, retval, extra_args = None):
928 device = extra_args[0]
929 mountpoint = extra_args[1]
931 text = _("Filesystem check finished sucessfully")
932 self.msgWaiting.run_close(True, text)
934 text = _("Error checking disk. The disk or filesystem may be damaged")
935 self.msgWaiting.run_close(False, text)
937 def msgWaitingCB(self, ret, msg):
939 self.session.open(MessageBox, msg, MessageBox.TYPE_INFO, timeout = 10)
941 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 10)
943 partition = self.partition["partition"]
944 mountpoint = self.partition["mountpoint"]
945 fstype = self.partition["fstype"]
948 cmd = "ntfs-3g /dev/" + partition + " " + mountpoint
950 cmd = "mount /dev/" + partition + " " + mountpoint
951 self.deviceCheckConsole.ePopen(cmd, self.mountPartitionFinished)
955 def mountPartitionFinished(self, result, retval, extra_args = None):
964 class DeviceFormat(Screen):
965 skin = """<screen position="0,0" size="0,0"/>"""
966 def __init__(self, session, partition, newfstype):
967 Screen.__init__(self, session)
968 self.session = session
969 self.deviceFormatConsole = Console()
970 self.partition = partition
971 self.newfstype = newfstype
972 self.unmountedList = []
973 self.onLayoutFinish.append(self.timerStart)
974 self.formatStartTimer = eTimer()
975 self.formatStartTimer.callback.append(self.DeviceFormatStart)
976 self.umountTimer = eTimer()
977 self.umountTimer.callback.append(self.doUnmount)
978 self.onClose.append(enableUdevEvent)
980 def timerStart(self):
981 enableUdevEvent(False)
982 self.formatStartTimer.start(100,True)
984 def DeviceFormatStart(self):
985 print "DeviceFormatStart : ", self.partition,
986 print "Filesystem : ",self.newfstype
987 device = self.partition["partition"]
988 devicepath = "/dev/"+device
989 fssize = self.partition["size"]
990 newfstype = self.newfstype
991 msg = _("Format filesystem, please wait ...")
992 msg += _("\nDevice : %s")%(devicepath)
993 msg += _("\nFilesystem : %s")%(newfstype)
994 msg += _("\nSize : %s")%(byteConversion(fssize))
995 self.msgWaiting = self.session.openWithCallback(self.msgWaitingCB, MessageBox_2, msg, type = MessageBox_2.TYPE_INFO, enable_input = False, msgBoxID = None)
996 self.umountTimer.start(500,True)
999 mountpoint = self.partition["mountpoint"]
1000 if mountpoint != "":
1001 self.doumountPartition()
1003 self.umountPartitionFinished("NORESULT", 0)
1005 def doumountPartition(self):
1006 oldfstype = self.partition["fstype"]
1007 newfstype = self.newfstype
1009 if newfstype == oldfstype:
1010 device = self.partition["partition"]
1012 device = self.partition["partition"][:3]
1014 mounts = file('/proc/mounts','r')
1015 for line in mounts.readlines():
1016 if line.startswith("/dev/%s"%device):
1017 cmd += "umount %s;"%line.split()[0]
1018 self.unmountedList.append([line.split()[0], line.split()[1]])
1019 self.deviceFormatConsole.ePopen(cmd, self.umountPartitionFinished)
1021 def umountPartitionFinished(self, result, retval, extra_args = None):
1022 partition = self.partition["partition"]
1023 oldfstype = self.partition["fstype"]
1024 newfstype = self.newfstype
1026 if oldfstype == newfstype:
1027 self.changePartitionIDFinished("NORESULT", 0)
1029 sfdiskVer = CheckSfdiskVer()
1030 if sfdiskVer >= 2.26:
1031 cmd = "sfdisk --part-type /dev/%s %s" % (partition[:3], partition[3:])
1033 cmd = "sfdisk --change-id /dev/%s %s" % (partition[:3], partition[3:])
1035 if newfstype[:3] == "ext":
1039 self.deviceFormatConsole.ePopen(cmd, self.changePartitionIDFinished)
1041 errorMsg = _("Can not umount device /dev/%s.\nMaybe some files of the filesystem are open")%partition[:3]
1042 self.msgWaiting.run_close(False,errorMsg)
1044 def changePartitionIDFinished(self, result, retval, extra_args = None):
1045 device = self.partition["partition"][:3]
1046 mountpoint = self.partition["mountpoint"]
1047 oldfstype = self.partition["fstype"]
1048 newfstype = self.newfstype
1050 if oldfstype == newfstype:
1051 self.refreshPartitionFinished("NORESULT", 0)
1053 sfdiskVer = CheckSfdiskVer()
1054 if sfdiskVer < 2.26: # sfdisk -R option is deprecated at sfdiskVer >= 2.26
1055 cmd = "sfdisk -R /dev/%s; sleep 5" % (device)
1056 elif path.exists('/usr/sbin/partprobe'):
1057 cmd = 'partprobe /dev/%s; sleep 5' % (device)
1058 elif path.exists('/usr/sbin/partx'):
1059 cmd = 'partx -u /dev/%s; sleep 5' % (device)
1061 cmd = "sfdisk -R /dev/%s; sleep 5" % (device)
1063 self.deviceFormatConsole.ePopen(cmd, self.refreshPartitionFinished)
1065 if result and result.find("Use GNU Parted") > 0:
1066 print "[DeviceManager] /dev/%s use GNU Parted!" % device
1067 self.refreshPartitionFinished("NORESULT", 0)
1069 errorMsg = _("Can not change the partition ID for %s")%device
1070 self.msgWaiting.run_close(False,errorMsg)
1072 def refreshPartitionFinished(self, result, retval, extra_args = None):
1073 print "refreshPartitionFinished!"
1074 partition = self.partition["partition"]
1075 mountpoint = self.partition["mountpoint"]
1076 size = int(self.partition["size"])/1024/1024
1077 oldfstype = self.partition["fstype"]
1078 newfstype = self.newfstype
1080 if newfstype == "ext4":
1081 cmd = "mkfs.ext4 -F "
1083 cmd += "-T largefile "
1084 cmd += "-O extent,flex_bg,large_file,uninit_bg -m1 /dev/" + partition
1085 elif newfstype == "ext3":
1086 cmd = "mkfs.ext3 -F "
1088 cmd += "-T largefile "
1089 cmd += "-m0 /dev/" + partition
1090 elif newfstype == "ext2":
1091 cmd = "mkfs.ext2 -F "
1093 cmd += "-T largefile "
1094 cmd += "-m0 /dev/" + partition
1095 elif newfstype == "vfat":
1096 if size > 4 * 1024 * 1024:
1097 cmd = "mkfs.vfat -I -S4096 /dev/" + partition
1099 cmd = "mkfs.vfat -I /dev/" + partition
1100 if size > 2 * 1024: # if partiton size larger then 2GB, use FAT32
1102 self.deviceFormatConsole.ePopen(cmd, self.mkfsFinished)
1104 errorMsg = _("Can not format device /dev/%s.\nrefresh partition information failed!")%partition
1105 self.msgWaiting.run_close(False,errorMsg)
1107 def mkfsFinished(self, result, retval, extra_args = None):
1108 print "mkfsFinished!"
1109 partition = self.partition["partition"]
1112 if len(self.unmountedList) == 0:
1113 self.doMountFinished("NORESULT",0)
1114 for x in self.unmountedList:
1115 cmd += "mount %s %s;"%(x[0], x[1])
1116 self.deviceFormatConsole.ePopen(cmd, self.doMountFinished)
1118 text = _("Make filesystem Error /dev/%s.\nPlease check your device.")%partition
1119 self.msgWaiting.run_close(False, text)
1121 def doMountFinished(self, result, retval, extra_args = None):
1122 print "doMountFinished!"
1123 text = _("Format finished sucessfully.")
1124 self.msgWaiting.run_close(True, text)
1126 def msgWaitingCB(self, ret, msg):
1128 self.session.openWithCallback(self.exit, MessageBox, msg, MessageBox.TYPE_INFO, timeout = 10)
1130 self.session.openWithCallback(self.exit, MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 10)
1132 def exit(self, ret):
1139 self.blockDeviceList = []
1141 def getBlockDevices(self):
1142 return self.blockDeviceList
1145 self.blockDeviceList = []
1146 self.getBlockDeviceList()
1148 def getBlockDeviceList(self):
1149 print "get block device Infomations..."
1150 for blockdev in listdir("/sys/block"):
1151 (error, blacklisted, removable, partitions, size, model, vendor) = self.getBlockDeviceInfo(blockdev)
1152 if not blacklisted and not error:
1153 # print "%s : error %s, blacklisted %s, removable %s, partitions %s, size %s"%(blockdev, error, blacklisted, removable, partitions, size)
1155 blockDevice["blockdev"] = blockdev # str
1156 blockDevice["removable"] = removable # bool [True, False]
1157 blockDevice["partitions"] = partitions # list
1158 blockDevice["size"] = size # str
1159 blockDevice["model"] = model # str
1160 blockDevice["vendor"] = vendor # str
1161 self.blockDeviceList.append(blockDevice)
1163 def SortPartList(self, partList):
1164 length = len(partList)-1
1166 while sorted is False:
1168 for idx in range(length):
1169 if int(partList[idx][3:]) > int(partList[idx+1][3:]):
1171 partList[idx] , partList[idx+1] = partList[idx+1], partList[idx]
1173 def getBlockDeviceInfo(self, blockdev):
1174 devpath = "/sys/block/" + blockdev
1183 dev = int(readFile(devpath + "/dev").split(':')[0])
1184 if dev in (7, 31) or blockdev[0:2] != 'sd': # 7: loop, 31 : mtdblock
1186 return error, blacklisted, removable, partitions, size, model, vendor
1187 removable = bool(int(readFile(devpath + "/removable")))
1188 size = str(int(readFile(devpath + "/size").strip())*512)
1189 model = readFile(devpath + "/device/model")
1190 vendor = readFile(devpath + "/device/vendor")
1191 for partition in listdir(devpath):
1192 if partition[:len(blockdev)] != blockdev:
1194 partitions.append(partition)
1195 self.SortPartList(partitions)
1199 return error, blacklisted, removable, partitions, size, model, vendor
1201 def getPartitionInfo(self, partition):
1202 mountPoint = self.getPartitionMountpoint(partition)
1203 (uuid , fsType) = self.getPartitionBlkidInfo(partition)
1204 size_total = self.getPartitionSize(partition)
1206 if mountPoint != "":
1207 size_free = self.getPartitionFree(mountPoint)
1209 partitionInfo["partition"] = partition
1210 partitionInfo["mountpoint"] = mountPoint
1211 partitionInfo["uuid"] = uuid
1212 partitionInfo["fstype"] = fsType
1213 partitionInfo["size"] = size_total
1214 partitionInfo["free"] = size_free
1215 return partitionInfo
1217 def getPartitionMountpoint(self, partition):
1218 mounts = file('/proc/mounts').read().split('\n')
1220 if not x.startswith('/'):
1222 devpath, mountpoint, = x.split()[:2]
1223 if mountpoint.startswith('/autofs'):
1225 if path.basename(devpath) == partition:
1229 def getPartitionBlkidInfo(self, partition):
1230 parttionDev = "/dev/"+str(partition)
1233 cmd = "blkid -c /dev/null "+str(parttionDev)
1235 line = popen(cmd).readline().strip()
1236 if not line.startswith(parttionDev):
1237 return (uuid, partitionType)
1238 # print "Blikd %s : %s"%(parttionDev, line)
1239 if line.find(" UUID=") != -1:
1240 uuid = line.split(" UUID=")[1].split(' ')[0]
1241 if line.find(" TYPE=") != -1:
1242 partitionType = line.split(" TYPE=")[1].split(' ')[0].strip('"')
1244 print "get blkid info error (%s)"%cmd
1245 return (uuid, partitionType)
1247 def getPartitionSize(self, partition):
1248 devpath = "/sys/block/%s/%s"%( str(partition[:3]), str(partition) )
1250 size = readFile(devpath + "/size")
1251 return str(int(size)*512)
1255 def getPartitionFree(self, mountPoint):
1257 stat = statvfs(mountPoint)
1258 size_free = stat.f_bfree*stat.f_bsize
1263 def checkMountPoint(self, check_mountpoint):
1266 mounts = file('/proc/mounts').read().split('\n')
1268 if not x.startswith('/'):
1270 devpath, mountpoint = x.split()[:2]
1271 if mountpoint == check_mountpoint:
1277 def checkMountDev(self, device):
1280 mounts = file('/proc/mounts').read().split('\n')
1282 if not x.startswith('/'):
1284 devpath, mountpoint = x.split()[:2]
1285 if devpath == device:
1286 res.append(mountpoint)
1291 def isMounted(self, devpath, mountpoint):
1293 mounts = file('/proc/mounts').readlines()
1295 if not x.startswith('/'):
1297 _devpath, _mountpoint = x.split()[:2]
1298 if devpath == _devpath and mountpoint == _mountpoint:
1304 def isMounted_anymp(self, devpath):
1306 mounts = open('/proc/mounts', 'r').readlines()
1308 if not x.startswith('/'):
1310 _devPart, _mountpoint = x.split()[:2]
1311 if devpath == _devPart:
1317 # check partition type is extended or swap.
1318 def checkSwapExtended(self, partition):
1319 blockName = partition[:-1]
1320 partNum = partition[-1]
1321 data = os.popen("parted /dev/%s print" % blockName).readlines()
1323 info = x.strip().split()
1325 if len(info) > 0 and info[0] == str(partNum):
1326 if len(info) >= 5 and info[4].find('extended') != -1: # check Type is extended
1328 elif len(info) >= 6 and info[5].find('swap') != -1: # check File System is swap
1333 def isMountable(self, partition):
1334 if self.checkSwapExtended(partition):
1338 if self.isMounted_anymp('/dev/'+partition):
1341 elif os.access('/autofs/'+partition, 0):
1347 def isFstabAutoMounted(self, uuid, devpath, mountpoint):
1348 # print " >> isFstabMounted, uuid : %s, devpath : %s, mountpoint : %s"%(uuid, devpath, mountpoint)
1349 if mountpoint[-1] == '/':
1350 mountpoint = mountpoint[:-1]
1351 data = file('/etc/fstab').read().split('\n')
1353 if not line.startswith('/'):
1355 dev, mp, ms = line.split()[0:3]
1356 if uuid is not None and dev.startswith('UUID'):
1357 if dev.split('=')[1] == uuid.strip("\"") and mp == mountpoint and ms == 'auto':
1358 # print " >> line : ", line
1360 elif dev == devpath and mp == mountpoint and ms == 'auto':
1361 # print " >> line : ", line
1365 def umountByMountpoint(self, mountpoint):
1366 if mountpoint is None:
1369 if path.ismount(mountpoint):
1370 cmd = "umount " + mountpoint
1371 print "[DeviceManager] ", cmd
1374 print "Umount by mountpoint failed!"
1375 if not path.ismount(mountpoint):
1379 def umountByDevpath(self, devpath):
1380 cmd = "umount " + devpath
1381 print "[DeviceManager] ", cmd
1384 deviceinfo = DeviceInfo()
1386 class MountpointBrowser(Screen):
1388 <screen name="MountpointBrowser" position="center,120" size="670,500" title="Select mountpoint">
1389 <ePixmap pixmap="skin_default/buttons/red.png" position="20,0" size="140,40" alphatest="on" />
1390 <ePixmap pixmap="skin_default/buttons/green.png" position="180,0" size="140,40" alphatest="on" />
1391 <ePixmap pixmap="skin_default/buttons/yellow.png" position="340,0" size="140,40" alphatest="on" />
1392 <ePixmap pixmap="skin_default/buttons/blue.png" position="500,0" size="140,40" alphatest="on" />
1393 <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" />
1394 <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" />
1395 <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" />
1396 <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" />
1397 <eLabel position="10,50" size="650,1" backgroundColor="#b3b3b9"/>
1398 <widget name="filelist" position="10,60" size="650,440" itemHeight="30" scrollbarMode="showOnDemand"/>
1401 def __init__(self, session):
1402 Screen.__init__(self, session)
1403 self["key_red"] = StaticText(_("Cancel"))
1404 self["key_green"] = StaticText(_("Select"))
1405 self["key_yellow"] = StaticText(_("Create directory"))
1406 self["key_blue"] = StaticText("Delete directory")
1407 directory = "/media/"
1408 inhibitDirs = ["/autofs", "/mnt", "/hdd", "/bin", "/boot", "/dev", "/etc", "/home", "/lib", "/proc", "/sbin", "/share", "/sys", "/tmp", "/usr", "/var"]
1409 self.filelist = FileList(directory, matchingPattern="", inhibitDirs = inhibitDirs)
1410 self["filelist"] = self.filelist
1412 self["shortcuts"] = ActionMap(["ColorActions"],
1415 "green": self.select,
1416 "yellow": self.createDirectory,
1417 "blue": self.deleteDirectory,
1420 self["OkCancelActions"] = ActionMap(["OkCancelActions"],
1422 "cancel": self.exit,
1427 if self.filelist.canDescent():
1428 self.filelist.descent()
1431 if self["filelist"].getCurrentDirectory() is not None:
1432 if self.filelist.canDescent() and self["filelist"].getFilename() and self["filelist"].getFilename().startswith(self["filelist"].getCurrentDirectory()):
1433 self.filelist.descent()
1434 currDir = self["filelist"].getCurrentDirectory()
1437 self.close(self["filelist"].getFilename())
1439 def createDirectory(self):
1440 self.session.openWithCallback(self.createDirectoryCB, VirtualKeyBoard, title = (_("Input mount point path.")), text = "")
1442 def createDirectoryCB(self, retval = None):
1445 if retval is not None:
1446 newdir = self["filelist"].getCurrentDirectory()+'/'+retval
1447 if not path.exists(newdir):
1448 os.system("mkdir %s"%newdir)
1449 self.filelist.refresh()
1452 self.session.open(MessageBox, _("Create directory failed!\n%s")%newdir, MessageBox.TYPE_ERROR, timeout = 10)
1454 def deleteDirectory(self):
1457 if self["filelist"].getCurrentDirectory() is not None:
1458 if self.filelist.canDescent() and self["filelist"].getFilename() and self["filelist"].getFilename().startswith(self["filelist"].getCurrentDirectory()):
1459 delDir = self["filelist"].getFilename()
1460 if path.exists(delDir):
1461 os.system("rmdir '%s'"%delDir)
1462 if path.exists(delDir):
1463 self.session.open(MessageBox, _("Delete directory failed!\nMaybe directory is not empty."), MessageBox.TYPE_ERROR, timeout = 10)
1464 self.filelist.refresh()
1467 self.session.open(MessageBox, _("Delete directory failed!\n%s")%newdir, MessageBox.TYPE_ERROR, timeout = 10)
1472 class MessageBoxConfirm(MessageBox):
1474 <screen position="center,center" size="620,10" title="Message">
1475 <widget name="text" position="65,8" size="420,0" font="Regular;20" />
1476 <widget name="ErrorPixmap" pixmap="skin_default/icons/input_error.png" position="5,5" size="53,53" alphatest="blend" />
1477 <widget name="QuestionPixmap" pixmap="skin_default/icons/input_question.png" position="5,5" size="53,53" alphatest="blend" />
1478 <widget name="InfoPixmap" pixmap="skin_default/icons/input_info.png" position="5,5" size="53,53" alphatest="blend" />
1479 <widget name="list" position="100,100" size="380,375" transparent="1" />
1480 <applet type="onLayoutFinish">
1481 # this should be factored out into some helper code, but currently demonstrates applets.
1482 from enigma import eSize, ePoint
1484 orgwidth = self.instance.size().width()
1485 orgheight = self.instance.size().height()
1486 orgpos = self.instance.position()
1487 textsize = self["text"].getSize()
1489 # y size still must be fixed in font stuff...
1490 textsize = (textsize[0] + 50, textsize[1] + 50)
1492 if self.type == self.TYPE_YESNO:
1494 wsizex = textsize[0] + 60
1495 wsizey = textsize[1] + offset
1496 if (280 > wsizex):
1498 wsize = (wsizex, wsizey)
1501 self.instance.resize(eSize(*wsize))
1504 self["text"].instance.resize(eSize(*textsize))
1507 listsize = (wsizex, 50)
1508 self["list"].instance.move(ePoint(0, textsize[1]))
1509 self["list"].instance.resize(eSize(*listsize))
1513 newheight = wsize[1]
1514 self.instance.move(ePoint(orgpos.x() + (orgwidth - newwidth)/2, orgpos.y() + (orgheight - newheight)/2))
1519 dmconfigfile = resolveFilename(SCOPE_PLUGINS, "SystemPlugins/DeviceManager/devicemanager.cfg")
1521 def callBackforDeviceManager(session, callback_result = False):
1522 if callback_result == True:
1523 session.open(DeviceManager)
1525 def checkMounts(session):
1527 noMountable_dev = ""
1528 for blockdev in listdir("/sys/block"):
1529 devpath = "/sys/block/" + blockdev
1530 dev = int(readFile(devpath + "/dev").split(':')[0])
1531 if dev in (7, 31) or blockdev[0:2] != 'sd': # 7: loop, 31 : mtdblock
1534 noMountable_partitions = []
1535 for partition in listdir(devpath):
1536 if not partition.startswith(blockdev):
1539 if deviceinfo.checkSwapExtended(partition):
1542 partitions.append(partition)
1544 if deviceinfo.isMounted_anymp('/dev/' + partition):
1547 if os.access('/autofs/'+partition, 0) is False:
1548 noMountable_partitions.append(partition)
1550 if len(partitions) == 0 or len(noMountable_partitions) != 0:
1551 if noMountable_dev != "":
1552 noMountable_dev += ' '
1553 noMountable_dev += blockdev
1555 if noMountable_dev != "":
1556 print "Umountable partitions found."
1557 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
1558 AddNotificationWithCallback(
1559 boundFunction(callBackforDeviceManager, session),
1560 MessageBox, InfoText, timeout = 60, default = False
1563 print "checkMounts failed!"
1565 def sessionstart(reason, **kwargs):
1567 if kwargs.has_key("session") and config.plugins.devicemanager.mountcheck_enable.value == True:
1568 session = kwargs["session"]
1569 checkMounts(session)
1573 def autostart(reason, **kwargs):
1576 # at first enigma2 start
1577 if config.misc.firstrun.value:
1578 print "[DeviceManager] autostart : check devices at first start"
1579 if not path.exists("/media/hdd"):
1580 cmd = "mkdir -p /media/hdd"
1584 print "[DeviceManager] autostart failed!"
1588 def menu(menuid, **kwargs):
1589 if menuid == "system":
1590 return [(_("DeviceManager"), main, "device_manager", 50)]
1593 def main(session, **kwargs):
1594 session.open(DeviceManager)
1596 def Plugins(path, **kwargs):
1598 PluginDescriptor(name = _("DeviceManager"), description = _("manage block devices of your VU+"), where = PluginDescriptor.WHERE_MENU,fnc=menu),
1599 PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, needsRestart = True, fnc = sessionstart),
1600 PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, needsRestart = True, fnc = autostart)
1603 class MessageBox_2(MessageBox):
1604 def __init__(self, session, text, type = MessageBox.TYPE_YESNO, timeout = -1, close_on_any_key = False, default = True, enable_input = True, msgBoxID = None):
1605 MessageBox.__init__(self, session, text, type, timeout, close_on_any_key, default, enable_input, msgBoxID)
1606 self.skinName = "MessageBox"
1607 self.closeTimer = eTimer()
1608 self.closeTimer.callback.append(self.msg_close)
1609 self.devicemanager_ret = False
1610 self.devicemanager_msg = ""
1612 def msg_close(self):
1613 self.close(self.devicemanager_ret, self.devicemanager_msg)
1615 def run_close(self, ret, msg=""):
1616 self.devicemanager_ret = ret
1617 self.devicemanager_msg = msg
1618 self.closeTimer.start(100,True)
1620 def createSummary(self):
1621 return MessageBox_2_Summary
1623 class MessageBox_2_Summary(Screen):
1625 <screen name="MessageBox_2_Summary" position="0,0" size="256,64" id="1">
1626 <widget source="parent.Text" render="Label" position="0,0" size="256,64" font="Regular;13" halign="center" valign="center" />