diff --git a/NeoBoot/files/Harddisk.py b/NeoBoot/files/Harddisk.py new file mode 100644 index 0000000..e0b4e91 --- /dev/null +++ b/NeoBoot/files/Harddisk.py @@ -0,0 +1,1048 @@ +# -*- coding: utf-8 -*- + +from Plugins.Extensions.NeoBoot.__init__ import _ +import os +import time +from Tools.Directories import fileExists, pathExists, fileCheck +from Tools.CList import CList +from Components.SystemInfo import SystemInfo +from Components.Console import Console +from Task import LoggingTask +import Task +from Screens.Screen import Screen +from Components.ActionMap import ActionMap +from Components.MenuList import MenuList +from Components.Label import Label +from Components.Pixmap import Pixmap +from Screens.MessageBox import MessageBox + +def readFile(filename): + file = open(filename) + data = file.read().strip() + file.close() + return data + + +def getProcMounts(): + try: + mounts = open('/proc/mounts', 'r') + except IOError as ex: + print '[Harddisk] Failed to open /proc/mounts', ex + return [] + + result = [ line.strip().split(' ') for line in mounts ] + for item in result: + item[1] = item[1].replace('\\040', ' ') + + return result + + +def getNonNetworkMediaMounts(): + return [ x[1] for x in getProcMounts() if x[1].startswith('/media/') and not x[0].startswith('//') ] + + +def isFileSystemSupported(filesystem): + try: + for fs in open('/proc/filesystems', 'r'): + if fs.strip().endswith(filesystem): + return True + + return False + except Exception as ex: + print '[Harddisk] Failed to read /proc/filesystems:', ex + + +def findMountPoint(path): + path = os.path.abspath(path) + while not os.path.ismount(path): + path = os.path.dirname(path) + + return path + + +DEVTYPE_UDEV = 0 +DEVTYPE_DEVFS = 1 + +class Harddisk(): + + def __init__(self, device, removable = False): + self.device = device + if os.access('/dev/.udev', 0): + self.type = DEVTYPE_UDEV + elif os.access('/dev/.devfsd', 0): + self.type = DEVTYPE_DEVFS + else: + print '[Harddisk] Unable to determine structure of /dev' + self.type = -1 + self.card = False + self.max_idle_time = 0 + self.idle_running = False + self.last_access = time.time() + self.last_stat = 0 + self.timer = None + self.is_sleeping = False + self.dev_path = '' + self.disk_path = '' + self.mount_path = None + self.mount_device = None + self.phys_path = os.path.realpath(self.sysfsPath('device')) + self.removable = removable + self.internal = 'pci' in self.phys_path or 'ahci' in self.phys_path or 'sata' in self.phys_path + try: + data = open('/sys/block/%s/queue/rotational' % device, 'r').read().strip() + self.rotational = int(data) + except: + self.rotational = True + + if self.type == DEVTYPE_UDEV: + self.dev_path = '/dev/' + self.device + self.disk_path = self.dev_path + self.card = 'sdhci' in self.phys_path + elif self.type == DEVTYPE_DEVFS: + tmp = readFile(self.sysfsPath('dev')).split(':') + s_major = int(tmp[0]) + s_minor = int(tmp[1]) + for disc in os.listdir('/dev/discs'): + dev_path = os.path.realpath('/dev/discs/' + disc) + disk_path = dev_path + '/disc' + try: + rdev = os.stat(disk_path).st_rdev + except OSError: + continue + + if s_major == os.major(rdev) and s_minor == os.minor(rdev): + self.dev_path = dev_path + self.disk_path = disk_path + break + + self.card = self.device[:2] == 'hd' and 'host0' not in self.dev_path + print '[Harddisk] new device', self.device, '->', self.dev_path, '->', self.disk_path + if not removable and not self.card: + self.startIdle() + return + + def __lt__(self, ob): + return self.device < ob.device + + def partitionPath(self, n): + if self.type == DEVTYPE_UDEV: + if self.dev_path.startswith('/dev/mmcblk0'): + return self.dev_path + 'p' + n + else: + return self.dev_path + n + elif self.type == DEVTYPE_DEVFS: + return self.dev_path + '/part' + n + + def sysfsPath(self, filename): + return os.path.join('/sys/block/', self.device, filename) + + def stop(self): + if self.timer: + self.timer.stop() + self.timer.callback.remove(self.runIdle) + + def bus(self): + ret = _('External') + if self.type == DEVTYPE_UDEV: + type_name = ' (SD/MMC)' + elif self.type == DEVTYPE_DEVFS: + type_name = ' (CF)' + if self.card: + ret += type_name + else: + if self.internal: + ret = _('Internal') + if not self.rotational: + ret += ' (SSD)' + return ret + + def diskSize(self): + cap = 0 + try: + line = readFile(self.sysfsPath('size')) + cap = int(line) + return cap / 1000 * 512 / 1000 + except: + dev = self.findMount() + if dev: + try: + stat = os.statvfs(dev) + cap = int(stat.f_blocks * stat.f_bsize) + return cap / 1000 / 1000 + except: + pass + + return cap + + def capacity(self): + cap = self.diskSize() + if cap == 0: + return '' + if cap < 1000: + return _('%03d MB') % cap + return _('%d.%03d GB') % (cap / 1000, cap % 1000) + + def model(self): + try: + if self.device[:2] == 'hd': + return readFile('/proc/ide/' + self.device + '/model') + if self.device[:2] == 'sd': + vendor = readFile(self.sysfsPath('device/vendor')) + model = readFile(self.sysfsPath('device/model')) + return vendor + '(' + model + ')' + if self.device.startswith('mmcblk0'): + return readFile(self.sysfsPath('device/name')) + raise Exception, '[Harddisk] no hdX or sdX or mmcX' + except Exception as e: + print '[Harddisk] Failed to get model:', e + return '-?-' + + def free(self): + dev = self.findMount() + if dev: + try: + stat = os.statvfs(dev) + return stat.f_bfree / 1000 * (stat.f_bsize / 1024) + except: + pass + + return -1 + + def numPartitions(self): + numPart = -1 + if self.type == DEVTYPE_UDEV: + try: + devdir = os.listdir('/dev') + except OSError: + return -1 + + for filename in devdir: + if filename.startswith(self.device): + numPart += 1 + + elif self.type == DEVTYPE_DEVFS: + try: + idedir = os.listdir(self.dev_path) + except OSError: + return -1 + + for filename in idedir: + if filename.startswith('disc'): + numPart += 1 + if filename.startswith('part'): + numPart += 1 + + return numPart + + def mountDevice(self): + for parts in getProcMounts(): + if os.path.realpath(parts[0]).startswith(self.dev_path): + self.mount_device = parts[0] + self.mount_path = parts[1] + return parts[1] + + return None + + def enumMountDevices(self): + for parts in getProcMounts(): + if os.path.realpath(parts[0]).startswith(self.dev_path): + yield parts[1] + + def findMount(self): + if self.mount_path is None: + return self.mountDevice() + else: + return self.mount_path + + def unmount(self): + dev = self.mountDevice() + if dev is None: + return 0 + else: + cmd = 'umount ' + dev + print '[Harddisk]', cmd + res = os.system(cmd) + return res >> 8 + + def createPartition(self): + cmd = 'printf "8,\n;0,0\n;0,0\n;0,0\ny\n" | sfdisk -f -uS ' + self.disk_path + res = os.system(cmd) + return res >> 8 + + def mkfs(self): + return 1 + + def mount(self): + if self.mount_device is None: + dev = self.partitionPath('1') + else: + dev = self.mount_device + try: + fstab = open('/etc/fstab') + lines = fstab.readlines() + fstab.close() + except IOError: + return -1 + + for line in lines: + parts = line.strip().split(' ') + fspath = os.path.realpath(parts[0]) + if fspath == dev: + print '[Harddisk] mounting:', fspath + cmd = 'mount -t auto ' + fspath + res = os.system(cmd) + return res >> 8 + + res = -1 + if self.type == DEVTYPE_UDEV: + res = os.system('hdparm -z ' + self.disk_path) + from time import sleep + sleep(3) + return res >> 8 + + def fsck(self): + return 1 + + def killPartitionTable(self): + zero = 512 * '\x00' + h = open(self.dev_path, 'wb') + for i in range(9): + h.write(zero) + + h.close() + + def killPartition(self, n): + zero = 512 * '\x00' + part = self.partitionPath(n) + h = open(part, 'wb') + for i in range(3): + h.write(zero) + + h.close() + + def createInitializeJob(self): + job = Task.Job(_('Initializing storage device...')) + size = self.diskSize() + print '[HD] size: %s MB' % size + task = UnmountTask(job, self) + task = Task.PythonTask(job, _('Removing partition table')) + task.work = self.killPartitionTable + task.weighting = 1 + task = Task.LoggingTask(job, _('Rereading partition table')) + task.weighting = 1 + task.setTool('hdparm') + task.args.append('-z') + task.args.append(self.disk_path) + task = Task.ConditionTask(job, _('Waiting for partition'), timeoutCount=20) + task.check = lambda : not os.path.exists(self.partitionPath('1')) + task.weighting = 1 + if os.path.exists('/usr/sbin/parted'): + use_parted = True + elif size > 2097151: + addInstallTask(job, 'parted') + use_parted = True + else: + use_parted = False + task = Task.LoggingTask(job, _('Creating partition')) + task.weighting = 5 + if use_parted: + task.setTool('parted') + if size < 1024: + alignment = 'min' + else: + alignment = 'opt' + if size > 2097151: + parttype = 'gpt' + else: + parttype = 'msdos' + task.args += ['-a', + alignment, + '-s', + self.disk_path, + 'mklabel', + parttype, + 'mkpart', + 'primary', + '0%', + '100%'] + else: + task.setTool('sfdisk') + task.args.append('-f') + task.args.append('-uS') + task.args.append(self.disk_path) + if size > 128000: + print '[HD] Detected >128GB disk, using 4k alignment' + task.initial_input = '8,,L\n;0,0\n;0,0\n;0,0\ny\n' + else: + task.initial_input = ',,L\n;\n;\n;\ny\n' + task = Task.ConditionTask(job, _('Waiting for partition')) + task.check = lambda : os.path.exists(self.partitionPath('1')) + task.weighting = 1 + task = MkfsTask(job, _('Creating filesystem')) + big_o_options = ['dir_index'] + +###__blokada hash dla ext4 >>> +# if isFileSystemSupported('ext4'): +# task.setTool('mkfs.ext4') +# if size > 20000: +# try: +# version = map(int, open('/proc/version', 'r').read().split(' ', 4)[2].split('.', 2)[:2]) +# if version[0] > 3 or version[0] > 2 and version[1] >= 2: +# task.args += ['-C', '262144'] +# big_o_options.append('bigalloc') +# except Exception as ex: +# print 'Failed to detect Linux version:', ex +# else: +# task.setTool('mkfs.ext3') + + task.setTool('mkfs.ext3') + if size > 250000: + task.args += ['-T', + 'largefile', + '-N', + '262144'] + big_o_options.append('sparse_super') + elif size > 16384: + task.args += ['-T', 'largefile'] + big_o_options.append('sparse_super') + elif size > 2048: + task.args += ['-T', + 'largefile', + '-N', + str(size * 32)] + task.args += ['-m0', + '-O', + ','.join(big_o_options), + self.partitionPath('1')] + task = MountTask(job, self) + task.weighting = 3 + task = Task.ConditionTask(job, _('Waiting for mount'), timeoutCount=20) + task.check = self.mountDevice + task.weighting = 1 + return job + + def initialize(self): + return -5 + + def check(self): + return -5 + + def createCheckJob(self): + job = Task.Job(_('Checking filesystem...')) + if self.findMount(): + UnmountTask(job, self) + dev = self.mount_device + else: + dev = self.partitionPath('1') + task = Task.LoggingTask(job, 'fsck') + task.setTool('fsck.ext3') + task.args.append('-f') + task.args.append('-p') + task.args.append(dev) + MountTask(job, self) + task = Task.ConditionTask(job, _('Waiting for mount')) + task.check = self.mountDevice + return job + + def getDeviceDir(self): + return self.dev_path + + def getDeviceName(self): + return self.disk_path + + def readStats(self): + try: + l = open('/sys/block/%s/stat' % self.device).read() + except IOError: + return (-1, -1) + + data = l.split(None, 5) + return (int(data[0]), int(data[4])) + + def startIdle(self): + from enigma import eTimer + if self.bus() == _('External'): + Console().ePopen(('sdparm', + 'sdparm', + '--set=SCT=0', + self.disk_path)) + else: + Console().ePopen(('hdparm', + 'hdparm', + '-S0', + self.disk_path)) + self.timer = eTimer() + self.timer.callback.append(self.runIdle) + self.idle_running = True + self.setIdleTime(self.max_idle_time) + + def runIdle(self): + if not self.max_idle_time: + return + t = time.time() + idle_time = t - self.last_access + stats = self.readStats() + l = sum(stats) + if l != self.last_stat and l >= 0: + self.last_stat = l + self.last_access = t + idle_time = 0 + self.is_sleeping = False + if idle_time >= self.max_idle_time and not self.is_sleeping: + self.setSleep() + self.is_sleeping = True + + def setSleep(self): + if self.bus() == _('External'): + Console().ePopen(('sdparm', + 'sdparm', + '--flexible', + '--readonly', + '--command=stop', + self.disk_path)) + else: + Console().ePopen(('hdparm', + 'hdparm', + '-y', + self.disk_path)) + + def setIdleTime(self, idle): + self.max_idle_time = idle + if self.idle_running: + if not idle: + self.timer.stop() + else: + self.timer.start(idle * 100, False) + + def isSleeping(self): + return self.is_sleeping + + +class Partition(): + + def __init__(self, mountpoint, device = None, description = '', force_mounted = False): + self.mountpoint = mountpoint + self.description = description + self.force_mounted = mountpoint and force_mounted + self.is_hotplug = force_mounted + self.device = device + + def __str__(self): + return 'Partition(mountpoint=%s,description=%s,device=%s)' % (self.mountpoint, self.description, self.device) + + def stat(self): + if self.mountpoint: + return os.statvfs(self.mountpoint) + raise OSError, 'Device %s is not mounted' % self.device + + def free(self): + try: + s = self.stat() + return s.f_bavail * s.f_bsize + except OSError: + return None + + return None + + def total(self): + try: + s = self.stat() + return s.f_blocks * s.f_bsize + except OSError: + return None + + return None + + def tabbedDescription(self): + if self.mountpoint.startswith('/media/net') or self.mountpoint.startswith('/media/autofs'): + return self.description + return self.description + '\t' + self.mountpoint + + def mounted(self, mounts = None): + if self.force_mounted: + return True + else: + if self.mountpoint: + if mounts is None: + mounts = getProcMounts() + for parts in mounts: + if self.mountpoint.startswith(parts[1]): + return True + + return False + + def filesystem(self, mounts = None): + if self.mountpoint: + if mounts is None: + mounts = getProcMounts() + for fields in mounts: + if self.mountpoint.endswith('/') and not self.mountpoint == '/': + if fields[1] + '/' == self.mountpoint: + return fields[2] + elif fields[1] == self.mountpoint: + return fields[2] + + return '' + + +def addInstallTask(job, package): + task = Task.LoggingTask(job, 'update packages') + task.setTool('opkg') + task.args.append('update') + task = Task.LoggingTask(job, 'Install ' + package) + task.setTool('opkg') + task.args.append('install') + task.args.append(package) + + +class HarddiskManager(): + + def __init__(self): + self.hdd = [] + self.cd = '' + self.partitions = [] + self.devices_scanned_on_init = [] + self.on_partition_list_change = CList() + self.enumerateBlockDevices() + p = (('/media/hdd', _('Hard disk')), + ('/media/card', _('Card')), + ('/media/cf', _('Compact flash')), + ('/media/mmc1', _('MMC card')), + ('/media/net', _('Network mount')), + ('/media/net1', _('Network mount %s') % '1'), + ('/media/net2', _('Network mount %s') % '2'), + ('/media/net3', _('Network mount %s') % '3'), + ('/media/ram', _('Ram disk')), + ('/media/usb', _('USB stick')), + ('/media/usb1', _('USB1 stick')), + ('/media/usb2', _('USB2 stick')), + ('/', _('Internal flash'))) + known = set([ os.path.normpath(a.mountpoint) for a in self.partitions if a.mountpoint ]) + for m, d in p: + if m not in known and os.path.ismount(m): + self.partitions.append(Partition(mountpoint=m, description=d)) + + def getBlockDevInfo(self, blockdev): + HasMMC = fileExists('/proc/cmdline') and 'root=/dev/mmcblk' in open('/proc/cmdline', 'r').read() + devpath = '/sys/block/' + blockdev + error = False + removable = False + blacklisted = False + is_cdrom = False + partitions = [] + try: + if os.path.exists(devpath + '/removable'): + removable = bool(int(readFile(devpath + '/removable'))) + if os.path.exists(devpath + '/dev'): + dev = int(readFile(devpath + '/dev').split(':')[0]) + else: + dev = None + blacklisted = dev in [1, + 7, + 31, + 253, + 254] + (['HasMMC'] and [179] or []) + if blockdev[0:2] == 'sr': + is_cdrom = True + if blockdev[0:2] == 'hd': + try: + media = readFile('/proc/ide/%s/media' % blockdev) + if 'cdrom' in media: + is_cdrom = True + except IOError: + error = True + + if not is_cdrom and os.path.exists(devpath): + for partition in os.listdir(devpath): + if partition[0:len(blockdev)] != blockdev: + continue + partitions.append(partition) + + else: + self.cd = blockdev + except IOError: + error = True + + medium_found = True + try: + open('/dev/' + blockdev).close() + except IOError as err: + if err.errno == 159: + medium_found = False + + return (error, + blacklisted, + removable, + is_cdrom, + partitions, + medium_found) + + def enumerateBlockDevices(self): + print '[Harddisk] enumerating block devices...' + for blockdev in os.listdir('/sys/block'): + error, blacklisted, removable, is_cdrom, partitions, medium_found = self.addHotplugPartition(blockdev) + if not error and not blacklisted and medium_found: + for part in partitions: + self.addHotplugPartition(part) + + self.devices_scanned_on_init.append((blockdev, + removable, + is_cdrom, + medium_found)) + + def getAutofsMountpoint(self, device): + r = self.getMountpoint(device) + if r is None: + return '/media/' + device + else: + return r + + def getMountpoint(self, device): + dev = '/dev/%s' % device + for item in getProcMounts(): + if item[0] == dev: + return item[1] + + return None + + def addHotplugPartition(self, device, physdev = None): + if not physdev: + dev, part = self.splitDeviceName(device) + try: + physdev = os.path.realpath('/sys/block/' + dev + '/device')[4:] + except OSError: + physdev = dev + print "couldn't determine blockdev physdev for device", device + + error, blacklisted, removable, is_cdrom, partitions, medium_found = self.getBlockDevInfo(device) + if not blacklisted and medium_found: + description = self.getUserfriendlyDeviceName(device, physdev) + p = Partition(mountpoint=self.getMountpoint(device), description=description, force_mounted=True, device=device) + self.partitions.append(p) + if p.mountpoint: + self.on_partition_list_change('add', p) + l = len(device) + if l and (not device[l - 1].isdigit() or device == 'mmcblk0'): + self.hdd.append(Harddisk(device, removable)) + self.hdd.sort() + SystemInfo['Harddisk'] = True + return (error, + blacklisted, + removable, + is_cdrom, + partitions, + medium_found) + + def addHotplugAudiocd(self, device, physdev = None): + if not physdev: + dev, part = self.splitDeviceName(device) + try: + physdev = os.path.realpath('/sys/block/' + dev + '/device')[4:] + except OSError: + physdev = dev + print "couldn't determine blockdev physdev for device", device + + error, blacklisted, removable, is_cdrom, partitions, medium_found = self.getBlockDevInfo(device) + if not blacklisted and medium_found: + description = self.getUserfriendlyDeviceName(device, physdev) + p = Partition(mountpoint='/media/audiocd', description=description, force_mounted=True, device=device) + self.partitions.append(p) + self.on_partition_list_change('add', p) + SystemInfo['Harddisk'] = False + return (error, + blacklisted, + removable, + is_cdrom, + partitions, + medium_found) + + def removeHotplugPartition(self, device): + for x in self.partitions[:]: + if x.device == device: + self.partitions.remove(x) + if x.mountpoint: + self.on_partition_list_change('remove', x) + + l = len(device) + if l and not device[l - 1].isdigit(): + for hdd in self.hdd: + if hdd.device == device: + hdd.stop() + self.hdd.remove(hdd) + break + + SystemInfo['Harddisk'] = len(self.hdd) > 0 + + def HDDCount(self): + return len(self.hdd) + + def HDDList(self): + list = [] + for hd in self.hdd: + hdd = hd.model() + ' - ' + hd.bus() + cap = hd.capacity() + if cap != '': + hdd += ' (' + cap + ')' + list.append((hdd, hd)) + + return list + + def getCD(self): + return self.cd + + def getMountedPartitions(self, onlyhotplug = False, mounts = None): + if mounts is None: + mounts = getProcMounts() + parts = [ x for x in self.partitions if (x.is_hotplug or not onlyhotplug) and x.mounted(mounts) ] + devs = set([ x.device for x in parts ]) + for devname in devs.copy(): + if not devname: + continue + dev, part = self.splitDeviceName(devname) + if part and dev in devs: + devs.remove(dev) + + return [ x for x in parts if not x.device or x.device in devs ] + + def splitDeviceName(self, devname): + dev = devname[:3] + part = devname[3:] + for p in part: + if not p.isdigit(): + return (devname, 0) + + return (dev, part and int(part) or 0) + + def getUserfriendlyDeviceName(self, dev, phys): + dev, part = self.splitDeviceName(dev) + description = _('External Storage %s') % dev + try: + description = readFile('/sys' + phys + '/model') + except IOError as s: + print "couldn't read model: ", s + + if part and part != 1: + description += _(' (Partition %d)') % part + return description + + def addMountedPartition(self, device, desc): + for x in self.partitions: + if x.mountpoint == device: + return + + self.partitions.append(Partition(mountpoint=device, description=desc)) + + def removeMountedPartition(self, mountpoint): + for x in self.partitions[:]: + if x.mountpoint == mountpoint: + self.partitions.remove(x) + self.on_partition_list_change('remove', x) + + def setDVDSpeed(self, device, speed = 0): + ioctl_flag = int(21282) + if not device.startswith('/'): + device = '/dev/' + device + try: + from fcntl import ioctl + cd = open(device) + ioctl(cd.fileno(), ioctl_flag, speed) + cd.close() + except Exception as ex: + print '[Harddisk] Failed to set %s speed to %s' % (device, speed), ex + + +class UnmountTask(Task.LoggingTask): + + def __init__(self, job, hdd): + Task.LoggingTask.__init__(self, job, _('Unmount')) + self.hdd = hdd + self.mountpoints = [] + + def prepare(self): + try: + dev = self.hdd.disk_path.split('/')[-1] + open('/dev/nomount.%s' % dev, 'wb').close() + except Exception as e: + print 'ERROR: Failed to create /dev/nomount file:', e + + self.setTool('umount') + self.args.append('-f') + for dev in self.hdd.enumMountDevices(): + self.args.append(dev) + self.postconditions.append(Task.ReturncodePostcondition()) + self.mountpoints.append(dev) + + if not self.mountpoints: + print 'UnmountTask: No mountpoints found?' + self.cmd = 'true' + self.args = [self.cmd] + + def afterRun(self): + for path in self.mountpoints: + try: + os.rmdir(path) + except Exception as ex: + print "Failed to remove path '%s':" % path, ex + + +class MountTask(Task.LoggingTask): + + def __init__(self, job, hdd): + Task.LoggingTask.__init__(self, job, _('Mount')) + self.hdd = hdd + + def prepare(self): + try: + dev = self.hdd.disk_path.split('/')[-1] + os.unlink('/dev/nomount.%s' % dev) + except Exception as e: + print 'ERROR: Failed to remove /dev/nomount file:', e + + if self.hdd.mount_device is None: + dev = self.hdd.partitionPath('1') + else: + dev = self.hdd.mount_device + fstab = open('/etc/fstab') + lines = fstab.readlines() + fstab.close() + for line in lines: + parts = line.strip().split(' ') + fspath = os.path.realpath(parts[0]) + if os.path.realpath(fspath) == dev: + self.setCmdline('mount -t auto ' + fspath) + self.postconditions.append(Task.ReturncodePostcondition()) + return + + if self.hdd.type == DEVTYPE_UDEV: + self.setCmdline('sleep 2; hdparm -z ' + self.hdd.disk_path) + self.postconditions.append(Task.ReturncodePostcondition()) + return + + +class MkfsTask(Task.LoggingTask): + + def prepare(self): + self.fsck_state = None + return + + def processOutput(self, data): + print '[Mkfs]', data + if 'Writing inode tables:' in data: + self.fsck_state = 'inode' + elif 'Creating journal' in data: + self.fsck_state = 'journal' + self.setProgress(80) + elif 'Writing superblocks ' in data: + self.setProgress(95) + elif self.fsck_state == 'inode': + if '/' in data: + try: + d = data.strip(' \x08\r\n').split('/', 1) + if '\x08' in d[1]: + d[1] = d[1].split('\x08', 1)[0] + self.setProgress(80 * int(d[0]) / int(d[1])) + except Exception as e: + print '[Mkfs] E:', e + + return + self.log.append(data) + + +###########################__From HarddiskSetup_################################ +class HarddiskSetup(Screen): + + def __init__(self, session, hdd, action, text, question): + Screen.__init__(self, session) + self.action = action + self.question = question + self.setTitle(_('Setup hard disk')) + self['model'] = Label(_('Model: ') + hdd.model()) + self['capacity'] = Label(_('Capacity: ') + hdd.capacity()) + self['bus'] = Label(_('Bus: ') + hdd.bus()) + self['key_red'] = Label(_('Cancel')) + self['key_green'] = Label(text) + self['actions'] = ActionMap(['OkCancelActions'], {'ok': self.hddQuestion, + 'cancel': self.close}) + self['shortcuts'] = ActionMap(['ShortcutActions'], {'red': self.close, + 'green': self.hddQuestion}) + + def hddQuestion(self): + message = self.question + '\n' + _('You can continue watching TV etc. while this is running.') + self.session.openWithCallback(self.hddConfirmed, MessageBox, message) + + def hddConfirmed(self, confirmed): + if not confirmed: + return + from Components.Task import job_manager + try: + job = self.action() + job_manager.AddJob(job, onSuccess=job_manager.popupTaskView) + from Screens.TaskView import JobView + self.session.open(JobView, job, afterEventChangeable=False) + except Exception as ex: + self.session.open(MessageBox, str(ex), type=MessageBox.TYPE_ERROR, timeout=10) + + self.close() + + +class HarddiskSelection(Screen): + def __init__(self, session): + Screen.__init__(self, session) + self.setTitle(_('Select hard disk')) + self.skinName = 'HarddiskSelection' + if harddiskmanager.HDDCount() == 0: + tlist = [] + tlist.append((_('no storage devices found'), 0)) + self['hddlist'] = MenuList(tlist) + else: + self['hddlist'] = MenuList(harddiskmanager.HDDList()) + self['key_red'] = Label(_('Cancel')) + self['key_green'] = Label(_('Select')) + self['actions'] = ActionMap(['OkCancelActions'], {'ok': self.okbuttonClick, + 'cancel': self.close}) + self['shortcuts'] = ActionMap(['ShortcutActions'], {'red': self.close, + 'green': self.okbuttonClick}) + + def doIt(self, selection): + self.session.openWithCallback(self.close, HarddiskSetup, selection, action=selection.createInitializeJob, text=_('Initialize'), question=_('Do you really want to initialize the device?\nAll data on the disk will be lost!')) + + def okbuttonClick(self): + selection = self['hddlist'].getCurrent() + if selection[1] != 0: + self.doIt(selection[1]) + + +class HarddiskFsckSelection(HarddiskSelection): + + def doIt(self, selection): + self.session.openWithCallback(self.close, HarddiskSetup, selection, action=selection.createCheckJob, text=_('Check'), question=_('Do you really want to check the filesystem?\nThis could take lots of time!')) +###########################__end HarddiskSetup_################################ + + +harddiskmanager = HarddiskManager() + +def isSleepStateDevice(device): + ret = os.popen('hdparm -C %s' % device).read() + if 'SG_IO' in ret or 'HDIO_DRIVE_CMD' in ret: + return None + elif 'drive state is: standby' in ret or 'drive state is: idle' in ret: + return True + elif 'drive state is: active/idle' in ret: + return False + else: + return None + + +def internalHDDNotSleeping(external = False): + state = False + if harddiskmanager.HDDCount(): + for hdd in harddiskmanager.HDDList(): + if hdd[1].internal or external: + if hdd[1].idle_running and hdd[1].max_idle_time and not hdd[1].isSleeping(): + state = True + + return state + + +harddiskmanager = HarddiskManager() +SystemInfo['ext4'] = isFileSystemSupported('ext4') or isFileSystemSupported('ext3') diff --git a/NeoBoot/files/Task.py b/NeoBoot/files/Task.py new file mode 100644 index 0000000..18d2beb --- /dev/null +++ b/NeoBoot/files/Task.py @@ -0,0 +1,524 @@ +# -*- coding: utf-8 -*- + +#from __future__ import print_function +#from Plugins.Extensions.NeoBoot.__init__ import _ +from Tools.CList import CList + +class Job(object): + NOT_STARTED, IN_PROGRESS, FINISHED, FAILED = range(4) + + def __init__(self, name): + self.tasks = [] + self.resident_tasks = [] + self.workspace = '/tmp' + self.current_task = 0 + self.callback = None + self.name = name + self.finished = False + self.end = 100 + self.__progress = 0 + self.weightScale = 1 + self.afterEvent = None + self.state_changed = CList() + self.status = self.NOT_STARTED + self.onSuccess = None + return + + def fromDescription(self, description): + pass + + def createDescription(self): + return None + + def getProgress(self): + if self.current_task == len(self.tasks): + return self.end + t = self.tasks[self.current_task] + jobprogress = t.weighting * t.progress / float(t.end) + sum([ task.weighting for task in self.tasks[:self.current_task] ]) + return int(jobprogress * self.weightScale) + + progress = property(getProgress) + + def getStatustext(self): + return {self.NOT_STARTED: _('Waiting'), + self.IN_PROGRESS: _('In progress'), + self.FINISHED: _('Finished'), + self.FAILED: _('Failed')}[self.status] + + def task_progress_changed_CB(self): + self.state_changed() + + def addTask(self, task): + task.job = self + task.task_progress_changed = self.task_progress_changed_CB + self.tasks.append(task) + + def start(self, callback): + self.callback = callback + self.restart() + + def restart(self): + self.status = self.IN_PROGRESS + self.state_changed() + self.runNext() + sumTaskWeightings = sum([ t.weighting for t in self.tasks ]) or 1 + self.weightScale = self.end / float(sumTaskWeightings) + + def runNext(self): + if self.current_task == len(self.tasks): + if len(self.resident_tasks) == 0: + self.status = self.FINISHED + self.state_changed() + self.callback(self, None, []) + self.callback = None + else: + print 'still waiting for %d resident task(s) %s to finish' % (len(self.resident_tasks), str(self.resident_tasks)) + else: + self.tasks[self.current_task].run(self.taskCallback) + self.state_changed() + return + + def taskCallback(self, task, res, stay_resident = False): + cb_idx = self.tasks.index(task) + if stay_resident: + if cb_idx not in self.resident_tasks: + self.resident_tasks.append(self.current_task) + print 'task going resident:', task + else: + print 'task keeps staying resident:', task + return + if len(res): + print '>>> Error:', res + self.status = self.FAILED + self.state_changed() + self.callback(self, task, res) + if cb_idx != self.current_task: + if cb_idx in self.resident_tasks: + print 'resident task finished:', task + self.resident_tasks.remove(cb_idx) + if res == []: + self.state_changed() + self.current_task += 1 + self.runNext() + + def retry(self): + self.restart() + + def abort(self): + if self.current_task < len(self.tasks): + self.tasks[self.current_task].abort() + for i in self.resident_tasks: + self.tasks[i].abort() + + def cancel(self): + self.abort() + + def __str__(self): + return 'Components.Task.Job name=%s #tasks=%s' % (self.name, len(self.tasks)) + + +class Task(object): + + def __init__(self, job, name): + self.name = name + self.immediate_preconditions = [] + self.global_preconditions = [] + self.postconditions = [] + self.returncode = None + self.initial_input = None + self.job = None + self.end = 100 + self.weighting = 100 + self.__progress = 0 + self.cmd = None + self.cwd = '/tmp' + self.args = [] + self.cmdline = None + self.task_progress_changed = None + self.output_line = '' + job.addTask(self) + self.container = None + return + + def setCommandline(self, cmd, args): + self.cmd = cmd + self.args = args + + def setTool(self, tool): + self.cmd = tool + self.args = [tool] + self.global_preconditions.append(ToolExistsPrecondition()) + self.postconditions.append(ReturncodePostcondition()) + + def setCmdline(self, cmdline): + self.cmdline = cmdline + + def checkPreconditions(self, immediate = False): + not_met = [] + if immediate: + preconditions = self.immediate_preconditions + else: + preconditions = self.global_preconditions + for precondition in preconditions: + if not precondition.check(self): + not_met.append(precondition) + + return not_met + + def _run(self): + if self.cmd is None and self.cmdline is None: + self.finish() + return + else: + from enigma import eConsoleAppContainer + self.container = eConsoleAppContainer() + self.container.appClosed.append(self.processFinished) + self.container.stdoutAvail.append(self.processStdout) + self.container.stderrAvail.append(self.processStderr) + if self.cwd is not None: + self.container.setCWD(self.cwd) + if not self.cmd and self.cmdline: + print 'execute:', self.container.execute(self.cmdline), self.cmdline + else: + print 'execute:', self.container.execute(self.cmd, *self.args), ' '.join(self.args) + if self.initial_input: + self.writeInput(self.initial_input) + return + return + + def run(self, callback): + failed_preconditions = self.checkPreconditions(True) + self.checkPreconditions(False) + if failed_preconditions: + print '[Task] preconditions failed' + callback(self, failed_preconditions) + return + self.callback = callback + try: + self.prepare() + self._run() + except Exception as ex: + print '[Task] exception:', ex + self.postconditions = [FailedPostcondition(ex)] + self.finish() + + def prepare(self): + pass + + def cleanup(self, failed): + pass + + def processStdout(self, data): + self.processOutput(data) + + def processStderr(self, data): + self.processOutput(data) + + def processOutput(self, data): + self.output_line += data + while True: + i = self.output_line.find('\n') + if i == -1: + break + self.processOutputLine(self.output_line[:i + 1]) + self.output_line = self.output_line[i + 1:] + + def processOutputLine(self, line): + print '[Task %s]' % self.name, line[:-1] + + def processFinished(self, returncode): + self.returncode = returncode + self.finish() + + def abort(self): + if self.container: + self.container.kill() + self.finish(aborted=True) + + def finish(self, aborted = False): + self.afterRun() + not_met = [] + if aborted: + not_met.append(AbortedPostcondition()) + else: + for postcondition in self.postconditions: + if not postcondition.check(self): + not_met.append(postcondition) + + self.cleanup(not_met) + self.callback(self, not_met) + + def afterRun(self): + pass + + def writeInput(self, input): + self.container.write(input) + + def getProgress(self): + return self.__progress + + def setProgress(self, progress): + if progress > self.end: + progress = self.end + if progress < 0: + progress = 0 + self.__progress = progress + if self.task_progress_changed: + self.task_progress_changed() + + progress = property(getProgress, setProgress) + + def __str__(self): + return 'Components.Task.Task name=%s' % self.name + + +class LoggingTask(Task): + + def __init__(self, job, name): + Task.__init__(self, job, name) + self.log = [] + + def processOutput(self, data): + print '[%s]' % self.name, data, + self.log.append(data) + + +class PythonTask(Task): + + def _run(self): + from twisted.internet import threads + from enigma import eTimer + self.aborted = False + self.pos = 0 + threads.deferToThread(self.work).addBoth(self.onComplete) + self.timer = eTimer() + self.timer.callback.append(self.onTimer) + self.timer.start(5) + + def work(self): + raise NotImplemented, 'work' + + def abort(self): + self.aborted = True + if self.callback is None: + self.finish(aborted=True) + return + + def onTimer(self): + self.setProgress(self.pos) + + def onComplete(self, result): + self.postconditions.append(FailedPostcondition(result)) + self.timer.stop() + del self.timer + self.finish() + + +class ConditionTask(Task): + + def __init__(self, job, name, timeoutCount = None): + Task.__init__(self, job, name) + self.timeoutCount = timeoutCount + + def _run(self): + self.triggerCount = 0 + + def prepare(self): + from enigma import eTimer + self.timer = eTimer() + self.timer.callback.append(self.trigger) + self.timer.start(1000) + + def cleanup(self, failed): + if hasattr(self, 'timer'): + self.timer.stop() + del self.timer + + def check(self): + return True + + def trigger(self): + self.triggerCount += 1 + try: + if self.timeoutCount is not None and self.triggerCount > self.timeoutCount: + raise Exception, 'Timeout elapsed, sorry' + res = self.check() + except Exception as e: + self.postconditions.append(FailedPostcondition(e)) + res = True + + if res: + self.finish() + return + + +class JobManager: + + def __init__(self): + self.active_jobs = [] + self.failed_jobs = [] + self.job_classes = [] + self.in_background = False + self.visible = False + self.active_job = None + return + + def AddJob(self, job, onSuccess = None, onFail = None): + job.onSuccess = onSuccess + if onFail is None: + job.onFail = self.notifyFailed + else: + job.onFail = onFail + self.active_jobs.append(job) + self.kick() + return + + def kick(self): + if self.active_job is None: + if self.active_jobs: + self.active_job = self.active_jobs.pop(0) + self.active_job.start(self.jobDone) + return + + def notifyFailed(self, job, task, problems): + from Tools import Notifications + from Screens.MessageBox import MessageBox + if problems[0].RECOVERABLE: + Notifications.AddNotificationWithCallback(self.errorCB, MessageBox, _('Error: %s\nRetry?') % problems[0].getErrorMessage(task)) + return True + else: + Notifications.AddNotification(MessageBox, job.name + '\n' + _('Error') + ': %s' % problems[0].getErrorMessage(task), type=MessageBox.TYPE_ERROR) + return False + + def jobDone(self, job, task, problems): + print 'job', job, 'completed with', problems, 'in', task + if problems: + if not job.onFail(job, task, problems): + self.errorCB(False) + else: + self.active_job = None + if job.onSuccess: + job.onSuccess(job) + self.kick() + return + + def popupTaskView(self, job): + if not self.visible: + from Tools import Notifications + from Screens.TaskView import JobView + self.visible = True + Notifications.AddNotification(JobView, job) + + def errorCB(self, answer): + if answer: + print 'retrying job' + self.active_job.retry() + else: + print 'not retrying job.' + self.failed_jobs.append(self.active_job) + self.active_job = None + self.kick() + return + + def getPendingJobs(self): + list = [] + if self.active_job: + list.append(self.active_job) + list += self.active_jobs + return list + + +class Condition: + RECOVERABLE = False + + def getErrorMessage(self, task): + return _('An unknown error occurred!') + ' (%s @ task %s)' % (self.__class__.__name__, task.__class__.__name__) + + +class WorkspaceExistsPrecondition(Condition): + + def check(self, task): + return os.access(task.job.workspace, os.W_OK) + + +class DiskspacePrecondition(Condition): + + def __init__(self, diskspace_required): + self.diskspace_required = diskspace_required + self.diskspace_available = 0 + + def check(self, task): + import os + try: + s = os.statvfs(task.job.workspace) + self.diskspace_available = s.f_bsize * s.f_bavail + return self.diskspace_available >= self.diskspace_required + except OSError: + return False + + def getErrorMessage(self, task): + return _('Not enough disk space. Please free up some disk space and try again. (%d MB required, %d MB available)') % (self.diskspace_required / 1024 / 1024, self.diskspace_available / 1024 / 1024) + + +class ToolExistsPrecondition(Condition): + + def check(self, task): + import os + if task.cmd[0] == '/': + self.realpath = task.cmd + print '[Task.py][ToolExistsPrecondition] WARNING: usage of absolute paths for tasks should be avoided!' + return os.access(self.realpath, os.X_OK) + self.realpath = task.cmd + path = os.environ.get('PATH', '').split(os.pathsep) + path.append(task.cwd + '/') + absolutes = filter(lambda file: os.access(file, os.X_OK), map(lambda directory, file = task.cmd: os.path.join(directory, file), path)) + if absolutes: + self.realpath = absolutes[0] + return True + return False + + def getErrorMessage(self, task): + return _('A required tool (%s) was not found.') % self.realpath + + +class AbortedPostcondition(Condition): + + def getErrorMessage(self, task): + return 'Cancelled upon user request' + + +class ReturncodePostcondition(Condition): + + def check(self, task): + return task.returncode == 0 + + def getErrorMessage(self, task): + if hasattr(task, 'log') and task.log: + log = ''.join(task.log).strip() + log = log.split('\n')[-3:] + log = '\n'.join(log) + return log + else: + return _('Error code') + ': %s' % task.returncode + + +class FailedPostcondition(Condition): + + def __init__(self, exception): + self.exception = exception + + def getErrorMessage(self, task): + if isinstance(self.exception, int): + if hasattr(task, 'log'): + log = ''.join(task.log).strip() + log = log.split('\n')[-4:] + log = '\n'.join(log) + return log + else: + return _('Error code') + ' %s' % self.exception + return str(self.exception) + + def check(self, task): + return self.exception is None or self.exception == 0 + + +job_manager = JobManager() \ No newline at end of file diff --git a/NeoBoot/files/devices.py b/NeoBoot/files/devices.py index 6cfe450..fb0f4a5 100644 --- a/NeoBoot/files/devices.py +++ b/NeoBoot/files/devices.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- -from __init__ import _ + +from Plugins.Extensions.NeoBoot.__init__ import _ from enigma import getDesktop from Plugins.Plugin import PluginDescriptor from Screens.ChoiceBox import ChoiceBox @@ -31,27 +31,46 @@ import os from Screens.VirtualKeyBoard import VirtualKeyBoard import gettext, os from Plugins.Extensions.NeoBoot.files.stbbranding import getTunerModel +LinkNeoBoot = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot' - -try: - cat = gettext.translation('lang', '/usr/lib/enigma2/python/Plugins/Extensions/files/po', [config.osd.language.getText()]) - _ = cat.gettext -except IOError: - pass - + class ManagerDevice(Screen): screenwidth = getDesktop(0).size().width() if screenwidth and screenwidth == 1920: - skin = '\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\t{"template": [\n\t\t\t\t MultiContentEntryText(pos = (90, 5), size = (600, 30), font=0, text = 0),\n\t\t\t\t MultiContentEntryText(pos = (110, 60), size = (900, 100), font=1, flags = RT_VALIGN_TOP, text = 1),\n\t\t\t\t MultiContentEntryPixmapAlphaBlend(pos = (0, 0), size = (160, 160,), png = 2),\n\t\t\t\t],\n\t\t\t\t"fonts": [gFont("Regular", 33),gFont("Regular", 33)],\n\t\t\t\t"itemHeight": 140\n\t\t\t\t}\n\t\t\t\n\t\t\n\t\t\n\t' + + skin = """ + + + + + + + + + \n\n\t\t\t\t{"template": [\n\n\t\t\t\t MultiContentEntryText(pos = (90, 5), size = (600, 75), font=0, text = 0),\n\n\t\t\t\t MultiContentEntryText(pos = (110, 60), size = (900, 80), font=1, flags = RT_VALIGN_TOP, text = 1),\n\n\t\t\t\t MultiContentEntryPixmapAlphaBlend(pos = (0, 0), size = (150, 130,)),\n\n\t\t\t\t],\n\t\t\t\t"fonts": [gFont("Regular", 33),gFont("Regular", 33)],\n\n\t\t\t\t"itemHeight": 140\n\t\t\t\t} + + + """ else: - skin = '\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t \n\t\t\n\t\t\t\n\t\t\t\t{"template": [\n\t\t\t\t MultiContentEntryText(pos = (90, 0), size = (600, 30), font=0, text = 0),\n\t\t\t\t MultiContentEntryText(pos = (110, 30), size = (600, 50), font=1, flags = RT_VALIGN_TOP, text = 1),\n\t\t\t\t MultiContentEntryPixmapAlphaBlend(pos = (0, 0), size = (80, 80), png = 2),\n\t\t\t\t],\n\t\t\t\t"fonts": [gFont("Regular", 24),gFont("Regular", 20)],\n\t\t\t\t"itemHeight": 85\n\t\t\t\t}\n\t\t\t\n\t\t\n\t\t\n\t' + skin = """ + + + + + + + \n\t\t\t\t{"template": [\n\t\t\t\t MultiContentEntryText(pos = (90, 0), size = (600, 30), font=0, text = 0),\n\t\t\t\t MultiContentEntryText(pos = (110, 30), size = (600, 50), font=1, flags = RT_VALIGN_TOP, text = 1),\n\t\t\t\t MultiContentEntryPixmapAlphaBlend(pos = (0, 0), size = (80, 80)),\n\t\t\t\t],\n\t\t\t\t"fonts": [gFont("Regular", 24),gFont("Regular", 20)],\n\t\t\t\t"itemHeight": 85\n\t\t\t\t}\n\t\t\t + + + """ + def __init__(self, session): Screen.__init__(self, session) Screen.setTitle(self, _('Mount Manager')) - self['key_red'] = Label(_('Initialize')) + self['key_red'] = Label(_('Initialize ext3')) self['key_green'] = Label(_('SetupMounts')) - self['key_yellow'] = Label(_('Unmount')) + self['key_yellow'] = Label(_('Initialize ext4')) self['key_blue'] = Label(_('Exit')) self['lab1'] = Label() self.onChangedEntry = [] @@ -59,15 +78,27 @@ class ManagerDevice(Screen): self['list'] = List(self.list) self['list'].onSelectionChanged.append(self.selectionChanged) self['actions'] = ActionMap(['WizardActions', 'ColorActions', 'MenuActions'], {'back': self.close, - 'red': self.Format, + 'red': self.Format_ext3, 'green': self.SetupMounts, - 'yellow': self.Unmount, - 'blue': self.Mount}) + 'yellow': self.Format_ext4, + 'blue': self.ExitBack, + 'back': self.close}) self.activityTimer = eTimer() self.activityTimer.timeout.get().append(self.updateList2) self.updateList() self.onShown.append(self.setWindowTitle) + def Format_ext3(self): + from Harddisk import HarddiskSelection + self.session.openWithCallback(self.updateList, HarddiskSelection) + + def Format_ext4(self): + from Screens.HarddiskSetup import HarddiskSelection + self.session.openWithCallback(self.updateList, HarddiskSelection) + + def ExitBack(self): + self.close() + def setWindowTitle(self): self.setTitle(_('Mount Manager')) @@ -123,20 +154,24 @@ class ManagerDevice(Screen): device2 = re.sub('[0-9]', '', device) devicetype = path.realpath('/sys/block/' + device2 + '/device') d2 = device - name = _('HARD DISK: ') - mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_hdd.png' + name = _('HARD DISK: ') + mypixmap = '' + LinkNeoBoot + '/images/dev_hdd.png' model = file('/sys/block/' + device2 + '/device/model').read() model = str(model).replace('\n', '') des = '' if devicetype.find('usb') != -1: name = _('USB: ') - mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png' + mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png' if devicetype.find('usb1') != -1: name = _('USB1: ') - mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png' + mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png' if devicetype.find('usb2') != -1: name = _('USB2: ') - mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png' + mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png' + if devicetype.find('card') != -1: + name = _('CARD: ') + mypixmap = '' + LinkNeoBoot + '/images/dev_sd.png' + name = name + model self.Console = Console() self.Console.ePopen("sfdisk -l /dev/sd? | grep swap | awk '{print $(NF-9)}' >/tmp/devices.tmp") @@ -198,13 +233,6 @@ class ManagerDevice(Screen): os.system('cp /etc/fstab.org /etc/fstab') self.session.openWithCallback(self.updateList, DevicesConf) - def Format(self): - from Screens.HarddiskSetup import HarddiskSelection - self.session.openWithCallback(self.updateList, HarddiskSelection) - - def Mount(self): - self.close() - def Unmount(self): sel = self['list'].getCurrent() if sel: @@ -270,9 +298,19 @@ class ManagerDevice(Screen): class DevicesConf(Screen, ConfigListScreen): screenwidth = getDesktop(0).size().width() if screenwidth and screenwidth == 1920: - skin = '\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t' + skin = """ + + + + + """ else: - skin = '\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t' + skin = """ + + + + + """ def __init__(self, session): Screen.__init__(self, session) @@ -326,19 +364,23 @@ class DevicesConf(Screen, ConfigListScreen): devicetype = path.realpath('/sys/block/' + device2 + '/device') d2 = device name = _('HARD DISK: ') - mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_hdd.png' + mypixmap = '' + LinkNeoBoot + '/images/dev_hdd.png' model = file('/sys/block/' + device2 + '/device/model').read() model = str(model).replace('\n', '') des = '' if devicetype.find('usb') != -1: name = _('USB: ') - mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png' + mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png' if devicetype.find('usb1') != -1: name = _('USB1: ') - mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png' + mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png' if devicetype.find('usb2') != -1: name = _('USB2: ') - mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png' + mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png' + if devicetype.find('card') != -1: + name = _('CARD: ') + mypixmap = '' + LinkNeoBoot + '/images/dev_sd.png' + name = name + model f = open('/proc/mounts', 'r') for line in f.readlines(): @@ -369,7 +411,11 @@ class DevicesConf(Screen, ConfigListScreen): ('/media/usb', '/media/usb'), ('/media/usb1', '/media/usb1'), ('/media/usb2', '/media/usb2'), - ('/media/usb3', '/media/usb3')])) + ('/media/usb3', '/media/usb3'), + ('/media/usb3', '/media/cf'), + ('/media/usb3', '/media/card'), + ('/media/cf', '/media/cf'), + ('/media/card', '/media/card')])) if dtype == 'Linux': dtype = 'ext2', 'ext3', 'ext4' else: @@ -434,73 +480,77 @@ class DevicesConf(Screen, ConfigListScreen): out.close() self.device_uuid2 = result.split('UUID=')[1].split(' ')[0].replace('"', '') - if fileExists('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager2'): - out1 = open('/etc/devicemanager.cfg', 'a') - line1 = '"' + self.device_uuid2 + '"' + ':' + self.mountp + '\n' - out1.write(line1) - out1.close() - elif fileExists('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager'): - out2 = open('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager/devicemanager.cfg', 'a') - line2 = '"' + self.device_uuid2 + '"' + ':' + self.mountp + '\n' - out2.write(line2) - out2.close() - - if fileExists('/etc/init.d/udev'): - filename = '/etc/init.d/udev' - if os.path.exists(filename): +# if fileExists('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager2'): +# out1 = open('/etc/devicemanager.cfg', 'a') +# line1 = '"' + self.device_uuid2 + '"' + ':' + self.mountp + '\n' +# out1.write(line1) +# out1.close() +# elif fileExists('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager'): +# out2 = open('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager/devicemanager.cfg', 'a') +# line2 = '"' + self.device_uuid2 + '"' + ':' + self.mountp + '\n' +# out2.write(line2) +# out2.close() + - filename2 = filename + '.tmp' - out = open(filename2, 'w') - f = open(filename, 'r') - for line in f.readlines(): - if line.find('mount -a /media/hdd; mount -a /media/usb') != -1: - line = '' - out.write(line) - - f.close() - out.close() - os.rename(filename2, filename) + - filename2 = filename + '.tmp' - out = open(filename2, 'w') - f = open(filename, 'r') - for line in f.readlines(): - if line.find('exit 0') != -1: - line = '' - out.write(line) - - f.close() - out.close() - os.rename(filename2, filename) - os.system('echo "mount -a /media/hdd; mount -a /media/usb" >> /etc/init.d/udev; chmod 0755 /etc/init.d/udev ') - - if fileExists('/etc/init.d/mdev'): - filename = '/etc/init.d/mdev' - if os.path.exists(filename): - - filename2 = filename + '.tmp' - out = open(filename2, 'w') - f = open(filename, 'r') - for line in f.readlines(): - if line.find('mount -a /media/hdd; mount -a /media/usb') != -1: - line = '' - out.write(line) - - f.close() - out.close() - os.rename(filename2, filename) - - system('echo "" >> /etc/init.d/mdev; echo "mount -a /media/hdd; mount -a /media/usb" >> /etc/init.d/mdev; chmod 0755 /etc/init.d/mdev ') - - +#SetDiskLabel - dziekuje autorowi class SetDiskLabel(Screen): - skin = '\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t' + screenwidth = getDesktop(0).size().width() + if screenwidth and screenwidth == 1920: + skin =""" + + + + + + + + + + + + + + + + + + + + + + + + + """ % (_('!!!Do not set the label for /dev/mmcblk0p !!!')) + else: + skin = """ + + + + + + + + + + + + + + + + + + + """ def __init__(self, session): global liczymy Screen.__init__(self, session) - self.labList = ['hdd', 'usb'] + self.labList = ['hdd', 'usb','card', 'cf'] self.list = [] self.sprDev() self.devlist = [] @@ -653,6 +703,6 @@ class DeviceManagerSummary(Screen): def SkinPath(): myskinpath = resolveFilename(SCOPE_CURRENT_SKIN, '') - if myskinpath == '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/': - myskinpath = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/' + if myskinpath == '' + LinkNeoBoot + '/images/': + myskinpath = '' + LinkNeoBoot + '/images/' return myskinpath diff --git a/NeoBoot/files/neoconsole.py b/NeoBoot/files/neoconsole.py new file mode 100644 index 0000000..42007f1 --- /dev/null +++ b/NeoBoot/files/neoconsole.py @@ -0,0 +1,220 @@ +# -*- coding: utf-8 -*- + +from Plugins.Extensions.NeoBoot.__init__ import _ +from enigma import eConsoleAppContainer +from Screens.Screen import Screen +from Components.ActionMap import ActionMap +from Components.ScrollLabel import ScrollLabel +from Components.Sources.StaticText import StaticText +from Screens.MessageBox import MessageBox +from Components.Label import Label + + +class Console(Screen): + skin = """ + + """ + +# def __init__(self, session, title = 'Console', cmdlist = None, finishedCallback = None, closeOnSuccess = False): +# Screen.__init__(self, session) + + def __init__(self, session, title = _('Console'), cmdlist = None, finishedCallback = None, closeOnSuccess = False): + Screen.__init__(self, session) + self.finishedCallback = finishedCallback + self.closeOnSuccess = closeOnSuccess + self.errorOcurred = False + self['key_red'] = Label(_('Stop action')) + self['key_green'] = Label(_('Hide Console')) + self['text'] = ScrollLabel('') + self['summary_description'] = StaticText('') + self['actions'] = ActionMap(['WizardActions', 'DirectionActions', 'ColorActions'], {'ok': self.cancel, + 'back': self.cancel, + 'up': self.key_up, + 'down': self.key_down, + 'green': self.key_green, + 'red': self.key_red}, -1) + self.cmdlist = cmdlist + self.newtitle = title + self.screen_hide = False + self.cancel_msg = None + self.output_file = '' + self.onShown.append(self.updateTitle) + self.container = eConsoleAppContainer() + self.run = 0 + self.container.appClosed.append(self.runFinished) + self.container.dataAvail.append(self.dataAvail) + self.onLayoutFinish.append(self.startRun) + return + + def updateTitle(self): + self.setTitle(self.newtitle) + + def doExec(self, cmd): + if isinstance(cmd, (list, tuple)): + return self.container.execute(cmd[0], *cmd) + else: + return self.container.execute(cmd) + + def startRun(self): + self['text'].setText(_('Execution progress:') + '\n\n') + self['summary_description'].setText(_('Execution progress:')) + print '[Console] executing in run', self.run, ' the command:', self.cmdlist[self.run] + if self.doExec(self.cmdlist[self.run]): + self.runFinished(-1) + + def runFinished(self, retval): + if retval: + self.errorOcurred = True + self.toggleScreenHide(True) + self.run += 1 + if self.run != len(self.cmdlist): + if self.doExec(self.cmdlist[self.run]): + self.runFinished(-1) + else: +# self['key_red'].setText(_('Close')) +# self['key_green'].setText(_('Save')) + self.toggleScreenHide(True) + if self.cancel_msg: + self.cancel_msg.close() + from Tools.Directories import fileExists + if not fileExists('/etc/vtiversion.info'): + lastpage = self['text'].isAtLastPage() + self['text'].appendText('\n' + _('Execution finished!!')) + self['summary_description'].setText('\n' + _('Execution finished!!')) + if self.finishedCallback is not None: + self.finishedCallback() + if not self.errorOcurred and self.closeOnSuccess: + self.output_file = 'end' + self.cancel() + return + + def key_up(self): + if self.screen_hide: + self.toggleScreenHide() + return + self['text'].pageUp() + + def key_down(self): + if self.screen_hide: + self.toggleScreenHide() + return + self['text'].pageDown() + + def key_green(self): + if self.screen_hide: + self.toggleScreenHide() + return + if self.output_file == 'end': + pass + elif self.output_file.startswith('/tmp/'): + self['text'].setText(self.readFile(self.output_file)) + self['key_green'].setText(_(' ')) + self.output_file = 'end' + elif self.run == len(self.cmdlist): + self.saveOutputText() + #self.toggleScreenHide() + else: + self.toggleScreenHide() + + def key_red(self): + if self.screen_hide: + self.toggleScreenHide() + return + if self.run == len(self.cmdlist): + self.cancel() + else: + self.cancel_msg = self.session.openWithCallback(self.cancelCB, MessageBox, _('Cancel execution?'), type=MessageBox.TYPE_YESNO, default=False) + + def cancelCB(self, ret = None): + self.cancel_msg = None + if ret: + self.cancel(True) + return + + def saveOutputText(self): + from time import time, localtime + lt = localtime(time()) + self.output_file = '/tmp/%02d%02d%02d_console.txt' % (lt[3], lt[4], lt[5]) + self.session.openWithCallback(self.saveOutputTextCB, MessageBox, _("Save the commands and the output to a file?\n('%s')") % self.output_file, type=MessageBox.TYPE_YESNO, default=True) + + def formatCmdList(self, source): + if isinstance(source, (list, tuple)): + for x in source: + for y in self.formatCmdList(x): + yield y + + else: + yield source + + def saveOutputTextCB(self, ret = None): + if ret: + from os import path + failtext = _("Path to save not exist: '/tmp/'") + if path.exists('/tmp/'): + text = 'commands ...\n\n' + try: + cmdlist = list(self.formatCmdList(self.cmdlist)) + text += 'command line: %s\n\n' % cmdlist[0] + script = '' + for cmd in cmdlist[0].split(): + if '.' in cmd: + if cmd[-3:] in ('.py', '.sh'): + script = cmd + break + + if script and path.isfile(script): + text += 'script listing: %s\n\n%s\n\n' % (script, self.readFile(script)) + if len(cmdlist) > 1: + text += 'next commands:\n\n' + '\n'.join(cmdlist[1:]) + '\n\n' + except: + text += 'error read commands!!!\n\n' + + text += '-' * 50 + '\n\noutputs ...\n\n%s' % self['text'].getText() + try: + f = open(self.output_file, 'w') + f.write(text) + f.close() + self['key_green'].setText(_('Load')) + return + except: + failtext = _("File write error: '%s'") % self.output_file + + self.output_file = 'end' + self['key_green'].setText(_(' ')) + self.session.open(MessageBox, failtext, type=MessageBox.TYPE_ERROR) + else: + self.output_file = '' + + def toggleScreenHide(self, setshow = False): + if self.screen_hide or setshow: + self.show() + else: + self.hide() + self.screen_hide = not (self.screen_hide or setshow) + + def readFile(self, file): + try: + with open(file, 'r') as rdfile: + rd = rdfile.read() + rdfile.close() + except: + if file == self.output_file: + rd = self['text'].getText() + else: + rd = "File read error: '%s'\n" % file + + return rd + + def cancel(self, force = False): + if self.screen_hide: + self.toggleScreenHide() + return + if force or self.run == len(self.cmdlist): + self.close() + self.container.appClosed.remove(self.runFinished) + self.container.dataAvail.remove(self.dataAvail) + if self.run != len(self.cmdlist): + self.container.kill() + + def dataAvail(self, str): + self['text'].appendText(str) \ No newline at end of file diff --git a/NeoBoot/files/stbbranding.py b/NeoBoot/files/stbbranding.py index 7aa02b1..194bb12 100644 --- a/NeoBoot/files/stbbranding.py +++ b/NeoBoot/files/stbbranding.py @@ -332,7 +332,7 @@ def getVuModel(): f = open("/proc/stb/info/vumodel",'r') procmodel = f.readline().strip() f.close() - model = procmodel.title().replace("olose", "olo SE").replace("olo2se", "olo2 SE").replace("2", "²") + model = procmodel.title().replace("olose", "olo SE").replace("olo2se", "olo2 SE").replace("2", "²") return model #zwraca nazwe stb z pliku hostname @@ -694,5 +694,3 @@ def getMachineProcModel(): boxbrand = sys.modules[__name__] - -