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
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.hotplug_enable = ConfigEnableDisable(default=True)
36 config.plugins.devicemanager.mountcheck_enable = ConfigEnableDisable(default=True)
38 def readFile(filename):
40 data = file.read().strip()
44 def byteConversion(byte):
45 if type(byte) == str and len(byte) == 0:
47 if type(byte) != long:
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)
54 int_part = byte/1024/1024
55 dec_part = byte%(1024*1024)/1024
56 return "%d.%d MB"%(int_part, dec_part)
58 def checkStrValue(value , empty = ""):
59 if type(value) != str or len(value) == 0:
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" ],
75 "cancel": self.keyCancel,
76 "red": self.keyCancel,
77 "green": self.keySave,
79 self.onShown.append(self.setWindowTitle)
80 self.old_hotplug_enable = config.plugins.devicemanager.hotplug_enable.value
82 def setWindowTitle(self):
83 self.setTitle(_("DeviceManager configuration"))
85 def createConfigList(self):
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))
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)
96 if DeviceManagerhotplugDeviceStart in harddiskmanager.on_partition_list_change:
97 harddiskmanager.on_partition_list_change.remove(DeviceManagerhotplugDeviceStart)
99 for x in self["config"].list:
103 class DeviceManager(Screen):
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">
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
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
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
142 "fonts": [gFont("Regular", 22),gFont("Regular", 16),gFont("Regular", 28)],
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"
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(" ")
164 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions", "MenuActions" ],
167 "cancel": self.keyCancel,
168 "red": self.keyCancel,
170 "yellow": self.keyYellow,
171 "blue": self.keyBlue,
172 "menu": self.keyMenu,
174 self.DeviceManagerConsole = Console()
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 = {}
184 def addPartitionListChange(self):
185 harddiskmanager.on_partition_list_change.append(self.partitionListChanged)
187 def removePartitionListChange(self):
188 harddiskmanager.on_partition_list_change.remove(self.partitionListChanged)
190 def partitionListChanged(self, action, device):
191 print "[Device manager] hotplug partitionListChanged"
192 if self.currList != "default" and device.device[:3] != self.currDevice["blockdev"]:
194 self.showDeviceList()
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"))
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"))
207 self["key_green"].setText(_("Mount"))
209 if currentPartition["fstype"] == "":
210 self["key_blue"].setText("")
211 elif currentPartition["fstype"][:3] == "ext":
212 self["key_blue"].setText(_("Check"))
214 self["key_blue"].setText("")
216 def showDeviceList(self):
218 self["key_red"].setText(_("Close"))
219 self["key_green"].setText(_("Ok"))
220 self["key_yellow"].setText(" ")
221 self["key_blue"].setText(_("Initialize"))
223 for device in deviceinfo.getBlockDevices():
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]
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)
239 def showPartitionList(self):
240 if self.currDevice is None:
243 for partition in self.currDevice["partitions"]:
244 partitionInfo = deviceinfo.getPartitionInfo(partition)
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
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()
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)
269 def showMountPointSetup(self):
270 if self.currDevice is None or self.currPartition is None:
272 partition = self.currPartition["partition"]
273 if not os.access("/autofs/%s"%partition,0):
274 self.session.open(MessageBox, _("This partition is not mountable.\nYou need to check or format this partition."), MessageBox.TYPE_ERROR, timeout = 10)
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)
297 def getCurrentDevice(self):
299 return self["menu"].getCurrent()[6]
303 def getCurrentPartition(self):
305 return self["menu"].getCurrent()[7]
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)
317 self.showPartitionList()
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()
329 self.doUmount(currMountPoint, self.showPartitionList)
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])
342 # print "Setup mountpoint manually!"
343 self.session.openWithCallback(self.MountpointBrowserCB, MountpointBrowser)
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"
363 if self.currList == "partitions":
364 self.choiceBoxFstype()
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"])
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)
378 self.session.open(MessageBox, _("Partition info is not found."), MessageBox.TYPE_ERROR, timeout = 10)
381 self.session.open(DeviceManagerConfiguration)
383 def deviceInitCB(self, ret = True):
384 self.showDeviceList()
386 def deviceCheckCB(self, ret = True):
387 self.showPartitionList()
389 def deviceFormatCB(self, ret = True):
390 self.showPartitionList()
392 def choiceBoxFstype(self):
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)
400 def choiceBoxFstypeCB(self, choice):
404 partition = self.getCurrentPartition()
405 if partition is not None:
406 self.session.openWithCallback(self.deviceFormatCB, DeviceFormat, partition, choice[1])
408 self.session.open(MessageBox, _("Partition info is not found."), MessageBox.TYPE_ERROR, timeout = 10)
410 # about mount funcs..
411 def doUmount(self, mountpoint, callback):
412 cmd = "umount %s"%mountpoint
413 print "[DeviceManager] cmd : %s"%cmd
415 if not path.ismount(mountpoint):
416 devicemanagerconfig.updateConfigList()
418 self.session.open(MessageBox, _("Can't umount %s. \nMaybe device or resource busy.")%mountpoint, MessageBox.TYPE_ERROR, timeout = 10)
421 def getDefaultMountPoint(self):
422 return self.defaultMountPoint
424 def getAutoMountPoint(self):
425 mountPoint = "/media/"+self.currDevice["model"]
426 mountPoint = mountPoint.replace(' ','-')
427 if path.ismount(mountPoint):
430 mountPoint_fix = mountPoint+str(partnum)
431 if not path.ismount(mountPoint_fix):
434 mountPoint = mountPoint_fix
437 def doMount(self, partition, mountpoint):
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)
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)
458 # check current device mounted on another mountpoint.
459 mp_list = deviceinfo.checkMountDev(devpath)
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)
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)
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) )
484 self.session.open(MessageBox, _("Mount Failed!\n(%s -> %s)")%(device, mountpoint), MessageBox.TYPE_ERROR, timeout = 10)
486 def doMountFinished(self, result, retval, extra_args = None):
487 (devpath, mountpoint) = extra_args
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)
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()
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)
514 self.doMount(self.currPartition, mountPoint)
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()
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)
543 self.doMkfsTimer = eTimer()
544 self.doMkfsTimer.callback.append(self.doMkfs)
545 self.doInitializeTimer = eTimer()
546 self.doInitializeTimer.callback.append(self.doInitialize)
548 self.partitionType = "MBR"
550 self.inputbox_partitionSizeRemain = self.inputbox_partitionSizeTotal
553 def timerStart(self):
554 self.initStartTimer.start(100,True)
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)
560 def confirmed(self, ret):
562 self.InitializeStart()
566 def exit(self, ret = True):
569 def unmountAll(self, device):
570 mounts = file('/proc/mounts').read().split('\n')
574 if not line.startswith("/dev/" + device):
576 cmd += "umount %s ;"% line.split()[0]
577 print "[DeviceManager] %s"%cmd
580 mounts = file('/proc/mounts').read().split('\n')
582 if line.startswith("/dev/" + device):
586 def InitializeStart(self):
587 if self.devicesize >= ( 2.2 * 1000 * 1000 * 1000 * 1000 ): # 2.2TB
588 self.partitionType = "GPT"
590 self.inputbox_partitionSizeRemain = 100
593 self.InputPartitionSize_step1()
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)
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()
603 self.session.openWithCallback(self.exit, MessageBox, _("The number you entered is wrong!"), MessageBox.TYPE_ERROR, timeout = 10)
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()
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)
616 def InputPartitionSize_step2_CB(self, ret):
618 if self.inputbox_partitionSizeRemain < int(ret) or int(ret) == 0:
619 self.InputPartitionSize_step2()
621 self.inputbox_partitionSizeList.append(str(ret))
622 self.inputbox_partitionSizeRemain -= int(ret)
623 self.InputPartitionSize_step2()
625 self.session.openWithCallback(self.exit ,MessageBox, _("The number you entered is wrong!"), MessageBox.TYPE_ERROR, timeout = 10)
627 def choiceBoxFstype(self):
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)
635 def choiceBoxFstypeCB(self, choice):
639 self.fstype = choice[1]
640 if self.fstype not in ["ext2", "ext3", "ext4", "vfat"]:
643 self.initInitializeConfirm()
645 def initInitializeConfirm(self):
646 # print self.inputbox_partitionSizeList
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)
654 def initInitializeConfirmCB(self,ret):
656 self.initInitialize()
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)
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)
672 def doInitialize(self):
673 def CheckPartedVer():
674 cmd = 'parted --version'
675 lines = os.popen(cmd).readlines()
677 if l.find("parted (GNU parted)") != -1:
678 ver = l.split()[3].strip()
683 print "[CheckPartedVer] check parted version Failed!"
687 partitions = len(self.inputbox_partitionSizeList) # get num of partition
689 if self.partitionType == "MBR":
691 cmd = 'printf "8,\n;0,0\n;0,0\n;0,0\ny\n" | sfdisk -f -uS /dev/' + self.device
695 set += ",%s\n"%(self.inputbox_partitionSizeList[p])
699 cmd = 'printf "%s" | sfdisk -f -uM /dev/%s'%(set,self.device)
701 elif self.partitionType == "GPT": # partition type is GPT
703 partedVer = CheckPartedVer()
704 if partedVer >= 2.1: # align option is supported in version 2.1 or later
705 setAlign = "--align optimal"
708 cmd = 'parted %s /dev/%s --script mklabel gpt mkpart disk ext2 0%% 100%%' % (setAlign, self.device)
709 else: # has multiple partitions
711 for p in range(partitions):
714 p_end = int( (long(self.inputbox_partitionSizeList[p]) * 100) / 100 )
716 elif p > 0 and partitions > (p + 1):
718 p_end = int( (long(self.inputbox_partitionSizeList[p]) * 100) / 100 )+ p_start
720 elif partitions == (p + 1):
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)
730 errorMsg = "Invalid partitioning type"
731 self.msgWaiting.run_close(False, errorMsg)
733 self.deviceInitConsole.ePopen(cmd, self.initInitializeFinished)
735 def initInitializeFinished(self, result, retval, extra_args = None):
737 if self.partitionType == "MBR":
738 cmd = "sfdisk -R /dev/%s ; sleep 5" % (self.device)
741 self.deviceInitConsole.ePopen(cmd, self.initInitializingRefreshFinished)
743 errorMsg = "initInitializing device Error at /dev/%s"%self.device
744 self.msgWaiting.run_close(False, errorMsg)
746 def initInitializingRefreshFinished(self, result, retval, extra_args = None):
747 cmd = "/bin/umount /dev/%s*" % (self.device)
748 self.deviceInitConsole.ePopen(cmd, self.initInitializingUmountFinished)
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
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)
765 self.msgWaiting.run_close(True)
766 # self.createFilesystem(self.newpartitions)
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)
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])
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
801 cmd = "/usr/sbin/mkfs.vfat -I " + fulldevicename
803 self.createFilesystemFinished(None, -1, (self.device, fulldevicename))
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)
813 self.doMkfsTimer.start(500,True)
816 fulldevicename = "/dev/" + self.device + str(self.devicenumber)
817 self.deviceInitConsole.ePopen(self.mkfs_cmd, self.createFilesystemFinished, (self.device, fulldevicename))
819 def createFilesystemFinished(self, result, retval, extra_args = None):
820 device = extra_args[0]
821 fulldevicename = extra_args[1]
823 self.msgWaitingMkfs.run_close(True)
825 errorMsg = _("Creating filesystem Error")
826 if fulldevicename is not None:
827 errorMsg += _(" at /dev/%s")%fulldevicename
828 self.msgWaitingMkfs.run_close(False, errorMsg)
830 def createFilesystemStart(self):
831 self.createFilesystem(self.newpartitions)
833 def msgWaitingCB(self, ret, msg=""):
835 self.createFSStartTimer.start(100,True)
839 self.exitMessageTimer.start(100,True)
841 def msgWaitingMkfsCB(self, ret, msg=""):
842 if self.devicenumber < self.newpartitions:
843 self.createFSStartTimer.start(100,True)
847 self.msg = _("Device Initialization finished sucessfully!")
848 self.updateDeviceInfo()
849 self.exitMessageTimer.start(100,True)
853 self.exitMessageTimer.start(100,True)
855 def exitMessage(self):
857 self.session.openWithCallback(self.exit, MessageBox, self.msg, MessageBox.TYPE_INFO, timeout = 10)
859 self.session.openWithCallback(self.exit, MessageBox, self.msg, MessageBox.TYPE_ERROR, timeout = 10)
861 def updateDeviceInfo(self):
862 # update devicemanager configs
863 devicemanagerconfig.updateConfigList()
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)
881 def timerStart(self):
882 self.checkStartTimer.start(100,True)
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)
890 self.deviceCheckStart()
892 def confirmed(self, ret):
893 print "confirmed : ",ret
895 self.deviceCheckStart()
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)
915 device = self.partition["partition"]
916 mountpoint = self.partition["mountpoint"]
917 fstype = self.partition["fstype"]
919 self.doUmountFsck(device, mountpoint, fstype)
921 self.umountFsckFinished("NORESULT", 0, (device, mountpoint, fstype))
923 def doUmountFsck(self, device, mountpoint, fstype):
924 cmd = "umount /dev/%s" % device
925 self.deviceCheckConsole.ePopen(cmd, self.umountFsckFinished, (device, mountpoint, fstype))
927 def umountFsckFinished(self, result, retval, extra_args = None):
928 device = extra_args[0]
929 mountpoint = extra_args[1]
930 fstype = extra_args[2]
932 cmd = "fsck." + fstype + " -f -p /dev/" + device
933 self.deviceCheckConsole.ePopen(cmd, self.fsckFinished, extra_args)
935 errorMsg = _("Can not umount device /dev/%s.\nMaybe some files of the filesystem are open")%device
936 self.msgWaiting.run_close(False,errorMsg)
938 def fsckFinished(self, result, retval, extra_args = None):
939 device = extra_args[0]
940 mountpoint = extra_args[1]
942 text = _("Filesystem check finished sucessfully")
943 self.msgWaiting.run_close(True, text)
945 text = _("Error checking disk. The disk or filesystem may be damaged")
946 self.msgWaiting.run_close(False, text)
948 def msgWaitingCB(self, ret, msg):
950 self.session.open(MessageBox, msg, MessageBox.TYPE_INFO, timeout = 10)
952 self.session.open(MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 10)
954 partition = self.partition["partition"]
955 mountpoint = self.partition["mountpoint"]
956 fstype = self.partition["fstype"]
959 cmd = "ntfs-3g /dev/" + partition + " " + mountpoint
961 cmd = "mount /dev/" + partition + " " + mountpoint
962 self.deviceCheckConsole.ePopen(cmd, self.mountPartitionFinished)
966 def mountPartitionFinished(self, result, retval, extra_args = None):
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)
991 def timerStart(self):
992 self.formatStartTimer.start(100,True)
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)
1010 def doUnmount(self):
1011 mountpoint = self.partition["mountpoint"]
1012 if mountpoint != "":
1013 self.doumountPartition()
1015 self.umountPartitionFinished("NORESULT", 0)
1017 def doumountPartition(self):
1018 oldfstype = self.partition["fstype"]
1019 newfstype = self.newfstype
1021 if newfstype == oldfstype:
1022 device = self.partition["partition"]
1024 device = self.partition["partition"][:3]
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)
1033 def umountPartitionFinished(self, result, retval, extra_args = None):
1034 partition = self.partition["partition"]
1035 oldfstype = self.partition["fstype"]
1036 newfstype = self.newfstype
1038 if oldfstype == newfstype:
1039 self.changePartitionIDFinished("NORESULT", 0)
1041 cmd = "sfdisk --change-id /dev/%s %s" % (partition[:3], partition[3:])
1042 if newfstype[:3] == "ext":
1046 self.deviceFormatConsole.ePopen(cmd, self.changePartitionIDFinished)
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)
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
1057 if oldfstype == newfstype:
1058 self.refreshPartitionFinished("NORESULT", 0)
1060 cmd = "sfdisk -R /dev/%s; sleep 5"%(device)
1061 self.deviceFormatConsole.ePopen(cmd, self.refreshPartitionFinished)
1063 if result and result.find("Use GNU Parted") > 0:
1064 print "[DeviceManager] /dev/%s use GNU Parted!" % device
1065 self.refreshPartitionFinished("NORESULT", 0)
1067 errorMsg = _("Can not change the partition ID for %s")%device
1068 self.msgWaiting.run_close(False,errorMsg)
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
1078 if newfstype == "ext4":
1079 cmd = "/sbin/mkfs.ext4 -F "
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 "
1086 cmd += "-T largefile "
1087 cmd += "-m0 /dev/" + partition
1088 elif newfstype == "ext2":
1089 cmd = "/sbin/mkfs.ext2 -F "
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
1097 cmd = "/usr/sbin/mkfs.vfat -I /dev/" + partition
1098 self.deviceFormatConsole.ePopen(cmd, self.mkfsFinished)
1100 errorMsg = _("Can not format device /dev/%s.\nrefresh partition information failed!")%partition
1101 self.msgWaiting.run_close(False,errorMsg)
1103 def mkfsFinished(self, result, retval, extra_args = None):
1104 print "mkfsFinished!"
1105 partition = self.partition["partition"]
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)
1114 text = _("Make filesystem Error /dev/%s.\nPlease check your device.")%partition
1115 self.msgWaiting.run_close(False, text)
1117 def doMountFinished(self, result, retval, extra_args = None):
1118 print "doMountFinished!"
1119 text = _("Format finished sucessfully.")
1120 self.msgWaiting.run_close(True, text)
1122 def msgWaitingCB(self, ret, msg):
1124 self.session.openWithCallback(self.exit, MessageBox, msg, MessageBox.TYPE_INFO, timeout = 10)
1126 self.session.openWithCallback(self.exit, MessageBox, msg, MessageBox.TYPE_ERROR, timeout = 10)
1128 def exit(self, ret):
1129 if self.setHotplugDisabled == True:
1130 devicemanagerhotplug.setHotplugActive(True)
1131 self.setHotplugDisabled = False
1138 self.blockDeviceList = []
1140 def getBlockDevices(self):
1141 return self.blockDeviceList
1144 self.blockDeviceList = []
1145 self.getBlockDeviceList()
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)
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)
1162 def SortPartList(self, partList):
1163 length = len(partList)-1
1165 while sorted is False:
1167 for idx in range(length):
1168 if int(partList[idx][3:]) > int(partList[idx+1][3:]):
1170 partList[idx] , partList[idx+1] = partList[idx+1], partList[idx]
1172 def getBlockDeviceInfo(self, blockdev):
1173 devpath = "/sys/block/" + blockdev
1182 dev = int(readFile(devpath + "/dev").split(':')[0])
1183 if dev in (7, 31) or blockdev[0:2] != 'sd': # 7: loop, 31 : mtdblock
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:
1193 partitions.append(partition)
1194 self.SortPartList(partitions)
1198 return error, blacklisted, removable, partitions, size, model, vendor
1200 def getPartitionInfo(self, partition):
1201 mountPoint = self.getPartitionMountpoint(partition)
1202 (uuid , fsType) = self.getPartitionBlkidInfo(partition)
1203 size_total = self.getPartitionSize(partition)
1205 if mountPoint != "":
1206 size_free = self.getPartitionFree(mountPoint)
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
1216 def getPartitionMountpoint(self, partition):
1217 mounts = file('/proc/mounts').read().split('\n')
1219 if not x.startswith('/'):
1221 devpath, mountpoint, = x.split()[:2]
1222 if mountpoint.startswith('/autofs'):
1224 if path.basename(devpath) == partition:
1228 def getPartitionBlkidInfo(self, partition):
1229 parttionDev = "/dev/"+str(partition)
1232 cmd = "blkid -c /dev/null "+str(parttionDev)
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('"')
1243 print "get blkid info error (%s)"%cmd
1244 return (uuid, partitionType)
1246 def getPartitionSize(self, partition):
1247 devpath = "/sys/block/%s/%s"%( str(partition[:3]), str(partition) )
1249 size = readFile(devpath + "/size")
1250 return str(int(size)*512)
1254 def getPartitionFree(self, mountPoint):
1256 stat = statvfs(mountPoint)
1257 size_free = stat.f_bfree*stat.f_bsize
1262 def checkMountPoint(self, check_mountpoint):
1265 mounts = file('/proc/mounts').read().split('\n')
1267 if not x.startswith('/'):
1269 devpath, mountpoint = x.split()[:2]
1270 if mountpoint == check_mountpoint:
1276 def checkMountDev(self, device):
1279 mounts = file('/proc/mounts').read().split('\n')
1281 if not x.startswith('/'):
1283 devpath, mountpoint = x.split()[:2]
1284 if devpath == device:
1285 res.append(mountpoint)
1290 def isMounted(self, devpath, mountpoint):
1292 mounts = file('/proc/mounts').read().split('\n')
1294 if not x.startswith('/'):
1296 _devpath, _mountpoint = x.split()[:2]
1297 if devpath == _devpath and mountpoint == _mountpoint:
1303 def isMountable(self, partition):
1304 autofsPath = "/autofs/"+partition.device
1307 os.listdir(autofsPath)
1313 def isFstabAutoMounted(self, uuid, devpath, mountpoint):
1314 # print " >> isFstabMounted, uuid : %s, devpath : %s, mountpoint : %s"%(uuid, devpath, mountpoint)
1315 if mountpoint[-1] == '/':
1316 mountpoint = mountpoint[:-1]
1317 data = file('/etc/fstab').read().split('\n')
1319 if not line.startswith('/'):
1321 dev, mp, ms = line.split()[0:3]
1322 if uuid is not None and dev.startswith('UUID'):
1323 if dev.split('=')[1] == uuid.strip("\"") and mp == mountpoint and ms == 'auto':
1324 # print " >> line : ", line
1326 elif dev == devpath and mp == mountpoint and ms == 'auto':
1327 # print " >> line : ", line
1331 def umountByMountpoint(self, mountpoint):
1332 if mountpoint is None:
1335 if path.ismount(mountpoint):
1336 cmd = "umount " + mountpoint
1337 print "[DeviceManager] ", cmd
1340 print "Umount by mountpoint failed!"
1341 if not path.ismount(mountpoint):
1345 def umountByDevpath(self, devpath):
1346 cmd = "umount " + devpath
1347 print "[DeviceManager] ", cmd
1350 deviceinfo = DeviceInfo()
1352 class MountpointBrowser(Screen):
1354 <screen name="MountpointBrowser" position="center,120" size="670,500" title="Select mountpoint">
1355 <ePixmap pixmap="skin_default/buttons/red.png" position="20,0" size="140,40" alphatest="on" />
1356 <ePixmap pixmap="skin_default/buttons/green.png" position="180,0" size="140,40" alphatest="on" />
1357 <ePixmap pixmap="skin_default/buttons/yellow.png" position="340,0" size="140,40" alphatest="on" />
1358 <ePixmap pixmap="skin_default/buttons/blue.png" position="500,0" size="140,40" alphatest="on" />
1359 <widget source="key_red" render = "Label" position="20,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#9f1313" transparent="1" />
1360 <widget source="key_green" render = "Label" position="180,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#1f771f" transparent="1" />
1361 <widget source="key_yellow" render = "Label" position="340,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#a08500" transparent="1" />
1362 <widget source="key_blue" render = "Label" position="500,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#18188b" transparent="1" />
1363 <eLabel position="10,50" size="650,1" backgroundColor="#b3b3b9"/>
1364 <widget name="filelist" position="10,60" size="650,440" itemHeight="30" scrollbarMode="showOnDemand"/>
1367 def __init__(self, session):
1368 Screen.__init__(self, session)
1369 self["key_red"] = StaticText(_("Cancel"))
1370 self["key_green"] = StaticText(_("Select"))
1371 self["key_yellow"] = StaticText(_("Create directory"))
1372 self["key_blue"] = StaticText("Delete directory")
1373 directory = "/media/"
1374 inhibitDirs = ["/autofs", "/mnt", "/hdd", "/bin", "/boot", "/dev", "/etc", "/home", "/lib", "/proc", "/sbin", "/share", "/sys", "/tmp", "/usr", "/var"]
1375 self.filelist = FileList(directory, matchingPattern="", inhibitDirs = inhibitDirs)
1376 self["filelist"] = self.filelist
1378 self["shortcuts"] = ActionMap(["ColorActions"],
1381 "green": self.select,
1382 "yellow": self.createDirectory,
1383 "blue": self.deleteDirectory,
1386 self["OkCancelActions"] = ActionMap(["OkCancelActions"],
1388 "cancel": self.exit,
1393 if self.filelist.canDescent():
1394 self.filelist.descent()
1397 if self["filelist"].getCurrentDirectory() is not None:
1398 if self.filelist.canDescent() and self["filelist"].getFilename() and self["filelist"].getFilename().startswith(self["filelist"].getCurrentDirectory()):
1399 self.filelist.descent()
1400 currDir = self["filelist"].getCurrentDirectory()
1403 self.close(self["filelist"].getFilename())
1405 def createDirectory(self):
1406 self.session.openWithCallback(self.createDirectoryCB, VirtualKeyBoard, title = (_("Input mount point path.")), text = "")
1408 def createDirectoryCB(self, retval = None):
1411 if retval is not None:
1412 newdir = self["filelist"].getCurrentDirectory()+'/'+retval
1413 if not path.exists(newdir):
1414 os.system("mkdir %s"%newdir)
1415 self.filelist.refresh()
1418 self.session.open(MessageBox, _("Create directory failed!\n%s")%newdir, MessageBox.TYPE_ERROR, timeout = 10)
1420 def deleteDirectory(self):
1423 if self["filelist"].getCurrentDirectory() is not None:
1424 if self.filelist.canDescent() and self["filelist"].getFilename() and self["filelist"].getFilename().startswith(self["filelist"].getCurrentDirectory()):
1425 delDir = self["filelist"].getFilename()
1426 if path.exists(delDir):
1427 os.system("rmdir '%s'"%delDir)
1428 if path.exists(delDir):
1429 self.session.open(MessageBox, _("Delete directory failed!\nMaybe directory is not empty."), MessageBox.TYPE_ERROR, timeout = 10)
1430 self.filelist.refresh()
1433 self.session.open(MessageBox, _("Delete directory failed!\n%s")%newdir, MessageBox.TYPE_ERROR, timeout = 10)
1438 class MessageBoxConfirm(MessageBox):
1440 <screen position="center,center" size="620,10" title="Message">
1441 <widget name="text" position="65,8" size="420,0" font="Regular;20" />
1442 <widget name="ErrorPixmap" pixmap="skin_default/icons/input_error.png" position="5,5" size="53,53" alphatest="blend" />
1443 <widget name="QuestionPixmap" pixmap="skin_default/icons/input_question.png" position="5,5" size="53,53" alphatest="blend" />
1444 <widget name="InfoPixmap" pixmap="skin_default/icons/input_info.png" position="5,5" size="53,53" alphatest="blend" />
1445 <widget name="list" position="100,100" size="380,375" transparent="1" />
1446 <applet type="onLayoutFinish">
1447 # this should be factored out into some helper code, but currently demonstrates applets.
1448 from enigma import eSize, ePoint
1450 orgwidth = self.instance.size().width()
1451 orgheight = self.instance.size().height()
1452 orgpos = self.instance.position()
1453 textsize = self["text"].getSize()
1455 # y size still must be fixed in font stuff...
1456 textsize = (textsize[0] + 50, textsize[1] + 50)
1458 if self.type == self.TYPE_YESNO:
1460 wsizex = textsize[0] + 60
1461 wsizey = textsize[1] + offset
1462 if (280 > wsizex):
1464 wsize = (wsizex, wsizey)
1467 self.instance.resize(eSize(*wsize))
1470 self["text"].instance.resize(eSize(*textsize))
1473 listsize = (wsizex, 50)
1474 self["list"].instance.move(ePoint(0, textsize[1]))
1475 self["list"].instance.resize(eSize(*listsize))
1479 newheight = wsize[1]
1480 self.instance.move(ePoint(orgpos.x() + (orgwidth - newwidth)/2, orgpos.y() + (orgheight - newheight)/2))
1485 dmconfigfile = resolveFilename(SCOPE_PLUGINS, "SystemPlugins/DeviceManager/devicemanager.cfg")
1486 class DeviceManagerConfig():
1488 self.configList = []
1490 def getConfigList(self):
1491 return self.configList
1493 def updateConfigList(self):
1495 self.configList = []
1496 file = open("/proc/mounts")
1497 mounts = file.readlines()
1500 if x.startswith("/dev/sd"):
1501 device = x.split()[0].split('/dev/')[1]
1502 mountpoint = x.split()[1]
1503 if mountpoint.startswith('/autofs'):
1505 (uuid, partitionType) = deviceinfo.getPartitionBlkidInfo(device)
1506 if uuid != '' and mountpoint != '':
1507 self.configList.append([uuid, mountpoint])
1510 print "updateConfigList failed!"
1512 def loadConfig(self):
1513 if not fileExists(dmconfigfile):
1514 os.system("touch %s" % dmconfigfile)
1515 self.configList = []
1516 data = file(dmconfigfile).read().split('\n')
1518 if line.find(':') != -1:
1519 (uuid, mountpoint) = line.split(':')
1520 if uuid != '' and mountpoint != '':
1521 self.configList.append([uuid, mountpoint])
1523 def saveConfig(self):
1524 confFile = open(dmconfigfile,'w')
1526 for line in self.configList:
1527 data += "%s:%s\n"%(line[0],line[1]) # uuid, mountpoint
1528 confFile.write(data)
1531 def appendConfig(self, uuid, mountpoint):
1532 for x in self.configList:
1533 if x[0] == uuid or x[1] == mountpoint:
1534 self.configList.remove(x)
1535 self.configList.append([uuid, mountpoint])
1537 def removeConfig(self, value):
1538 for x in self.configList:
1539 if x[0] == value or x[1] == value:
1540 self.configList.remove(x)
1542 devicemanagerconfig = DeviceManagerConfig()
1544 class deviceManagerHotplug:
1546 self.hotplugActive = True
1548 def setHotplugActive(self,value=True):
1550 self.hotplugActive = True
1552 self.hotplugActive = False
1554 def printDebug(self):
1555 for p in harddiskmanager.partitions:
1556 print " # partition : %s %s %s %s %s(mp, des, f_mounted, is_hot, dev)"%(p.mountpoint, p.description, p.force_mounted, p.is_hotplug,p.device)
1558 def doMount(self, uuid, devpath, mountpoint, filesystem):
1559 # check current device mounted on another mountpoint.
1561 mp_list = deviceinfo.checkMountDev(devpath)
1563 if mp != mountpoint and path.ismount(mp):
1564 deviceinfo.umountByMountpoint(mp)
1565 # check another device mounted on configmountpoint
1567 devpath_list = deviceinfo.checkMountPoint(mountpoint)
1568 for devpath_ in devpath_list:
1569 if devpath_ != devpath:
1570 print "[DeviceManager] Mount Failed. (Another device is already mounted)"
1573 # print "[DeviceManager] doMount"
1574 if not path.exists(mountpoint):
1575 os.system("mkdir %s"%mountpoint)
1576 if path.exists(mountpoint):
1577 if not path.ismount(mountpoint):
1578 if filesystem == "ntfs":
1579 cmd = "ntfs-3g %s %s"%(devpath, mountpoint)
1580 elif filesystem is None:
1581 cmd = "mount %s %s"%(devpath, mountpoint)
1583 cmd = "mount -t %s %s %s"%(filesystem, devpath, mountpoint)
1584 print "[DeviceManager] cmd : %s"%cmd
1586 if not deviceinfo.isMounted(devpath, mountpoint):
1587 print "[DeviceManager] %s doMount failed!"%devpath
1590 # Update partition Info, add
1591 self.addPartitionAutofsMountpoint(devpath, mountpoint)
1593 def doUmount(self, device, mountpoint):
1594 devpath = "/dev/"+device
1595 mountpoints = deviceinfo.checkMountDev(devpath)
1596 if len(mountpoints) == 0:
1598 for mp in mountpoints:
1599 cmd = "umount %s"%devpath
1600 print "[DeviceManager] cmd : %s"%cmd
1603 def addHotPlugDevice(self, partition):
1604 device = partition.device
1605 devpath = "/dev/"+device
1607 (uuid, filesystem) = deviceinfo.getPartitionBlkidInfo(device)
1610 os.system("sleep 1")
1611 (uuid, filesystem) = deviceinfo.getPartitionBlkidInfo(device)
1613 print "[DeviceManagerHotplug] getBlkidInfo failed!"
1616 devicemanagerconfig.loadConfig()
1617 configList = devicemanagerconfig.getConfigList()
1619 for line in configList:
1620 if uuid == line[0].strip():
1621 mountpoint = line[1].strip()
1623 if mountpoint is None:
1626 if deviceinfo.isMounted(devpath, mountpoint):
1628 # print "[DeviceManagerHotplug] already mounted"
1630 self.doMount(uuid, devpath, mountpoint, filesystem)
1632 def removeHotplugDevice(self, partition):
1633 self.doUmount(partition.device, partition.mountpoint)
1635 def getHotplugAction(self, action, partition):
1636 if not self.hotplugActive or not config.plugins.devicemanager.hotplug_enable.value:
1638 if partition.device is None or not partition.device.startswith("sd"):
1640 print "[DeviceManagerHotplug] action : %s, device : %s"%(action, partition.device)
1643 self.addHotPlugDevice(partition)
1644 elif action == 'remove':
1645 self.removeHotplugDevice(partition)
1647 def addPartitionAutofsMountpoint(self, devpath, mountpoint):
1648 device = path.basename(devpath)
1649 autofsMountpoint = harddiskmanager.getAutofsMountpoint(device)
1650 # check already appended to partition list
1651 for x in harddiskmanager.partitions:
1652 if x.mountpoint == autofsMountpoint or x.mountpoint == mountpoint:
1655 from Components.Harddisk import Partition
1656 physdev = path.realpath('/sys/block/' + device[:3] + '/device')[4:]
1657 description = harddiskmanager.getUserfriendlyDeviceName(device, physdev)
1658 p = Partition(mountpoint = autofsMountpoint, description = description, force_mounted = True, device = device)
1659 harddiskmanager.partitions.append(p)
1660 harddiskmanager.on_partition_list_change("add", p)
1662 def autoMountOnStartup(self):
1663 devicemanagerconfig.loadConfig()
1664 configList = devicemanagerconfig.getConfigList()
1667 data = os.popen("blkid -c /dev/NULL /dev/sd*").readlines()
1669 devpath = uuid = filesystem = ""
1670 devpath = line.split(':')[0]
1671 if line.find(" UUID=") != -1:
1672 uuid = line.split(" UUID=")[1].split(' ')[0]
1673 if line.find(" TYPE=") != -1:
1674 filesystem = line.split(" TYPE=")[1].split(' ')[0].strip('"')
1675 blkiddata.append((devpath, uuid, filesystem))
1677 for c in configList:
1678 uuid_cfg = c[0].strip()
1679 mountpoint_cfg = c[1].strip()
1680 for (devpath, uuid, filesystem) in blkiddata:
1681 if uuid_cfg == uuid:
1683 if deviceinfo.isMounted(devpath, mountpoint_cfg):
1684 # print "[Devicemanager startup] already mounted"
1685 self.addPartitionAutofsMountpoint(devpath, mountpoint_cfg)
1687 # print "[autoMountOnStartup] do mount(%s %s %s)"%(devpath, configmountpoint, filesystem)
1688 self.doMount(uuid, devpath, mountpoint_cfg, filesystem)
1690 def umountOnShutdown(self):
1691 devicemanagerconfig.loadConfig()
1692 configList = devicemanagerconfig.getConfigList()
1695 data = file('/proc/mounts').read().split('\n')
1697 if not x.startswith('/dev/sd'):
1699 devpath, mountpoint = x.split()[:2]
1700 mounts.append((path.basename(devpath), mountpoint))
1702 data = self.getBlkidInfo()
1704 for c in configList:
1705 uuid_cfg = c[0].strip()
1706 mountpoint_cfg = c[1].strip()
1708 if uuid_cfg in data.keys():
1709 device_cfg = data[uuid_cfg]
1710 if device_cfg is None:
1712 for (device, mountpoint) in mounts:
1713 if device_cfg == device:
1714 if not deviceinfo.isFstabAutoMounted(uuid_cfg, "/dev/"+device_cfg, mountpoint_cfg):
1715 self.doUmount(device, mountpoint)
1717 def getBlkidInfo(self):
1719 blkid_data = os.popen("blkid -c /dev/NULL /dev/sd*").read()
1720 for line in blkid_data.split('\n'):
1721 # print "[DeviceManager] getBlkidInfo line : ",line
1723 device = path.basename(line.split(':')[0])
1724 if line.find(" UUID=") != -1:
1725 blkid_uuid = line.split(" UUID=")[1].split(' ')[0]
1726 data[blkid_uuid] = device
1729 devicemanagerhotplug = deviceManagerHotplug()
1731 def DeviceManagerhotplugDeviceStart(action, device):
1732 devicemanagerhotplug.getHotplugAction(action, device)
1734 def callBackforDeviceManager(session, callback_result = False):
1735 if callback_result == True:
1736 session.open(DeviceManager)
1738 def checkMounts(session):
1740 noMountable_dev = ""
1741 for blockdev in listdir("/sys/block"):
1742 devpath = "/sys/block/" + blockdev
1743 dev = int(readFile(devpath + "/dev").split(':')[0])
1744 if dev in (7, 31) or blockdev[0:2] != 'sd': # 7: loop, 31 : mtdblock
1747 noMountable_partitions = []
1748 for partition in listdir(devpath):
1749 if not partition.startswith(blockdev):
1751 partitions.append(partition)
1752 if os.access('/autofs/'+partition,0) is False:
1753 noMountable_partitions.append(partition)
1754 if len(partitions) == 0 or len(noMountable_partitions) != 0:
1755 if noMountable_dev != "":
1756 noMountable_dev += ' '
1757 noMountable_dev += blockdev
1759 if noMountable_dev != "":
1760 print "Umountable partitions found."
1761 InfoText = _("No mountable devices found.! (%s)\nDo you want to open DeviceManager and do initialize or format this device?\n\n(Open 'Menu->Setup->System -> Harddisk -> DeviceManager'\n and press MENU button to deactivate this check.)")%noMountable_dev
1762 AddNotificationWithCallback(
1763 boundFunction(callBackforDeviceManager, session),
1764 MessageBox, InfoText, timeout = 60, default = False
1767 print "checkMounts failed!"
1769 def sessionstart(reason, **kwargs):
1771 if kwargs.has_key("session") and config.plugins.devicemanager.mountcheck_enable.value == True:
1772 session = kwargs["session"]
1773 checkMounts(session)
1774 if config.plugins.devicemanager.hotplug_enable.value:
1775 harddiskmanager.on_partition_list_change.append(DeviceManagerhotplugDeviceStart)
1777 if config.plugins.devicemanager.hotplug_enable.value:
1778 harddiskmanager.on_partition_list_change.remove(DeviceManagerhotplugDeviceStart)
1780 def autostart(reason, **kwargs):
1783 # check at first enigma2 start
1784 if not fileExists(dmconfigfile):
1785 print "[DeviceManager] autostart : check devices at first start"
1786 sda_isremovable = False
1788 os.system("touch %s"%dmconfigfile)
1790 sda_data = popen("cat /proc/partitions | grep sda1").read()
1792 sda_UUID = popen("blkid -o value -s UUID /dev/sda1").read().strip('\n')
1793 sda_isremovable = bool(int(readFile("/sys/block/sda/removable")))
1794 print "sda : %s, %s"%(sda_UUID, sda_isremovable)
1797 cfg += '"%s":/media/hdd\n'%sda_UUID
1798 confFile = open(dmconfigfile,'w')
1801 if not path.exists("/media/hdd"):
1802 os.system("mkdir -p /media/hdd")
1804 devicemanagerhotplug.autoMountOnStartup()
1806 print "[DeviceManager] autostart failed!"
1808 devicemanagerhotplug.umountOnShutdown()
1810 def menu(menuid, **kwargs):
1811 if menuid == "system":
1812 return [(_("DeviceManager"), main, "device_manager", 50)]
1815 def main(session, **kwargs):
1816 session.open(DeviceManager)
1818 def Plugins(path, **kwargs):
1820 PluginDescriptor(name = _("DeviceManager"), description = _("manage block devices of your VU+"), where = PluginDescriptor.WHERE_MENU,fnc=menu),
1821 PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, needsRestart = True, fnc = sessionstart),
1822 PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, needsRestart = True, fnc = autostart)
1825 class MessageBox_2(MessageBox):
1826 def __init__(self, session, text, type = MessageBox.TYPE_YESNO, timeout = -1, close_on_any_key = False, default = True, enable_input = True, msgBoxID = None):
1827 MessageBox.__init__(self, session, text, type, timeout, close_on_any_key, default, enable_input, msgBoxID)
1828 self.skinName = "MessageBox"
1829 self.closeTimer = eTimer()
1830 self.closeTimer.callback.append(self.msg_close)
1831 self.devicemanager_ret = False
1832 self.devicemanager_msg = ""
1834 def msg_close(self):
1835 self.close(self.devicemanager_ret, self.devicemanager_msg)
1837 def run_close(self, ret, msg=""):
1838 self.devicemanager_ret = ret
1839 self.devicemanager_msg = msg
1840 self.closeTimer.start(100,True)
1842 def createSummary(self):
1843 return MessageBox_2_Summary
1845 class MessageBox_2_Summary(Screen):
1847 <screen name="MessageBox_2_Summary" position="0,0" size="256,64" id="1">
1848 <widget source="parent.Text" render="Label" position="0,0" size="256,64" font="Regular;13" halign="center" valign="center" />