You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3307 lines
136 KiB
3307 lines
136 KiB
#!/usr/bin/python
|
|
# -*- coding: UTF-8 -*-
|
|
###########################################################################
|
|
# mountconfig.py - description #
|
|
# ------------------------------ #
|
|
# begin : Fri Nov 30 2003 #
|
|
# copyright : (C) 2003 by Simon Edwards #
|
|
# email : simon@simonzone.com #
|
|
# #
|
|
###########################################################################
|
|
# #
|
|
# This program is free software; you can redistribute it and/or modify #
|
|
# it under the terms of the GNU General Public License as published by #
|
|
# the Free Software Foundation; either version 2 of the License, or #
|
|
# (at your option) any later version. #
|
|
# #
|
|
###########################################################################
|
|
|
|
import sys
|
|
import os
|
|
import os.path
|
|
from python_tqt.qt import *
|
|
from tdeui import *
|
|
from tdecore import *
|
|
from tdefile import *
|
|
from tdeio import *
|
|
from types import StringType,UnicodeType
|
|
import pwd
|
|
import grp
|
|
import math
|
|
import locale
|
|
import codecs
|
|
import subprocess
|
|
import MicroHAL
|
|
from SMBShareSelectDialog import *
|
|
from SimpleCommandRunner import *
|
|
from fuser import *
|
|
import sizeview
|
|
|
|
programname = "Disk & Filesystem Configuration"
|
|
version = "0.8.0"
|
|
|
|
# Are we running as a separate standalone application or in KControl?
|
|
standalone = __name__=='__main__'
|
|
|
|
# Running as the root user or not?
|
|
isroot = os.getuid()==0
|
|
allowuuid = True
|
|
allowlabel = True
|
|
|
|
|
|
"""
|
|
Universal Options
|
|
-----------------
|
|
|
|
async/sync
|
|
atime/noatime
|
|
auto/noauto
|
|
dev/nodev
|
|
exec/noexec
|
|
ro/rw
|
|
suid/nosuid
|
|
dirsync
|
|
nouser/user/users
|
|
|
|
defaults =>rw, suid, dev, exec, auto, nouser, and async.
|
|
|
|
Automatically set
|
|
=================
|
|
_netdev
|
|
The filesystem resides on a device that requires network access (used to
|
|
prevent the system from attempting to mount these filesystems until the
|
|
network has been enabled on the system).
|
|
|
|
remount
|
|
Attempt to remount an already-mounted file system. This is commonly used
|
|
to change the mount flags for a file system, especially to make a readonly
|
|
file system writeable. It does not change device or mount point.
|
|
|
|
Supported filesystems
|
|
---------------------
|
|
nfs
|
|
ext2
|
|
ext3
|
|
ext4
|
|
reiserfs
|
|
vfat
|
|
ntfs
|
|
udf
|
|
iso9660
|
|
supermount
|
|
reiser4
|
|
xfs
|
|
jfs
|
|
hfs
|
|
hfsplus
|
|
|
|
cifs (replacement for smbfs)
|
|
auto
|
|
|
|
swap
|
|
|
|
proc
|
|
sysfs
|
|
usbdevfs
|
|
procbususb
|
|
|
|
TODO
|
|
----
|
|
* SMB finished the connection username nad password fields.
|
|
* SMB entry: finished writing the config.
|
|
* SMBSelector: setting the username and password.
|
|
|
|
"""
|
|
|
|
############################################################################
|
|
class UserComboBox(KComboBox):
|
|
def __init__(self,parent,name=None):
|
|
KComboBox.__init__(self,parent,name)
|
|
tmplist = []
|
|
users = pwd.getpwall()
|
|
for user in users:
|
|
uid = int(user[2])
|
|
username = user[4]
|
|
tmplist.append( (int(uid),"%s (%s)" % (username,uid)) )
|
|
tmplist.sort(lambda a,b: cmp(a[1],b[1]))
|
|
self.userlist = []
|
|
for user in tmplist:
|
|
self.insertItem(user[1])
|
|
self.userlist.append(user[0])
|
|
|
|
########################################################################
|
|
def setUID(self,uid):
|
|
if uid in self.userlist:
|
|
self.setCurrentItem(self.userlist.index(int(uid)))
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
########################################################################
|
|
def UID(self):
|
|
return self.userlist[self.currentItem()]
|
|
|
|
############################################################################
|
|
class GroupComboBox(KComboBox):
|
|
def __init__(self,parent,name=None):
|
|
KComboBox.__init__(self,parent,name)
|
|
self.grouplist = []
|
|
groups = grp.getgrall()
|
|
tmplist = []
|
|
for group in groups:
|
|
gid = group[2]
|
|
groupname = group[0]
|
|
tmplist.append( (int(gid),"%s (%s)" % (groupname,gid)) )
|
|
tmplist.sort(lambda a,b: cmp(a[1],b[1]))
|
|
self.grouplist = []
|
|
for group in tmplist:
|
|
self.insertItem(group[1])
|
|
self.grouplist.append(group[0])
|
|
|
|
########################################################################
|
|
def setGID(self,gid):
|
|
if gid in self.grouplist:
|
|
self.setCurrentItem(self.grouplist.index(int(gid)))
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
########################################################################
|
|
def GID(self):
|
|
return self.grouplist[self.currentItem()]
|
|
|
|
|
|
############################################################################
|
|
class MountEntryExt(object):
|
|
use_as_device = "devicenode" # Can be one of "devicenode", "uuid" or "label"
|
|
showdevice = True
|
|
showlabel = False
|
|
showuuid = False
|
|
|
|
########################################################################
|
|
# Base can be either a fstab format line of text, of another MountEntry
|
|
# object.
|
|
def __init__(self,base=None):
|
|
if base==None:
|
|
self.device = unicode(i18n("<device>"))
|
|
self.mountpoint = unicode(i18n("<mount point>"))
|
|
self.mounttype = 'ext2'
|
|
self.uuid = ""
|
|
self.label = ""
|
|
self.extraoptions = "noauto"
|
|
self.fs_freq = 0
|
|
self.fs_passno = 0
|
|
self.enabled = False
|
|
self.managed = False
|
|
self.device_string = ""
|
|
|
|
elif isinstance(base,StringType) or isinstance(base,UnicodeType):
|
|
parts = base.split()
|
|
|
|
device_ref = MountEntry.decodeMountEntryString(parts[0])
|
|
self.uuid = ""
|
|
self.label = ""
|
|
if device_ref.startswith("UUID="):
|
|
self.uuid = device_ref[5:]
|
|
self.setUseAsDevice("uuid")
|
|
mapped_device = microhal.getDeviceByUUID(self.uuid)
|
|
if mapped_device is not None:
|
|
self.device = mapped_device.getDev()
|
|
else:
|
|
self.device = ""
|
|
try:
|
|
self.label = mapped_device.getLabel()
|
|
except AttributeError:
|
|
pass
|
|
elif device_ref.startswith("LABEL="):
|
|
self.label = device_ref[6:]
|
|
self.setUseAsDevice("label")
|
|
mapped_device = microhal.getDeviceByLabel(self.label)
|
|
if mapped_device is not None:
|
|
self.device = mapped_device.getDev()
|
|
else:
|
|
self.device = ""
|
|
else:
|
|
self.device = device_ref
|
|
|
|
self.mountpoint = MountEntry.decodeMountEntryString(parts[1])
|
|
self.mounttype = MountEntry.decodeMountEntryString(parts[2])
|
|
self.extraoptions = MountEntry.decodeMountEntryString(parts[3])
|
|
self.fs_freq = int(parts[4])
|
|
self.fs_passno = int(parts[5])
|
|
self.enabled = False
|
|
|
|
options = self.extraoptions.split(",")
|
|
self.managed = "managed" in options
|
|
try:
|
|
options.remove("managed")
|
|
except ValueError:
|
|
pass
|
|
self.extraoptions = ",".join(options)
|
|
|
|
else:
|
|
# This is a new entry, but it's based on another one.
|
|
self.device = base.device
|
|
self.mountpoint = base.mountpoint
|
|
self.mounttype = base.mounttype
|
|
self.extraoptions = base.extraoptions
|
|
self.fs_freq = base.fs_freq
|
|
self.fs_passno = base.fs_passno
|
|
self.uuid = base.uuid
|
|
self.enabled = base.enabled
|
|
self.managed = False
|
|
self.iconname = self.getIconName()
|
|
|
|
########################################################################
|
|
def copy(self,newobject=None):
|
|
if newobject is None:
|
|
newobject = MountEntryExt()
|
|
# FIXME: use "newobject = self.__class__()" and get rid of the newobject parameter.
|
|
newobject.device = self.device
|
|
newobject.mountpoint = self.mountpoint
|
|
newobject.mounttype = self.mounttype
|
|
newobject.use_as_device = self.use_as_device
|
|
newobject.showlabel = self.showlabel
|
|
newobject.showdevice = self.showdevice
|
|
newobject.showuuid = self.showuuid
|
|
newobject.extraoptions = self.extraoptions
|
|
newobject.fs_freq = self.fs_freq
|
|
newobject.fs_passno = self.fs_passno
|
|
newobject.enabled = self.enabled
|
|
newobject.uuid = self.uuid
|
|
newobject.label = self.label
|
|
return newobject
|
|
|
|
########################################################################
|
|
def cleanup(self):
|
|
# This method is called after the entry has been removed from the
|
|
# mounttable.
|
|
pass
|
|
|
|
########################################################################
|
|
def setMountType(self,mounttypename): self.mounttype = mounttypename
|
|
|
|
########################################################################
|
|
def isFileSystemAvailable(self):
|
|
return microhal.isSupportedFileSystem(self.mounttype)
|
|
|
|
def getDevice(self): return self.device
|
|
def setDevice(self,device): self.device = device
|
|
def setUseAsDevice(self,use_as): self.use_as_device = use_as
|
|
def getUseAsDevice(self): return self.use_as_device
|
|
def setUUID(self,uuid): self.uuid = uuid
|
|
def setLabel(self,label): self.label = label
|
|
def getMountPoint(self): return self.mountpoint
|
|
def setMountPoint(self,mountpoint): self.mountpoint = mountpoint
|
|
def getExtraOptions(self): return self.extraoptions
|
|
def setExtraOptions(self,extraoptions): self.extraoptions = extraoptions
|
|
def getFSFreq(self): return self.fs_freq
|
|
def setFSFreq(self,fs_freq): self.fs_freq = fs_freq
|
|
def getFSPassno(self): return self.fs_passno
|
|
def setFSPassno(self,fs_passno): self.fs_passno = fs_passno
|
|
def isManaged(self): return self.managed
|
|
|
|
def getUUID(self):
|
|
if not self.uuid:
|
|
return ""
|
|
return self.uuid
|
|
|
|
def getLabel(self):
|
|
try:
|
|
if not self.label:
|
|
return ""
|
|
return self.label
|
|
except AttributeError:
|
|
return ""
|
|
|
|
def getDeviceString(self):
|
|
if self.getUseAsDevice() == "label":
|
|
if self.label != "":
|
|
return MountEntry.encodeMountEntryString("LABEL="+self.label)
|
|
else:
|
|
print "No Label set, preventing you from shooting yourself in the foot"
|
|
elif self.getUseAsDevice() == "uuid":
|
|
if self.uuid != "":
|
|
return "UUID="+self.uuid
|
|
return MountEntry.encodeMountEntryString("UUID="+self.uuid)
|
|
else:
|
|
print "No UUID set, preventing you from shooting yourself in the foot"
|
|
return MountEntry.encodeMountEntryString(self.device)
|
|
|
|
########################################################################
|
|
def getName(self):
|
|
if os.path.basename(self.device).startswith("fd"):
|
|
return "Floppy"
|
|
else:
|
|
return self.mountpoint
|
|
|
|
########################################################################
|
|
def getIconName(self):
|
|
if self.device is not None and os.path.basename(self.device).startswith("fd"):
|
|
return "hi16-floppy"
|
|
else:
|
|
return "hi16-blockdevice"
|
|
|
|
########################################################################
|
|
def updateStatus(self,mtablist):
|
|
self.enabled = self.mountpoint in mtablist
|
|
|
|
########################################################################
|
|
def getFstabOptions(self):
|
|
if self.extraoptions!="":
|
|
return self.extraoptions.split(",")
|
|
else:
|
|
return []
|
|
|
|
########################################################################
|
|
def getFstabLine(self):
|
|
# Construct the options field.
|
|
_options = self.getFstabOptions()
|
|
options = []
|
|
# Remove whitespace and dupes
|
|
for o in _options:
|
|
if o.strip() not in options:
|
|
options.append(o.strip())
|
|
|
|
return self.getDeviceString() + \
|
|
u" " + MountEntry.encodeMountEntryString(self.mountpoint.replace("%20","\040")) + \
|
|
u" " + MountEntry.encodeMountEntryString(self.mounttype) + \
|
|
u" " + MountEntry.encodeMountEntryString(u",".join(options)) + \
|
|
u" " + unicode(self.fs_freq) + u" " + unicode(self.fs_passno)
|
|
|
|
########################################################################
|
|
def getCategory(self):
|
|
return self.device
|
|
|
|
########################################################################
|
|
def isEnabled(self): return self.enabled
|
|
|
|
########################################################################
|
|
def enable(self,parentdialog):
|
|
self._setBusy(parentdialog,True)
|
|
try:
|
|
(rc,output) = SimpleCommandRunner().run(["/bin/mount",self.mountpoint])
|
|
finally:
|
|
self._setBusy(parentdialog,False)
|
|
if rc!=0:
|
|
self.handleMountFailure(parentdialog,rc,output,True)
|
|
|
|
########################################################################
|
|
def disable(self,parentdialog):
|
|
self._setBusy(parentdialog,True)
|
|
try:
|
|
(rc,output) = SimpleCommandRunner().run(["/bin/umount",self.mountpoint])
|
|
finally:
|
|
self._setBusy(parentdialog,False)
|
|
if rc!=0:
|
|
self.handleMountFailure(parentdialog,rc,output,False)
|
|
|
|
########################################################################
|
|
def handleMountFailure(self,parentdialog,rc,output,mount_action=True):
|
|
"""
|
|
Keyword arguments:
|
|
mount_action - True=enable, False=disable
|
|
"""
|
|
global kapp
|
|
if mount_action:
|
|
msg = i18n("An error occurred while enabling %1.\n\nThe system reported: %2").arg( \
|
|
self.mountpoint).arg(output)
|
|
captionmsg = i18n("Unable to enable %1").arg(self.mountpoint)
|
|
else:
|
|
msg = i18n("An error occurred while disabling %1.\n\nThe system reported: %2").arg(
|
|
self.mountpoint).arg(output)
|
|
captionmsg = i18n("Unable to disable %1").arg(self.mountpoint)
|
|
|
|
extramsg = unicode(i18n("Return code from mount was %1.\n").arg(rc))
|
|
|
|
if (rc & 1)!=0:
|
|
extramsg += unicode(i18n("\"incorrect invocation or permissions\"\n"))
|
|
if (rc & 2)!=0:
|
|
extramsg += unicode(i18n("\"system error (out of memory, cannot fork, no more loop devices)\"\n"))
|
|
if (rc & 4)!=0:
|
|
extramsg += unicode(i18n("\"internal mount bug or missing nfs support in mount\"\n"))
|
|
if (rc & 8)!=0:
|
|
extramsg += unicode(i18n("\"user interrupt\"\n"))
|
|
if (rc & 16)!=0:
|
|
extramsg += unicode(i18n("\"problems writing or locking /etc/mtab\"\n"))
|
|
if (rc & 32)!=0:
|
|
extramsg += unicode(i18n("\"mount failure\"\n"))
|
|
if (rc & 64)!=0:
|
|
extramsg += unicode(i18n("\"some mount succeeded\"\n"))
|
|
|
|
in_use = False
|
|
if not mount_action:
|
|
# Use lsof to find out what is blocking the device.
|
|
lsof_bin = '/usr/bin/lsof'
|
|
rc, output = SimpleCommandRunner().run([lsof_bin,'-FncL',str(self.mountpoint)])
|
|
if rc==0:
|
|
# Check if there is one or more processes using the device.
|
|
in_use = len(output.split())>3
|
|
if in_use:
|
|
# Start fuser.py which lists open filedescriptors on device and offers to get
|
|
# rid of them.
|
|
fuser = FUser(str(self.mountpoint),None,lsof_bin,kapp)
|
|
fuser.exec_loop()
|
|
in_use_message = ""
|
|
if fuser.result() != 0:
|
|
in_use_message = unicode(i18n("Unmounting %1 failed or was cancelled.").arg(self.device))
|
|
extramsg += in_use_message
|
|
else:
|
|
extramsg += unicode(i18n("(none)"))
|
|
|
|
if not in_use:
|
|
KMessageBox.detailedSorry(parentdialog, msg, extramsg, captionmsg)
|
|
|
|
########################################################################
|
|
def _setBusy(self,parentdialog,flag):
|
|
global kapp
|
|
if flag:
|
|
kapp.setOverrideCursor( TQCursor(TQt.WaitCursor) )
|
|
parentdialog.setEnabled(False)
|
|
|
|
# It is necessary to process some of the events in the event queue.
|
|
# Otherwise the user won't see that the window is disabled.
|
|
# ( setEnabled() here above doesn't redraw the window immediately.
|
|
# Redrawing is done via the event queue.)
|
|
kapp.processEvents()
|
|
else:
|
|
parentdialog.setEnabled(True)
|
|
kapp.restoreOverrideCursor()
|
|
|
|
############################################################################
|
|
class MountEntryExtCommonUnix(MountEntryExt):
|
|
|
|
USERMOUNT_NO = 0
|
|
USERMOUNT_ONE = 1
|
|
USERMOUNT_ANY = 2
|
|
USERMOUNT_OWNER = 3
|
|
|
|
########################################################################
|
|
# Base can be either a fstab format line of text, or another MountEntry
|
|
# object.
|
|
def __init__(self,base=None):
|
|
super(MountEntryExtCommonUnix,self).__init__(base)
|
|
|
|
if isinstance(base,MountEntryExtCommonUnix):
|
|
# Being initalised from an existing object.
|
|
# Only mess with objects
|
|
self.atime = base.atime
|
|
self.auto = base.auto
|
|
self.writeable = base.writeable
|
|
self.usedevpoints = base.usedevpoints
|
|
self.showlabel = True
|
|
self.showuuid = True
|
|
self.allowexecutables = base.allowexecutables
|
|
self.allowsuid = base.allowsuid
|
|
self.allowusermount = base.allowusermount
|
|
|
|
elif isinstance(base,StringType) or isinstance(base,UnicodeType):
|
|
options = self.extraoptions.split(",")
|
|
|
|
self.atime = True
|
|
if "noatime" in options:
|
|
self.atime = False
|
|
self.auto = True
|
|
if "noauto" in options:
|
|
self.auto = False
|
|
self.writeable = True
|
|
if "ro" in options:
|
|
self.writeable = False
|
|
self.usedevpoints = True
|
|
if "nodev" in options:
|
|
self.usedevpoints = False
|
|
self.allowexecutables = True
|
|
if "noexec" in options:
|
|
self.allowexecutables = False
|
|
self.allowsuid = True
|
|
if "nosuid" in options:
|
|
self.allowsuid = False
|
|
self.allowusermount = self.USERMOUNT_NO
|
|
if "user" in options:
|
|
self.allowusermount = self.USERMOUNT_ONE
|
|
if "users" in options:
|
|
self.allowusermount = self.USERMOUNT_ANY
|
|
if "owner" in options:
|
|
self.allowusermount = self.USERMOUNT_OWNER
|
|
|
|
self.showlabel = True
|
|
self.showuuid = True
|
|
|
|
for x in ["noatime","atime","auto","noauto","dev","nodev","nouser", \
|
|
"owner","users","user","suid","nosuid","exec","noexec","rw","ro"]:
|
|
try:
|
|
options.remove(x)
|
|
except ValueError:
|
|
pass
|
|
|
|
self.extraoptions = ",".join(options)
|
|
|
|
else:
|
|
# Set some sane defaults.
|
|
self.showlabel = True
|
|
self.showuuid = True
|
|
self.atime = True
|
|
self.auto = False
|
|
self.writeable = True
|
|
self.usedevpoints = False
|
|
self.allowexecutables = False
|
|
self.allowsuid = False
|
|
self.allowusermount = self.USERMOUNT_NO
|
|
|
|
########################################################################
|
|
def copy(self,newobject=None):
|
|
if newobject is None:
|
|
newobject = MountEntryExtCommonUnix()
|
|
super(MountEntryExtCommonUnix,self).copy(newobject)
|
|
newobject.atime = self.atime
|
|
newobject.auto = self.auto
|
|
newobject.use_as_device = self.use_as_device
|
|
newobject.showlabel = self.showlabel
|
|
newobject.showdevice = self.showdevice
|
|
newobject.showuuid = self.showuuid
|
|
newobject.uuid = self.uuid
|
|
newobject.label = self.label
|
|
newobject.writeable = self.writeable
|
|
newobject.usedevpoints = self.usedevpoints
|
|
newobject.allowexecutables = self.allowexecutables
|
|
newobject.allowsuid = self.allowsuid
|
|
newobject.allowusermount = self.allowusermount
|
|
return newobject
|
|
|
|
########################################################################
|
|
def getFstabOptions(self):
|
|
options = []
|
|
|
|
# These options must appear before the others. 'user', according to the
|
|
# mount man page implies 'noexec' too, BUT the noexec can be overridden
|
|
# by specifying 'exec' after the 'user' keyword. Therefore 'exec' etc
|
|
# must come after 'user', 'users' and friends.
|
|
options.append(['nouser','user','users','owner'][self.allowusermount])
|
|
|
|
super_options = super(MountEntryExtCommonUnix,self).getFstabOptions()
|
|
options.extend(super_options)
|
|
|
|
options.append(['noatime','atime'][self.atime])
|
|
options.append(['noauto','auto'][self.auto])
|
|
options.append(['ro','rw'][self.writeable])
|
|
options.append(['nodev','dev'][self.usedevpoints])
|
|
options.append(['noexec','exec'][self.allowexecutables])
|
|
options.append(['nosuid','suid'][self.allowsuid])
|
|
return options
|
|
|
|
########################################################################
|
|
# atime/noatime
|
|
def getAtime(self): return self.atime
|
|
def setAtime(self,val): self.atime = val
|
|
# auto/noauto
|
|
def getMountAtBoot(self): return self.auto
|
|
def setMountAtBoot(self,val): self.auto = val
|
|
# ro/rw
|
|
def getWritable(self): return self.writeable
|
|
def setWritable(self,val): self.writeable = val
|
|
# dev, nodev
|
|
def getUseDevPoints(self): return self.usedevpoints
|
|
def setUseDevPoints(self,val): self.usedevpoints = val
|
|
# exec/noexec
|
|
def getAllowExecutables(self): return self.allowexecutables
|
|
def setAllowExecutable(self,val): self.allowexecutables = val
|
|
# suid/nosuid
|
|
def getSUID(self): return self.allowsuid
|
|
def setSUID(self,val): self.allowsuid = val
|
|
# nouser/user/users/owner
|
|
def setAllowUserMount(self,val): self.allowusermount = val
|
|
def getAllowUserMount(self): return self.allowusermount
|
|
|
|
|
|
############################################################################
|
|
# Common unix filesystems, but for local hard disks. i.e. partitions.
|
|
class MountEntryExtCommonUnixLocal(MountEntryExtCommonUnix):
|
|
########################################################################
|
|
def __init__(self,base=None):
|
|
super(MountEntryExtCommonUnixLocal,self).__init__(base)
|
|
########################################################################
|
|
def copy(self,newobject=None):
|
|
if newobject is None:
|
|
newobject = MountEntryExtCommonUnixLocal()
|
|
super(MountEntryExtCommonUnixLocal,self).copy(newobject)
|
|
newobject.showlabel = self.showlabel
|
|
newobject.showdevice = self.showdevice
|
|
newobject.showuuid = self.showuuid
|
|
return newobject
|
|
|
|
|
|
############################################################################
|
|
class MountEntryExtAlien(MountEntryExt):
|
|
|
|
USERMOUNT_NO = 0
|
|
USERMOUNT_ONE = 1
|
|
USERMOUNT_ANY = 2
|
|
USERMOUNT_OWNER = 3
|
|
|
|
########################################################################
|
|
# Base can be either a fstab format line of text, of another MountEntry
|
|
# object.
|
|
def __init__(self,base=None):
|
|
super(MountEntryExtAlien,self).__init__(base)
|
|
|
|
if isinstance(base,MountEntryExtAlien):
|
|
self.uid = base.uid
|
|
self.gid = base.gid
|
|
self.label = base.label
|
|
self.writeable = base.writeable
|
|
self.auto = base.auto
|
|
self.allowusermount = base.allowusermount
|
|
|
|
elif isinstance(base,StringType) or isinstance(base,UnicodeType):
|
|
self.uid = 0
|
|
self.gid = 0
|
|
options = self.extraoptions.split(",")
|
|
newoptions = []
|
|
for line in options:
|
|
if line.startswith("uid="):
|
|
try:
|
|
self.uid = int(line[4:])
|
|
except ValueError:
|
|
self.uid = 0
|
|
elif line.startswith("gid="):
|
|
try:
|
|
self.gid = int(line[4:])
|
|
except ValueError:
|
|
self.gid = 0
|
|
else:
|
|
# We hang on to unknown options for later.
|
|
newoptions.append(line)
|
|
options = newoptions
|
|
|
|
self.writeable = True
|
|
if "ro" in options:
|
|
self.writeable = False
|
|
self.auto = True
|
|
if "noauto" in options:
|
|
self.auto = False
|
|
self.allowusermount = self.USERMOUNT_NO
|
|
if "user" in options:
|
|
self.allowusermount = self.USERMOUNT_ONE
|
|
if "users" in options:
|
|
self.allowusermount = self.USERMOUNT_ANY
|
|
if "owner" in options:
|
|
self.allowusermount = self.USERMOUNT_OWNER
|
|
|
|
for x in ["noatime","atime","auto","noauto","dev","nodev","nouser", \
|
|
"owner","users","user","suid","nosuid","exec","noexec","rw", \
|
|
"ro"]:
|
|
try:
|
|
options.remove(x)
|
|
except ValueError:
|
|
pass
|
|
self.extraoptions = ",".join(options)
|
|
|
|
else:
|
|
self.uid = 0
|
|
self.gid = 0
|
|
self.writeable = False
|
|
self.auto = False
|
|
self.allowusermount = self.USERMOUNT_NO
|
|
|
|
########################################################################
|
|
def copy(self,newobject=None):
|
|
if newobject is None:
|
|
newobject = MountEntryExtAlien()
|
|
super(MountEntryExtAlien,self).copy(newobject)
|
|
newobject.uid = self.uid
|
|
newobject.gid = self.gid
|
|
newobject.use_as_device = self.use_as_device
|
|
newobject.showlabel = self.showlabel
|
|
newobject.showdevice = self.showdevice
|
|
newobject.showuuid = self.showuuid
|
|
newobject.writeable = self.writeable
|
|
newobject.auto = self.auto
|
|
newobject.allowusermount = self.allowusermount
|
|
return newobject
|
|
|
|
########################################################################
|
|
def getFstabOptions(self):
|
|
# Construct the options field.
|
|
options = super(MountEntryExtAlien,self).getFstabOptions()
|
|
options.append('uid='+unicode(self.uid))
|
|
options.append('gid='+unicode(self.gid))
|
|
options.append(['noauto','auto'][self.auto])
|
|
options.append(['ro','rw'][self.writeable])
|
|
options.append(['nouser','user','users','owner'][self.allowusermount])
|
|
return options
|
|
|
|
########################################################################
|
|
def getUID(self): return self.uid
|
|
def setUID(self,val): self.uid = val
|
|
def getGID(self): return self.gid
|
|
def setGID(self,val): self.gid = val
|
|
|
|
# ro/rw
|
|
def getWritable(self): return self.writeable
|
|
def setWritable(self,val): self.writeable = val
|
|
# auto/noauto
|
|
def getMountAtBoot(self): return self.auto
|
|
def setMountAtBoot(self,val): self.auto = val
|
|
# nouser/user/users/owner
|
|
def setAllowUserMount(self,val): self.allowusermount = val
|
|
def getAllowUserMount(self): return self.allowusermount
|
|
|
|
############################################################################
|
|
class MountEntryExtVFAT(MountEntryExtAlien):
|
|
def __init__(self,base=None):
|
|
super(MountEntryExtVFAT,self).__init__(base)
|
|
|
|
if isinstance(base,MountEntryExtVFAT):
|
|
self.suppresspermissionerrors = base.suppresspermissionerrors
|
|
elif isinstance(base,StringType) or isinstance(base,UnicodeType):
|
|
options = self.extraoptions.split(",")
|
|
self.suppresspermissionerrors = "quiet" in options
|
|
try:
|
|
options.remove("quiet")
|
|
except ValueError:
|
|
pass
|
|
self.extraoptions = ",".join(options)
|
|
|
|
else:
|
|
self.suppresspermissionerrors = False
|
|
|
|
########################################################################
|
|
def copy(self,newobject=None):
|
|
if newobject is None:
|
|
newobject = MountEntryExtVFAT()
|
|
super(MountEntryExtVFAT,self).copy(newobject)
|
|
newobject.suppresspermissionerrors = self.suppresspermissionerrors
|
|
newobject.showlabel = self.showlabel
|
|
newobject.showdevice = self.showdevice
|
|
newobject.showuuid = self.showuuid
|
|
return newobject
|
|
|
|
########################################################################
|
|
def getFstabOptions(self):
|
|
options = super(MountEntryExtVFAT,self).getFstabOptions()
|
|
if self.suppresspermissionerrors:
|
|
options.append('quiet')
|
|
return options
|
|
|
|
def getSuppressPermissionErrors(self): return self.suppresspermissionerrors
|
|
def setSuppressPermissionErrors(self,val): self.suppresspermissionerrors = val
|
|
|
|
############################################################################
|
|
class MountEntryExtSMB(MountEntryExtAlien):
|
|
CREDENTIALSBASENAME = "/etc/fstab_smb_credentials_"
|
|
########################################################################
|
|
def __init__(self,base=None):
|
|
super(MountEntryExtSMB,self).__init__(base)
|
|
|
|
if isinstance(base,MountEntryExtSMB):
|
|
self.username = base.username
|
|
self.password = base.password
|
|
self.credentialsfile = base.credentialsfile
|
|
|
|
elif isinstance(base,StringType) or isinstance(base,UnicodeType):
|
|
self.username = None
|
|
self.password = ""
|
|
self.credentialsfile = None
|
|
|
|
newoptions = []
|
|
options = self.extraoptions.split(",")
|
|
for line in options:
|
|
if line.startswith("username="):
|
|
self.username = line[9:]
|
|
elif line.startswith("password="):
|
|
self.password = line[9:]
|
|
elif line.startswith("credentials="):
|
|
self.credentialsfile = line[12:]
|
|
try:
|
|
fhandle = codecs.open(self.credentialsfile,'r',locale.getpreferredencoding())
|
|
for line in fhandle.readlines():
|
|
if line.startswith("username"):
|
|
self.username = line[8:].strip()[1:].strip()
|
|
elif line.startswith("password"):
|
|
self.password = line[8:].strip()[1:].strip()
|
|
fhandle.close()
|
|
|
|
if not self.credentialsfile.startswith(self.CREDENTIALSBASENAME):
|
|
self.credentialsfile = None
|
|
|
|
except IOError:
|
|
self.credentialsfile = None
|
|
|
|
elif line=="guest":
|
|
pass
|
|
else:
|
|
# We hang on to unknown options for later.
|
|
newoptions.append(line)
|
|
options = newoptions
|
|
|
|
if self.username == "":
|
|
self.username = None
|
|
|
|
self.extraoptions = ",".join(options)
|
|
|
|
else:
|
|
self.username = None
|
|
self.password = ""
|
|
self.credentialsfile = None
|
|
|
|
########################################################################
|
|
def copy(self,newobject=None):
|
|
if newobject is None:
|
|
newobject = MountEntryExtSMB()
|
|
super(MountEntryExtSMB,self).copy(newobject)
|
|
newobject.username = self.username
|
|
newobject.password = self.password
|
|
newobject.credentialsfile = self.credentialsfile
|
|
newobject.showlabel = self.showlabel
|
|
newobject.showdevice = self.showdevice
|
|
newobject.showuuid = self.showuuid
|
|
return newobject
|
|
|
|
########################################################################
|
|
def cleanup(self):
|
|
if (self.credentialsfile is not None) and os.path.exists(self.credentialsfile) and os.path.isfile(self.credentialsfile):
|
|
os.remove(self.credentialsfile)
|
|
|
|
########################################################################
|
|
def getIconName(self):
|
|
return "hi16-network"
|
|
|
|
########################################################################
|
|
def getFstabOptions(self):
|
|
options = super(MountEntryExtSMB,self).getFstabOptions()
|
|
if self.username is None:
|
|
if (self.credentialsfile is not None) and os.path.exists(self.credentialsfile) and os.path.isfile(self.credentialsfile):
|
|
os.remove(self.credentialsfile)
|
|
options.append("guest") # This option should stop mount(8) from asking for a password.
|
|
else:
|
|
# Write out the credentials file
|
|
if self.credentialsfile is None:
|
|
i = 1
|
|
while os.path.exists(self.CREDENTIALSBASENAME+unicode(i)):
|
|
i += 1
|
|
self.credentialsfile = self.CREDENTIALSBASENAME+unicode(i)
|
|
fd = os.open(self.credentialsfile,os.O_WRONLY|os.O_CREAT,0600)
|
|
fhandle = os.fdopen(fd,'w')
|
|
fhandle.write((u"username = %s\npassword = %s\n" % (self.username,self.password))
|
|
.encode(locale.getpreferredencoding(),'replace') )
|
|
fhandle.close()
|
|
options.append(u"credentials="+self.credentialsfile)
|
|
return options
|
|
|
|
########################################################################
|
|
def getUsername(self): return self.username
|
|
def setUsername(self,username): self.username = username
|
|
def getPassword(self): return self.password
|
|
def setPassword(self,password): self.password = password
|
|
|
|
############################################################################
|
|
class MountEntryExtSystem(MountEntryExt):
|
|
########################################################################
|
|
def __init__(self,base=None):
|
|
super(MountEntryExtSystem,self).__init__(base)
|
|
self.use_as_device = "devicenode"
|
|
self.label = ""
|
|
self.showuuid = False
|
|
self.showlabel = False
|
|
|
|
########################################################################
|
|
def copy(self,newobject=None):
|
|
if newobject is None:
|
|
newobject = MountEntryExtSystem()
|
|
super(MountEntryExtSystem,self).copy(newobject)
|
|
return newobject
|
|
|
|
########################################################################
|
|
def getCategory(self):
|
|
return "system"
|
|
|
|
def disable(self,parentdialog):
|
|
""" This shouldn't happen since system entries have the disable button disabled """
|
|
msg = i18n("Disabling %1 is not supported.").arg(self.mountpoint)
|
|
extramsg = i18n("""Some system devices cannot be disabled because they are needed for \
|
|
basic functionality of the operating system.""")
|
|
KMessageBox.detailedSorry(parentdialog,msg,extramsg,\
|
|
i18n("Error occurred while disabling %1").arg(self.mountpoint))
|
|
|
|
############################################################################
|
|
class MountEntryExtSwap(MountEntryExt):
|
|
|
|
########################################################################
|
|
# Base can be either a fstab format line of text, of another MountEntry
|
|
# object.
|
|
def __init__(self,base=None):
|
|
super(MountEntryExtSwap,self).__init__(base)
|
|
|
|
if isinstance(base,StringType) or isinstance(base,UnicodeType):
|
|
options = self.extraoptions.split(",")
|
|
try:
|
|
options.remove('defaults')
|
|
except ValueError:
|
|
pass
|
|
self.extraoptions = u",".join(options)
|
|
|
|
########################################################################
|
|
def copy(self,newobject=None):
|
|
if newobject is None:
|
|
newobject = MountEntryExtSwap()
|
|
super(MountEntryExtSwap,self).copy(newobject)
|
|
return newobject
|
|
|
|
########################################################################
|
|
def getFstabOptions(self):
|
|
options = super(MountEntryExtSwap,self).getFstabOptions()
|
|
if len(options)==0:
|
|
# Make sure there is at least one option in the list.
|
|
options.append('defaults')
|
|
return options
|
|
|
|
########################################################################
|
|
def updateStatus(self,mtablist):
|
|
|
|
this_device = self.device
|
|
if this_device is None:
|
|
# Find the device name by its UUID.
|
|
if self.uuid:
|
|
hal_device = microhal.getDeviceByUUID(self.uuid)
|
|
if self.label:
|
|
hal_device = microhal.getDeviceByLabel(self.label)
|
|
if hal_device is None:
|
|
self.enabled = False
|
|
return
|
|
this_device = hal_device.getDev()
|
|
|
|
# If the device is a symlink, then grab the complete target.
|
|
if os.path.islink(this_device):
|
|
this_device = os.path.join(os.path.dirname(this_device),os.readlink(this_device))
|
|
|
|
fhandle = open("/proc/swaps")
|
|
lines = fhandle.readlines()
|
|
fhandle.close()
|
|
|
|
try: del lines[0]
|
|
except IndexError: pass
|
|
|
|
self.enabled = False
|
|
for line in lines:
|
|
parts = line.split()
|
|
if parts[0]==this_device:
|
|
self.enabled = True
|
|
return
|
|
|
|
########################################################################
|
|
# Returns a list of command+arguments
|
|
def enable(self,parentdialog):
|
|
self._setBusy(parentdialog,True)
|
|
try:
|
|
(rc,output) = SimpleCommandRunner().run(['/sbin/swapon',self.device])
|
|
if rc!=0:
|
|
msg = i18n("An error occurred while enabling swap partition %1.\n\nThe system reported: %2").arg(self.device).arg(output)
|
|
KMessageBox.sorry(parentdialog,msg,\
|
|
i18n("Error occurred while enabling swap partition %1").arg(self.device))
|
|
finally:
|
|
self._setBusy(parentdialog,False)
|
|
|
|
########################################################################
|
|
# Returns a list of command+arguments or None.
|
|
def disable(self,parentdialog):
|
|
self._setBusy(parentdialog,True)
|
|
try:
|
|
(rc,output) = SimpleCommandRunner().run(['/sbin/swapoff',self.device])
|
|
if rc!=0:
|
|
msg = i18n("An error occurred while disabling swap partition %1.\n\nThe system reported: %2").arg(self.device).arg(output)
|
|
KMessageBox.sorry(parentdialog,msg,\
|
|
i18n("Error occurred while disabling swap partition %1").arg(self.device))
|
|
finally:
|
|
self._setBusy(parentdialog,False)
|
|
|
|
############################################################################
|
|
# This represents a mount entry.
|
|
#
|
|
# It also does a little trick with the MountEntryExt classes. MountEntry
|
|
# objects kind of 'change' class under your nose when they are set to
|
|
# different mount types. The handling of the different kinds of mount types
|
|
# is handled by MountEntryExt objects and subclasses.
|
|
|
|
class MountEntry(object):
|
|
|
|
MountTypes = {
|
|
'proc' : (MountEntryExtSystem,i18n("proc")),
|
|
'sysfs' : (MountEntryExtSystem,i18n("sysfs")),
|
|
'rootfs' : (MountEntryExtSystem,i18n("rootfs")),
|
|
'bdev' : (MountEntryExtSystem,i18n("bdev")),
|
|
'sockfs' : (MountEntryExtSystem,i18n("sockfs")),
|
|
'tmpfs' : (MountEntryExtSystem,i18n("tmpfs")),
|
|
'shm' : (MountEntryExtSystem,i18n("shm")),
|
|
'pipefs' : (MountEntryExtSystem,i18n("pipefs")),
|
|
'devfs' : (MountEntryExtSystem,i18n("devfs - Device File System")),
|
|
'devpts' : (MountEntryExtSystem,i18n("devpts")),
|
|
'ramfs' : (MountEntryExtSystem,i18n("ramfs")),
|
|
'auto' : (MountEntryExtCommonUnix,i18n("Automatic")),
|
|
'usbdevfs' : (MountEntryExtSystem,i18n("usbdevfs")),
|
|
'procbususb' : (MountEntryExtSystem,i18n("procbususb")),
|
|
'usbfs' : (MountEntryExtSystem,i18n("usbfs")),
|
|
'supermount' : (MountEntryExt,i18n("supermount")),
|
|
'swap' : (MountEntryExtSwap,i18n("Swap - Linux Swap Space")),
|
|
|
|
'nfs' : (MountEntryExtCommonUnix,i18n("NFS - Network File System")),
|
|
'cifs' : (MountEntryExtSMB,i18n("Windows File Sharing")),
|
|
|
|
'ext2' : (MountEntryExtCommonUnixLocal,i18n("Ext2 - Second Extended FS")),
|
|
'ext3' : (MountEntryExtCommonUnixLocal,i18n("Ext3 - Third Extended FS")),
|
|
'ext4' : (MountEntryExtCommonUnixLocal,i18n("Ext4 - Fourth Extended FS")),
|
|
'reiserfs' : (MountEntryExtCommonUnixLocal,i18n("ReiserFS")),
|
|
'reiser4' : (MountEntryExtCommonUnixLocal,i18n("Reiser4")),
|
|
'xfs' : (MountEntryExtCommonUnixLocal,i18n("XFS - SGI's journaling filesystem")),
|
|
'hfs' : (MountEntryExtCommonUnixLocal,i18n("HFS - Apple's Hierarchical File System")),
|
|
'hfsplus' : (MountEntryExtVFAT,i18n("HFS+ - Apple's modernized Hierarchical File System")),
|
|
'jfs' : (MountEntryExtCommonUnixLocal,i18n("JFS - IBM's Journaled File System")),
|
|
'vfat' : (MountEntryExtVFAT,i18n("VFAT - Microsoft FAT File Systems")),
|
|
'ntfs' : (MountEntryExtVFAT,i18n("NTFS - NT File System")),
|
|
'udf' : (MountEntryExtSystem,i18n("udf")),
|
|
'iso9660' : (MountEntryExt,i18n("iso9660 - CD-ROM")),
|
|
}
|
|
|
|
notInFstab = False
|
|
maydisable = True # Some entries, such as /proc can't be disabled.
|
|
|
|
########################################################################
|
|
# Base can be either a fstab format line of text, of another MountEntry
|
|
# object.
|
|
def __init__(self,base=None):
|
|
try:
|
|
self.extensionObjects = {}
|
|
if base==None:
|
|
self.mounttype = 'auto'
|
|
elif isinstance(base,StringType) or isinstance(base,UnicodeType):
|
|
parts = base.split()
|
|
self.mounttype = parts[2]
|
|
# 'udf,iso9660' seems default for some devices in fstab,
|
|
# check if all listed filesystems are available, if yes set to 'auto'.
|
|
if len(self.mounttype.split(',')) > 1:
|
|
"""
|
|
# We could check here, but then we'd need a reference to MicroHAL.
|
|
#for m in self.mounttype.split(','):
|
|
#if m not in supported_fs:
|
|
# print "Filesystem ", m, "not supported by the kernel"
|
|
# break
|
|
"""
|
|
self.mounttype = "auto"
|
|
else:
|
|
# This is a new entry, but it's based on another one.
|
|
self.mounttype = base.mounttype
|
|
self.extension = self.MountTypes[self.mounttype][0](base)
|
|
self.extensionObjects[self.mounttype] = self.extension
|
|
except (KeyError,IndexError):
|
|
raise InvalidMountEntryError, u"Unable to parse mount entry:"+unicode(base)
|
|
|
|
########################################################################
|
|
def getMountType(self):
|
|
return self.mounttype
|
|
|
|
########################################################################
|
|
def setMountType(self,newtypename):
|
|
if newtypename not in self.extensionObjects:
|
|
try:
|
|
self.extensionObjects[newtypename] = self.MountTypes[newtypename][0](self.extension)
|
|
except KeyError:
|
|
raise NotImplementedError, "Unknown mounttype:"+newtypename
|
|
self.mounttype = newtypename
|
|
self.extension = self.extensionObjects[newtypename]
|
|
self.extension.setMountType(newtypename)
|
|
|
|
########################################################################
|
|
def copy(self):
|
|
newentry = MountEntry()
|
|
newentry.mounttype = self.mounttype
|
|
newext = self.extension.copy()
|
|
newentry.use_as_device = self.use_as_device
|
|
newentry.showlabel = self.showlabel
|
|
newentry.showdevice = self.showdevice
|
|
newentry.showuuid = self.showuuid
|
|
newentry.extensionObjects[self.mounttype] = newext
|
|
newentry.extension = newext
|
|
return newentry
|
|
|
|
########################################################################
|
|
def inPlaceCopyFrom(self,sourceentry):
|
|
self.extension.cleanup()
|
|
|
|
tmpcopy = sourceentry.copy()
|
|
self.extensionObjects = tmpcopy.extensionObjects
|
|
self.mounttype = tmpcopy.mounttype
|
|
self.extension = tmpcopy.extension
|
|
|
|
# Override the attribute lookup, set/get, to use the extension object
|
|
########################################################################
|
|
def __getattr__(self,name):
|
|
try:
|
|
return getattr(self.extension,name)
|
|
except AttributeError, a:
|
|
print a
|
|
|
|
########################################################################
|
|
# FIXME
|
|
## def __setattr__(self,name,value):
|
|
## if 'extension' in self.__dict__:
|
|
## if name in self.extension.__dict__:
|
|
## setattr(self.extension,name,value)
|
|
## return
|
|
## self.__dict__[name] = value
|
|
|
|
########################################################################
|
|
def getMountTypes():
|
|
return MountEntry.MountTypes.keys()
|
|
getMountTypes = staticmethod(getMountTypes)
|
|
|
|
########################################################################
|
|
def getMountTypeLongName(typename):
|
|
return MountEntry.MountTypes[typename][1]
|
|
getMountTypeLongName = staticmethod(getMountTypeLongName)
|
|
|
|
########################################################################
|
|
def encodeMountEntryString(string):
|
|
newstring = u""
|
|
for c in string:
|
|
if c==' ':
|
|
newstring += "\\040"
|
|
elif c=="\t":
|
|
newstring += "\\012"
|
|
elif c=='\\':
|
|
newstring += "\\134"
|
|
else:
|
|
newstring += c
|
|
return newstring
|
|
encodeMountEntryString = staticmethod(encodeMountEntryString)
|
|
|
|
########################################################################
|
|
def decodeMountEntryString(string):
|
|
newstring = ""
|
|
while string!="":
|
|
if len(string)>=4 and string[0]=='\\' and isoct(string[1]) \
|
|
and isoct(string[2]) and isoct(string[3]):
|
|
newstring += chr(64*(ord(string[1])-ord('0')) + \
|
|
8*(ord(string[2])-ord('0')) + (ord(string[3])-ord('0')))
|
|
string = string[4:]
|
|
else:
|
|
newstring += string[0]
|
|
string = string[1:]
|
|
return newstring
|
|
decodeMountEntryString = staticmethod(decodeMountEntryString)
|
|
|
|
############################################################################
|
|
class MountEntryComment(MountEntry):
|
|
""" This represents a comment mount entry or generally something that we don't
|
|
understand (might be comment, might be fstab syntax we don't know, might be
|
|
a faulty line in there). We don't want to wipe that stuff out, but we can't
|
|
deal with it in a sensible way, so we keep it in a MountEntryComment,
|
|
exclude it from most operations, but will write it back to fstab afterwards
|
|
|
|
As a result of that we only define the stuff that's necessary, namely saving
|
|
the fstab line and returning it when writing."""
|
|
|
|
########################################################################
|
|
def __init__(self,base=None):
|
|
self.row = base
|
|
|
|
########################################################################
|
|
def getFstabLine(self): return self.row
|
|
|
|
############################################################################
|
|
def isoct(c): return c in '01234567'
|
|
|
|
############################################################################
|
|
class InvalidMountEntryError(Exception):
|
|
|
|
########################################################################
|
|
def __init__(self,arg=None):
|
|
self.arg = arg
|
|
|
|
########################################################################
|
|
def __str__(self):
|
|
return str(self.arg)
|
|
|
|
############################################################################
|
|
class MountTable(object):
|
|
|
|
########################################################################
|
|
def __init__(self,fstab_filename,mtab_filename):
|
|
self.fstab_filename = fstab_filename
|
|
self.mtab_filename = mtab_filename
|
|
|
|
self.entries = []
|
|
self.allentries = []
|
|
|
|
# sysfs does not need an entry in fstab, so we add it even if it's not
|
|
# in there, it's mounted automatically anyway and shows up in mtab
|
|
sysfs_in_fstab = False
|
|
usbdevfs_in_fstab = False
|
|
|
|
fhandle = codecs.open(self.fstab_filename,'r',locale.getpreferredencoding())
|
|
for row in fhandle.readlines():
|
|
row = row.strip('\n') # Carefully remove any trailing newline.
|
|
if row.strip().startswith("#") or row.strip()=="":
|
|
entry = MountEntryComment(row)
|
|
else:
|
|
try:
|
|
entry = MountEntry(row)
|
|
self.append(entry)
|
|
|
|
if entry.getMountType() == "sysfs":
|
|
sysfs_in_fstab = True
|
|
if entry.getMountType() == "usbdevfs" or "procbususb":
|
|
usbdevfs_in_fstab = True
|
|
if entry.getMountType() == "proc":
|
|
entry.maydisable = False
|
|
except InvalidMountEntryError:
|
|
entry = MountEntryComment(row)
|
|
# We keep a list with references to _all_ entries, also the comments,
|
|
# this is the one we'll use to write out our new fstab, only 'real'
|
|
# entries (real == entries we understand) are added to self to let them
|
|
# be handled by iterator.
|
|
# allentries includes comments and invalid lines, self doesn't.
|
|
self.allentries.append(entry)
|
|
fhandle.close()
|
|
|
|
if not sysfs_in_fstab:
|
|
sysfsentry = MountEntry(u"sysfs /sys sysfs defaults 0 0")
|
|
sysfsentry.notInFstab = True
|
|
sysfsentry.maydisable = False
|
|
#self.append(sysfsentry)
|
|
|
|
if not usbdevfs_in_fstab:
|
|
usbdevfsentry = MountEntry(u"procbususb /proc/bus/usb usbdevfs defaults 0 0")
|
|
usbdevfsentry.notInFstab = True
|
|
usbdevfsentry.maydisable = False
|
|
self.append(usbdevfsentry)
|
|
|
|
self.updateStatus()
|
|
|
|
########################################################################
|
|
def append(self,entry):
|
|
self.entries.append(entry)
|
|
|
|
########################################################################
|
|
def remove(self,entry):
|
|
self.allentries.remove(entry)
|
|
entry.cleanup()
|
|
|
|
########################################################################
|
|
def updateStatus(self,entry=None):
|
|
mtablist = self.getMtabList()
|
|
if entry==None:
|
|
for entry in self.entries:
|
|
entry.updateStatus(mtablist)
|
|
else:
|
|
entry.updateStatus(mtablist)
|
|
|
|
########################################################################
|
|
def getMtabList(self):
|
|
fhandle = open(self.mtab_filename)
|
|
mtablist = []
|
|
for row in fhandle.readlines():
|
|
if row.strip()[0]!='#':
|
|
parts = row.split()
|
|
mtablist.append(parts[1])
|
|
fhandle.close()
|
|
return mtablist
|
|
|
|
########################################################################
|
|
def updateFstabOnDisk(self):
|
|
fhandle = None
|
|
try:
|
|
try:
|
|
fhandle = codecs.open(self.fstab_filename+"~","w",locale.getpreferredencoding(),'replace')
|
|
for entry in self.allentries:
|
|
if not entry.notInFstab:
|
|
line = entry.getFstabLine()
|
|
fhandle.write(line+u"\n")
|
|
print line
|
|
fhandle.close()
|
|
fhandle = None
|
|
|
|
# Move it over the original
|
|
os.rename(self.fstab_filename+"~",self.fstab_filename)
|
|
return True
|
|
finally:
|
|
if fhandle:
|
|
fhandle.close()
|
|
except IOError:
|
|
return False
|
|
|
|
########################################################################
|
|
# We make this class look like a container, and just forward everything
|
|
# on to the entries attribute.
|
|
def __contains__(self,item):
|
|
return self.entries.__contains(item)
|
|
########################################################################
|
|
def __delitem__(self,key):
|
|
raise NotImplementedError, "No __delitem__ on MountTable."
|
|
|
|
########################################################################
|
|
def __getitem__(self,key):
|
|
return self.entries.__getitem__(key)
|
|
########################################################################
|
|
|
|
def __iter__(self):
|
|
return self.entries.__iter__()
|
|
########################################################################
|
|
def __len__(self):
|
|
return self.entries.__len__()
|
|
########################################################################
|
|
def __setitem__(self,key,value):
|
|
raise NotImplementedError, "No __setitem__ on MountTable."
|
|
|
|
############################################################################
|
|
class MountEntryDialogOptions(TQWidget):
|
|
|
|
deviceexample = i18n("(for example /dev/hdb3)")
|
|
|
|
########################################################################
|
|
def __init__(self,parent,showmountpoint=True,showdevice=True,
|
|
showfs_freq=True,showfs_passno=True,showuuid=True,showlabel=True):
|
|
TQWidget.__init__(self,parent)
|
|
self.showmountpoint = showmountpoint
|
|
self.showdevice = showdevice
|
|
self.showfs_freq = showfs_freq
|
|
self.showfs_passno = showfs_passno
|
|
self.showuuid = showuuid
|
|
self.showlabel = showlabel
|
|
self._fillPage()
|
|
# TODO: KDirSelectDialog needs "Create new Folder"
|
|
self.mountpointdialog = KDirSelectDialog("/",True,self,"Select Mount Point",True)
|
|
|
|
########################################################################
|
|
def _fillPage(self):
|
|
row = 0
|
|
grid = TQGridLayout(self,1,2)
|
|
grid.setSpacing(KDialog.spacingHint())
|
|
grid.setColStretch(0,0)
|
|
grid.setColStretch(2,0)
|
|
|
|
if self.showmountpoint:
|
|
|
|
label = TQLabel(i18n("Mount Point:"),self)
|
|
grid.addWidget(label,row,0)
|
|
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.mountpointlineedit = KLineEdit(hbox)
|
|
hbox.setStretchFactor(self.mountpointlineedit,1)
|
|
#self.connect(self.homediredit, SIGNAL("textChanged(const TQString &)"), self.slotHomeDirChanged)
|
|
self.mountpointbutton = KPushButton(i18n("Browse..."),hbox)
|
|
hbox.setStretchFactor(self.mountpointbutton,0)
|
|
self.connect(self.mountpointbutton,SIGNAL("clicked()"),self.slotBrowseMountPointClicked)
|
|
grid.addMultiCellWidget(hbox,row,row,1,3)
|
|
row += 1
|
|
|
|
if self.showdevice:
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
|
|
label = TQLabel(i18n("Device:"),self)
|
|
grid.addWidget(label,row,0)
|
|
|
|
self.devicecheckbox = TQRadioButton(i18n("by name"),hbox)
|
|
self.connect(self.devicecheckbox,SIGNAL("clicked()"), \
|
|
self.slotDeviceCheckboxClicked)
|
|
self.devicelineedit = KLineEdit(hbox)
|
|
grid.addMultiCellWidget(hbox,row,row,1,3)
|
|
row += 1
|
|
example = TQLabel(self.deviceexample,self)
|
|
grid.addMultiCellWidget(example,row,row,1,3)
|
|
row += 1
|
|
|
|
if self.showuuid:
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.uuidcheckbox = TQRadioButton(i18n("by UUID"),hbox)
|
|
self.connect(self.uuidcheckbox,SIGNAL("clicked()"), \
|
|
self.slotUUIDCheckboxClicked)
|
|
self.uuidlineedit = KLineEdit(hbox)
|
|
grid.addMultiCellWidget(hbox,row,row,1,3)
|
|
row += 1
|
|
|
|
if self.showlabel:
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.labelcheckbox = TQRadioButton(i18n("by label"),hbox)
|
|
self.connect(self.labelcheckbox,SIGNAL("clicked()"), \
|
|
self.slotLabelCheckboxClicked)
|
|
self.labellineedit = KLineEdit(hbox)
|
|
grid.addMultiCellWidget(hbox,row,row,1,3)
|
|
row += 1
|
|
else:
|
|
if self.showdevice:
|
|
label = TQLabel(i18n("Device:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.devicelineedit = KLineEdit(self)
|
|
grid.addMultiCellWidget(self.devicelineedit,row,row,1,3)
|
|
row += 1
|
|
example = TQLabel(self.deviceexample,self)
|
|
grid.addWidget(example,row,1)
|
|
|
|
if self.showuuid:
|
|
label = TQLabel(i18n("Device UUID:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.uuidlineedit = KLineEdit(self)
|
|
grid.addMultiCellWidget(self.uuidlineedit,row,row,1,3)
|
|
row += 1
|
|
|
|
if self.showlabel:
|
|
label = TQLabel(i18n("Device Label:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.labellineedit = KLineEdit(self)
|
|
grid.addMultiCellWidget(self.labellineedit,row,row,1,3)
|
|
row += 1
|
|
|
|
label = TQLabel(i18n("Options:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.optionslineedit = KLineEdit(self)
|
|
grid.addMultiCellWidget(self.optionslineedit,row,row,1,3)
|
|
row += 1
|
|
|
|
if self.showfs_freq:
|
|
label = TQLabel(i18n("fs_freq:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.fsfreqspinbox = KIntSpinBox (0,1000,1,0,10,self)
|
|
grid.addWidget(self.fsfreqspinbox,row,1)
|
|
|
|
if self.showfs_passno:
|
|
label = TQLabel(i18n("fs_passno:"),self)
|
|
grid.addWidget(label,row,2)
|
|
self.fspassnospinbox = KIntSpinBox (0,1000,1,0,10,self)
|
|
grid.addWidget(self.fspassnospinbox,row,3)
|
|
row += 1
|
|
|
|
grid.addWidget(TQWidget(self),row,0)
|
|
|
|
for x in range(grid.numRows()):
|
|
grid.setRowStretch(x,0)
|
|
grid.setRowStretch(grid.numRows()-1,1)
|
|
|
|
########################################################################
|
|
def displayMountEntry(self,entry):
|
|
global allowuuid, allowlabel
|
|
if self.showmountpoint:
|
|
self.mountpointlineedit.setText(entry.getMountPoint())
|
|
|
|
uuid = entry.getUUID()
|
|
if entry.getDevice() == "" and uuid != "":
|
|
device = microhal.getDeviceByUUID(uuid)
|
|
self.devicelineedit.setText(uuid)
|
|
else:
|
|
if self.showdevice:
|
|
self.devicelineedit.setText(entry.getDevice())
|
|
|
|
if self.showuuid:
|
|
if entry.getUUID()!="":
|
|
self.uuidlineedit.setText(entry.getUUID())
|
|
|
|
if self.showlabel:
|
|
if entry.getLabel()!="":
|
|
self.labellineedit.setText(entry.getLabel())
|
|
|
|
if entry.getUseAsDevice() == "devicenode":
|
|
if self.showdevice:
|
|
self.devicelineedit.setEnabled(True)
|
|
self.devicecheckbox.setChecked(True)
|
|
if self.showuuid:
|
|
self.uuidcheckbox.setChecked(False)
|
|
self.uuidlineedit.setEnabled(False)
|
|
if self.showlabel:
|
|
self.labelcheckbox.setChecked(False)
|
|
self.labellineedit.setEnabled(False)
|
|
elif entry.getUseAsDevice() == "label":
|
|
if self.showlabel:
|
|
self.labellineedit.setEnabled(True)
|
|
self.labelcheckbox.setChecked(True)
|
|
if self.showdevice:
|
|
self.devicelineedit.setEnabled(False)
|
|
self.devicecheckbox.setChecked(False)
|
|
if self.showuuid:
|
|
self.uuidlineedit.setEnabled(False)
|
|
self.uuidcheckbox.setChecked(False)
|
|
elif entry.getUseAsDevice() == "uuid":
|
|
if self.showdevice:
|
|
self.devicecheckbox.setChecked(False)
|
|
self.devicelineedit.setEnabled(False)
|
|
if self.showlabel:
|
|
self.labelcheckbox.setChecked(False)
|
|
self.labellineedit.setEnabled(False)
|
|
if self.showuuid:
|
|
self.uuidlineedit.setEnabled(True)
|
|
self.uuidcheckbox.setChecked(True)
|
|
|
|
## if allowlabel:
|
|
## self.labellineedit.setText(entry.getLabel())
|
|
## if allowuuid:
|
|
## self.uuidlineedit.setText(entry.getUUID())
|
|
## self.devicelineedit.setText(entry.getDevice())
|
|
|
|
self.optionslineedit.setText(entry.getExtraOptions())
|
|
if self.showfs_freq:
|
|
self.fsfreqspinbox.setValue(entry.getFSFreq())
|
|
if self.showfs_passno:
|
|
self.fspassnospinbox.setValue(entry.getFSPassno())
|
|
|
|
########################################################################
|
|
def undisplayMountEntry(self,entry):
|
|
if self.showmountpoint:
|
|
entry.setMountPoint( unicode(self.mountpointlineedit.text()) )
|
|
if self.showdevice:
|
|
entry.setDevice( unicode(self.devicelineedit.text()) )
|
|
|
|
if self.showuuid and self.showdevice:
|
|
if self.devicecheckbox.isChecked():
|
|
entry.setUUID(None)
|
|
else:
|
|
entry.setUUID( unicode(self.uuidlineedit.text()) )
|
|
if self.showlabel and self.showdevice:
|
|
if self.devicecheckbox.isChecked():
|
|
entry.setLabel(None)
|
|
else:
|
|
entry.setLabel( unicode(self.labellineedit.text()) )
|
|
|
|
if allowuuid and self.showuuid:
|
|
if self.uuidcheckbox.isChecked():
|
|
entry.setUseAsDevice("uuid")
|
|
if allowlabel and self.showlabel:
|
|
if self.labelcheckbox.isChecked():
|
|
entry.setUseAsDevice("label")
|
|
if self.showdevice:
|
|
if self.devicecheckbox.isChecked():
|
|
entry.setUseAsDevice("devicenode")
|
|
|
|
entry.setExtraOptions( unicode(self.optionslineedit.text()) )
|
|
if self.showfs_freq:
|
|
entry.setFSFreq(self.fsfreqspinbox.value())
|
|
if self.showfs_passno:
|
|
entry.setFSPassno(self.fspassnospinbox.value())
|
|
|
|
########################################################################
|
|
def slotBrowseMountPointClicked(self):
|
|
fileurl = KURL()
|
|
fileurl.setPath(self.mountpointlineedit.text())
|
|
self.mountpointdialog.setCurrentURL(fileurl)
|
|
if self.mountpointdialog.exec_loop()==TQDialog.Accepted:
|
|
self.mountpointlineedit.setText(self.mountpointdialog.url().path())
|
|
|
|
########################################################################
|
|
def slotDeviceCheckboxClicked(self):
|
|
self.uuidcheckbox.setChecked(False)
|
|
self.labelcheckbox.setChecked(False)
|
|
self.devicelineedit.setEnabled(True)
|
|
self.uuidlineedit.setEnabled(False)
|
|
self.labellineedit.setEnabled(False)
|
|
|
|
########################################################################
|
|
def slotUUIDCheckboxClicked(self):
|
|
if self.uuidlineedit.text() == "":
|
|
label = microhal.getUUIDByDevice(unicode(self.devicelineedit.text()))
|
|
self.uuidlineedit.setText(label)
|
|
self.devicecheckbox.setChecked(False)
|
|
self.devicelineedit.setEnabled(False)
|
|
self.uuidlineedit.setEnabled(True)
|
|
self.labelcheckbox.setChecked(False)
|
|
self.labellineedit.setEnabled(False)
|
|
|
|
def slotLabelCheckboxClicked(self):
|
|
if self.labellineedit.text() == "":
|
|
label = microhal.getLabelByDevice(unicode(self.devicelineedit.text()))
|
|
self.labellineedit.setText(label)
|
|
self.uuidcheckbox.setChecked(False)
|
|
self.devicelineedit.setEnabled(False)
|
|
self.uuidlineedit.setEnabled(False)
|
|
self.labelcheckbox.setChecked(True)
|
|
self.labellineedit.setEnabled(True)
|
|
|
|
############################################################################
|
|
class MountEntryDialogOptionsCommonUnix(MountEntryDialogOptions):
|
|
|
|
########################################################################
|
|
def __init__(self,parent):
|
|
MountEntryDialogOptions.__init__(self,parent)
|
|
self.advanceddialog = MountEntryAdvancedCommonUnixDialog(None)
|
|
|
|
########################################################################
|
|
def _fillPage(self):
|
|
|
|
row = 0
|
|
grid = TQGridLayout(self,1,2)
|
|
grid.setSpacing(KDialog.spacingHint())
|
|
grid.setColStretch(0,0)
|
|
grid.setRowStretch(6,1)
|
|
|
|
label = TQLabel(i18n("Mount Point:"),self)
|
|
grid.addWidget(label,row,0)
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.mountpointlineedit = KLineEdit(hbox)
|
|
hbox.setStretchFactor(self.mountpointlineedit,1)
|
|
#self.connect(self.homediredit, SIGNAL("textChanged(const TQString &)"), self.slotHomeDirChanged)
|
|
self.mountpointbutton = KPushButton(i18n("Browse..."),hbox)
|
|
hbox.setStretchFactor(self.mountpointbutton,0)
|
|
self.connect(self.mountpointbutton,SIGNAL("clicked()"), \
|
|
self.slotBrowseMountPointClicked)
|
|
grid.addWidget(hbox,row,1)
|
|
row += 1
|
|
|
|
if self.showuuid or self.showlabel:
|
|
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
|
|
label = TQLabel(i18n("Device:"),self)
|
|
grid.addWidget(label,row,0)
|
|
|
|
self.devicecheckbox = TQRadioButton(i18n("by name"),hbox)
|
|
self.connect(self.devicecheckbox,SIGNAL("clicked()"), \
|
|
self.slotDeviceCheckboxClicked)
|
|
self.devicelineedit = KLineEdit(hbox)
|
|
grid.addWidget(hbox,row,1)
|
|
row += 1
|
|
example = TQLabel(self.deviceexample,self)
|
|
grid.addWidget(example,row,1)
|
|
row += 1
|
|
|
|
if self.showuuid:
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.uuidcheckbox = TQRadioButton(i18n("by UUID"),hbox)
|
|
self.connect(self.uuidcheckbox,SIGNAL("clicked()"), \
|
|
self.slotUUIDCheckboxClicked)
|
|
self.uuidlineedit = KLineEdit(hbox)
|
|
grid.addWidget(hbox,row,1)
|
|
row += 1
|
|
|
|
if self.showlabel:
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.labelcheckbox = TQRadioButton(i18n("by label"),hbox)
|
|
self.connect(self.labelcheckbox,SIGNAL("clicked()"), \
|
|
self.slotLabelCheckboxClicked)
|
|
self.labellineedit = KLineEdit(hbox)
|
|
grid.addWidget(hbox,row,1)
|
|
row += 1
|
|
|
|
else:
|
|
label = TQLabel(i18n("Device:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.devicelineedit = KLineEdit(self)
|
|
grid.addWidget(self.devicelineedit,row,1)
|
|
row += 1
|
|
example = TQLabel(self.deviceexample,self)
|
|
grid.addWidget(example,row,1)
|
|
row += 1
|
|
|
|
self.autocheckbox = TQCheckBox(i18n("Enable at start up"),self)
|
|
grid.addWidget(self.autocheckbox,row,1)
|
|
row += 1
|
|
|
|
self.writeablecheckbox = TQCheckBox(i18n("Writeable"),self)
|
|
grid.addWidget(self.writeablecheckbox,row,1)
|
|
row += 1
|
|
|
|
label = TQLabel(i18n("Mount Permission:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.usermountcombobox = KComboBox(self)
|
|
self.usermountcombobox.insertItem(i18n("Root user only may enable/disable"))
|
|
self.usermountcombobox.insertItem(i18n("One user at a time may enable/disable"))
|
|
self.usermountcombobox.insertItem(i18n("Any user may enable/disable anytime"))
|
|
self.usermountcombobox.insertItem(i18n("Device owner may enable/disable"))
|
|
grid.addWidget(self.usermountcombobox,row,1)
|
|
row += 1
|
|
|
|
#grid.addWidget(,9,0)
|
|
button = KPushButton(i18n("Advanced..."),self)
|
|
button.setSizePolicy(TQSizePolicy.Fixed,TQSizePolicy.Fixed)
|
|
self.connect(button,SIGNAL("clicked()"),self.slotAdvancedClicked)
|
|
grid.addWidget(button,row,1,TQt.AlignRight)
|
|
row += 1
|
|
|
|
grid.addWidget(TQWidget(self),row,0)
|
|
|
|
for x in range(grid.numRows()):
|
|
grid.setRowStretch(x,0)
|
|
grid.setRowStretch(grid.numRows()-1,1)
|
|
|
|
########################################################################
|
|
def displayMountEntry(self,entry):
|
|
self.devicelineedit.setText(entry.getDevice())
|
|
|
|
if self.showuuid:
|
|
if entry.getUUID()!="":
|
|
self.uuidlineedit.setText(entry.getUUID())
|
|
|
|
if self.showlabel:
|
|
if entry.getLabel()!="":
|
|
self.labellineedit.setText(entry.getLabel())
|
|
|
|
if entry.getUseAsDevice() == "devicenode":
|
|
self.devicelineedit.setEnabled(True)
|
|
self.devicecheckbox.setChecked(True)
|
|
self.uuidcheckbox.setChecked(False)
|
|
self.uuidlineedit.setEnabled(False)
|
|
self.labelcheckbox.setChecked(False)
|
|
self.labellineedit.setEnabled(False)
|
|
elif entry.getUseAsDevice() == "label":
|
|
self.labellineedit.setEnabled(True)
|
|
self.labelcheckbox.setChecked(True)
|
|
self.devicelineedit.setEnabled(False)
|
|
self.devicecheckbox.setChecked(False)
|
|
self.uuidlineedit.setEnabled(False)
|
|
self.uuidcheckbox.setChecked(False)
|
|
elif entry.getUseAsDevice() == "uuid":
|
|
self.devicecheckbox.setChecked(False)
|
|
self.devicelineedit.setEnabled(False)
|
|
self.labelcheckbox.setChecked(False)
|
|
self.labellineedit.setEnabled(False)
|
|
self.uuidlineedit.setEnabled(True)
|
|
self.uuidcheckbox.setChecked(True)
|
|
|
|
self.devicelineedit.setText(entry.getDevice())
|
|
self.mountpointlineedit.setText(entry.getMountPoint())
|
|
self.options = entry.getExtraOptions()
|
|
self.fsfreq = entry.getFSFreq()
|
|
self.fspassno = entry.getFSPassno()
|
|
self.autocheckbox.setChecked(entry.getMountAtBoot())
|
|
self.writeablecheckbox.setChecked(entry.getWritable())
|
|
self.accesstime = entry.getAtime()
|
|
self.allowexecutable = entry.getAllowExecutables()
|
|
self.allowsuid = entry.getSUID()
|
|
self.usedevpoints = entry.getUseDevPoints()
|
|
self.usermountcombobox.setCurrentItem(entry.getAllowUserMount())
|
|
|
|
########################################################################
|
|
def undisplayMountEntry(self,entry):
|
|
|
|
entry.setDevice( unicode(self.devicelineedit.text()) )
|
|
if self.showuuid:
|
|
if self.devicecheckbox.isChecked() or self.labelcheckbox.isChecked():
|
|
entry.setUUID(None)
|
|
else:
|
|
entry.setUUID( unicode(self.uuidlineedit.text()) )
|
|
|
|
if self.showlabel:
|
|
if self.devicecheckbox.isChecked() or self.uuidcheckbox.isChecked():
|
|
entry.setLabel(None)
|
|
else:
|
|
entry.setLabel( unicode(self.labellineedit.text()) )
|
|
|
|
if not self.showlabel and not self.showuuid:
|
|
if self.uuidcheckbox.isChecked() or self.labelcheckbox.isChecked():
|
|
entry.setLabel(None)
|
|
else:
|
|
entry.setLabel( unicode(self.devicelineedit.text()) )
|
|
|
|
if allowuuid:
|
|
if self.uuidcheckbox.isChecked():
|
|
entry.setUseAsDevice("uuid")
|
|
if allowlabel:
|
|
if self.labelcheckbox.isChecked():
|
|
entry.setUseAsDevice("label")
|
|
if self.devicecheckbox.isChecked():
|
|
entry.setUseAsDevice("devicenode")
|
|
|
|
entry.setMountPoint( unicode(self.mountpointlineedit.text()) )
|
|
entry.setExtraOptions(self.options)
|
|
entry.setFSFreq(self.fsfreq)
|
|
entry.setFSPassno(self.fspassno)
|
|
entry.setAtime(self.accesstime)
|
|
entry.setMountAtBoot(self.autocheckbox.isChecked())
|
|
entry.setWritable(self.writeablecheckbox.isChecked())
|
|
entry.setUseDevPoints(self.usedevpoints)
|
|
entry.setAllowExecutable(self.allowexecutable)
|
|
entry.setSUID(self.allowsuid)
|
|
entry.setAllowUserMount(self.usermountcombobox.currentItem())
|
|
|
|
########################################################################
|
|
def slotAdvancedClicked(self):
|
|
(self.accesstime, self.allowexecutable, self.allowsuid, self.usedevpoints, self.options, self.fsfreq,
|
|
self.fspassno)\
|
|
= self.advanceddialog.do(self.accesstime, self.allowexecutable, self.allowsuid, self.usedevpoints,
|
|
self.options, self.fsfreq, self.fspassno)
|
|
|
|
########################################################################
|
|
def slotDeviceCheckboxClicked(self):
|
|
self.uuidcheckbox.setChecked(False)
|
|
self.devicelineedit.setEnabled(True)
|
|
self.labelcheckbox.setChecked(False)
|
|
self.labellineedit.setEnabled(False)
|
|
self.uuidlineedit.setEnabled(False)
|
|
|
|
########################################################################
|
|
def slotUUIDCheckboxClicked(self):
|
|
if self.uuidlineedit.text() == "":
|
|
label = microhal.getUUIDByDevice(unicode(self.devicelineedit.text()))
|
|
self.uuidlineedit.setText(label)
|
|
self.devicecheckbox.setChecked(False)
|
|
self.devicelineedit.setEnabled(False)
|
|
self.labelcheckbox.setChecked(False)
|
|
self.labellineedit.setEnabled(False)
|
|
self.uuidlineedit.setEnabled(True)
|
|
|
|
def slotLabelCheckboxClicked(self):
|
|
if self.labellineedit.text() == "":
|
|
label = microhal.getLabelByDevice(unicode(self.devicelineedit.text()))
|
|
self.labellineedit.setText(label)
|
|
self.devicecheckbox.setChecked(False)
|
|
self.devicelineedit.setEnabled(False)
|
|
self.uuidcheckbox.setChecked(False)
|
|
self.uuidlineedit.setEnabled(False)
|
|
self.labellineedit.setEnabled(True)
|
|
|
|
############################################################################
|
|
class MountEntryDialogOptionsSys(MountEntryDialogOptions):
|
|
########################################################################
|
|
def __init__(self,parent):
|
|
MountEntryDialogOptions.__init__(self,parent,True,False,False,False,False,False)
|
|
|
|
############################################################################
|
|
class MountEntryDialogOptionsSwap(MountEntryDialogOptions):
|
|
########################################################################
|
|
def __init__(self,parent):
|
|
MountEntryDialogOptions.__init__(self,parent,False,True,False,False)
|
|
|
|
class MountEntryDialogOptionsNfs(MountEntryDialogOptionsCommonUnix):
|
|
|
|
deviceexample = i18n("(for example 192.168.1.66:/export)")
|
|
|
|
############################################################################
|
|
class MountEntryDialogOptionsVFAT(MountEntryDialogOptions):
|
|
########################################################################
|
|
def __init__(self,parent):
|
|
MountEntryDialogOptions.__init__(self,parent)
|
|
self.advanceddialog = MountEntryAdvancedPlainDialog(None)
|
|
self.updatinggui= False
|
|
|
|
########################################################################
|
|
def _fillPage(self):
|
|
global allowuuid, allowlabel
|
|
|
|
row = 0
|
|
grid = TQGridLayout(self,11,2)
|
|
grid.setSpacing(KDialog.spacingHint())
|
|
grid.setColStretch(0,0)
|
|
grid.setColStretch(2,0)
|
|
grid.setRowStretch(10,1)
|
|
|
|
label = TQLabel(i18n("Mount Point:"),self)
|
|
grid.addWidget(label,row,0)
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.mountpointlineedit = KLineEdit(hbox)
|
|
hbox.setStretchFactor(self.mountpointlineedit,1)
|
|
#self.connect(self.homediredit, SIGNAL("textChanged(const TQString &)"), self.slotHomeDirChanged)
|
|
self.mountpointbutton = KPushButton(i18n("Browse..."),hbox)
|
|
hbox.setStretchFactor(self.mountpointbutton,0)
|
|
self.connect(self.mountpointbutton,SIGNAL("clicked()"),self.slotBrowseMountPointClicked)
|
|
grid.addMultiCellWidget(hbox,row,row,1,3)
|
|
row += 1
|
|
|
|
if allowuuid or allowlabel:
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
|
|
label = TQLabel(i18n("Device:"),self)
|
|
grid.addWidget(label,row,0)
|
|
|
|
self.devicecheckbox = TQRadioButton(i18n("by name"),hbox)
|
|
self.connect(self.devicecheckbox,SIGNAL("clicked()"), \
|
|
self.slotDeviceCheckboxClicked)
|
|
self.devicelineedit = KLineEdit(hbox)
|
|
grid.addWidget(hbox,row,1)
|
|
row += 1
|
|
example = TQLabel(self.deviceexample,self)
|
|
grid.addWidget(example,row,1)
|
|
row += 1
|
|
|
|
if allowuuid and self.showuuid:
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.uuidcheckbox = TQRadioButton(i18n("by UUID"),hbox)
|
|
self.connect(self.uuidcheckbox,SIGNAL("clicked()"), \
|
|
self.slotUUIDCheckboxClicked)
|
|
self.uuidlineedit = KLineEdit(hbox)
|
|
grid.addWidget(hbox,row,1)
|
|
row += 1
|
|
|
|
if allowlabel and self.showlabel:
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.labelcheckbox = TQRadioButton(i18n("by label"),hbox)
|
|
self.connect(self.labelcheckbox,SIGNAL("clicked()"), \
|
|
self.slotLabelCheckboxClicked)
|
|
self.labellineedit = KLineEdit(hbox)
|
|
grid.addWidget(hbox,row,1)
|
|
row += 1
|
|
|
|
else:
|
|
|
|
label = TQLabel(i18n("Device:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.devicelineedit = KLineEdit(self)
|
|
grid.addMultiCellWidget(self.devicelineedit,row,row,1,3)
|
|
row += 1
|
|
|
|
example = TQLabel(self.deviceexample,self)
|
|
grid.addWidget(example,row,1)
|
|
row += 1
|
|
|
|
self.autocheckbox = TQCheckBox(i18n("Enable at start up"),self)
|
|
grid.addMultiCellWidget(self.autocheckbox,row,row,1,3)
|
|
row += 1
|
|
|
|
# Security & Safety line.
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
tmplabel = TQLabel(hbox)
|
|
tmplabel.setPixmap(UserIcon("hi16-lock"))
|
|
hbox.setStretchFactor(tmplabel,0)
|
|
tmplabel = TQLabel(hbox)
|
|
tmplabel.setText(i18n("Security & Safety"))
|
|
hbox.setStretchFactor(tmplabel,0)
|
|
sep = KSeparator(KSeparator.Horizontal,hbox)
|
|
hbox.setStretchFactor(sep,1)
|
|
grid.addMultiCellWidget(hbox,row,row,0,3)
|
|
row += 1
|
|
|
|
self.writeablecheckbox = TQCheckBox(i18n("Writeable"),self)
|
|
grid.addMultiCellWidget(self.writeablecheckbox,row,row,1,3)
|
|
row += 1
|
|
|
|
label = TQLabel(i18n("Files belong to user:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.uidcombobox = UserComboBox(self)
|
|
grid.addMultiCellWidget(self.uidcombobox,row,row,1,3)
|
|
row += 1
|
|
|
|
label = TQLabel(i18n("Files belong to group:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.gidcombobox = GroupComboBox(self)
|
|
grid.addMultiCellWidget(self.gidcombobox,row,row,1,3)
|
|
row += 1
|
|
|
|
label = TQLabel(i18n("Mount Permission:"),self)
|
|
grid.addWidget(label,row,0)
|
|
self.usermountcombobox = KComboBox(self)
|
|
self.usermountcombobox.insertItem(i18n("Root user only may enable/disable"))
|
|
self.usermountcombobox.insertItem(i18n("One user at a time may enable/disable"))
|
|
self.usermountcombobox.insertItem(i18n("Any user may enable/disable anytime"))
|
|
self.usermountcombobox.insertItem(i18n("Device owner may enable/disable"))
|
|
grid.addMultiCellWidget(self.usermountcombobox,row,row,1,3)
|
|
row += 1
|
|
|
|
self.suppresspermissionerrorcheckbox = TQCheckBox(i18n("Suppress permission errors"),self)
|
|
grid.addMultiCellWidget(self.suppresspermissionerrorcheckbox,row,row,1,3)
|
|
row += 1
|
|
|
|
row += 1
|
|
button = KPushButton(i18n("Advanced..."),self)
|
|
button.setSizePolicy(TQSizePolicy.Fixed,TQSizePolicy.Fixed)
|
|
self.connect(button,SIGNAL("clicked()"),self.slotAdvancedClicked)
|
|
grid.addMultiCellWidget(button,row,row,1,3,TQt.AlignRight)
|
|
|
|
########################################################################
|
|
def displayMountEntry(self,entry):
|
|
global allowuuid, allowlabel
|
|
|
|
uuid = entry.getUUID()
|
|
if entry.getDevice() == "" and uuid != "":
|
|
device = microhal.getDeviceByUUID(uuid)
|
|
self.devicelineedit.setText(uuid)
|
|
else:
|
|
self.devicelineedit.setText(entry.getDevice())
|
|
|
|
if allowuuid:
|
|
self.uuidlineedit.setText(uuid)
|
|
if entry.getUUID()!="":
|
|
self.uuidlineedit.setEnabled(True)
|
|
self.devicelineedit.setEnabled(False)
|
|
self.devicecheckbox.setChecked(False)
|
|
self.uuidcheckbox.setChecked(True)
|
|
else:
|
|
self.devicelineedit.setEnabled(True)
|
|
self.uuidlineedit.setEnabled(False)
|
|
self.devicecheckbox.setChecked(True)
|
|
self.uuidcheckbox.setChecked(False)
|
|
|
|
if allowlabel: # If the filesystem has a label override the UUID settings
|
|
self.labellineedit.setText(entry.getLabel())
|
|
if entry.getLabel()!="":
|
|
self.labellineedit.setEnabled(True)
|
|
self.devicelineedit.setEnabled(False)
|
|
self.devicecheckbox.setChecked(False)
|
|
self.labelcheckbox.setChecked(True)
|
|
self.uuidlineedit.setEnabled(False)
|
|
self.uuidcheckbox.setChecked(False)
|
|
else:
|
|
if entry.getUUID()!="":
|
|
self.uuidlineedit.setEnabled(True)
|
|
self.devicelineedit.setEnabled(False)
|
|
self.devicecheckbox.setChecked(False)
|
|
self.uuidcheckbox.setChecked(True)
|
|
else:
|
|
self.devicelineedit.setEnabled(True)
|
|
self.uuidlineedit.setEnabled(False)
|
|
self.devicecheckbox.setChecked(True)
|
|
self.uuidcheckbox.setChecked(False)
|
|
|
|
if allowlabel:
|
|
self.labellineedit.setText(entry.getLabel())
|
|
if allowuuid:
|
|
self.uuidlineedit.setText(entry.getUUID())
|
|
self.devicelineedit.setText(entry.getDevice())
|
|
|
|
self.mountpointlineedit.setText(entry.getMountPoint())
|
|
self.options = entry.getExtraOptions()
|
|
self.fsfreq = entry.getFSFreq()
|
|
self.fspassno = entry.getFSPassno()
|
|
self.writeablecheckbox.setChecked(entry.getWritable())
|
|
self.autocheckbox.setChecked(entry.getMountAtBoot())
|
|
self.usermountcombobox.setCurrentItem(entry.getAllowUserMount())
|
|
self.uidcombobox.setUID(entry.getUID())
|
|
self.gidcombobox.setGID(entry.getGID())
|
|
self.suppresspermissionerrorcheckbox.setChecked(entry.getSuppressPermissionErrors())
|
|
|
|
########################################################################
|
|
def undisplayMountEntry(self,entry):
|
|
global allowuuid, allowlabel
|
|
if allowuuid:
|
|
if self.devicecheckbox.isChecked():
|
|
entry.setUUID(None)
|
|
else:
|
|
if allowlabel:
|
|
if self.labelcheckbox.isChecked():
|
|
entry.setLabel( unicode(self.labellineedit.text()) )
|
|
else:
|
|
entry.setUUID( unicode(self.uuidlineedit.text()) )
|
|
else:
|
|
entry.setUUID( unicode(self.uuidlineedit.text()) )
|
|
|
|
if allowlabel:
|
|
if self.devicecheckbox.isChecked():
|
|
entry.setLabel(None)
|
|
else:
|
|
if allowuuid:
|
|
if self.uuidcheckbox.isChecked():
|
|
entry.setUUID( unicode(self.uuidlineedit.text()) )
|
|
else:
|
|
entry.setLabel( unicode(self.labellineedit.text()) )
|
|
else:
|
|
entry.setLabel( unicode(self.labellineedit.text()) )
|
|
|
|
entry.setDevice( unicode(self.devicelineedit.text()) )
|
|
|
|
entry.setMountPoint( unicode(self.mountpointlineedit.text()) )
|
|
entry.setExtraOptions(self.options)
|
|
entry.setFSFreq(self.fsfreq)
|
|
entry.setFSPassno(self.fspassno)
|
|
entry.setMountAtBoot(self.autocheckbox.isChecked())
|
|
entry.setWritable(self.writeablecheckbox.isChecked())
|
|
entry.setAllowUserMount(self.usermountcombobox.currentItem())
|
|
entry.setUID(self.uidcombobox.UID())
|
|
entry.setGID(self.gidcombobox.GID())
|
|
entry.setSuppressPermissionErrors(self.suppresspermissionerrorcheckbox.isChecked())
|
|
|
|
########################################################################
|
|
def slotAdvancedClicked(self):
|
|
(self.options, self.fsfreq, self.fspassno)\
|
|
= self.advanceddialog.do(self.options, self.fsfreq, self.fspassno)
|
|
|
|
########################################################################
|
|
def slotDeviceCheckboxClicked(self):
|
|
self.uuidcheckbox.setChecked(False)
|
|
self.devicelineedit.setEnabled(True)
|
|
self.uuidlineedit.setEnabled(False)
|
|
|
|
########################################################################
|
|
def slotUUIDCheckboxClicked(self):
|
|
if self.uuidlineedit.text() == "":
|
|
label = microhal.getUUIDByDevice(unicode(self.devicelineedit.text()))
|
|
self.uuidlineedit.setText(label)
|
|
self.devicecheckbox.setChecked(False)
|
|
self.devicelineedit.setEnabled(False)
|
|
self.uuidlineedit.setEnabled(True)
|
|
|
|
############################################################################
|
|
class MountEntryDialogOptionsSMB(MountEntryDialogOptions):
|
|
|
|
########################################################################
|
|
def __init__(self,parent):
|
|
MountEntryDialogOptions.__init__(self,parent)
|
|
self.advanceddialog = MountEntryAdvancedPlainDialog(None)
|
|
self.updatinggui= False
|
|
|
|
########################################################################
|
|
def _fillPage(self):
|
|
grid = TQGridLayout(self,14,4)
|
|
grid.setSpacing(KDialog.spacingHint())
|
|
grid.setColStretch(0,0)
|
|
grid.setColStretch(2,0)
|
|
grid.setRowStretch(12,1)
|
|
|
|
label = TQLabel(i18n("Mount Point:"),self)
|
|
grid.addWidget(label,0,0)
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.mountpointlineedit = KLineEdit(hbox)
|
|
hbox.setStretchFactor(self.mountpointlineedit,1)
|
|
#self.connect(self.homediredit, SIGNAL("textChanged(const TQString &)"), self.slotHomeDirChanged)
|
|
self.mountpointbutton = KPushButton(i18n("Browse..."),hbox)
|
|
hbox.setStretchFactor(self.mountpointbutton,0)
|
|
self.connect(self.mountpointbutton,SIGNAL("clicked()"),self.slotBrowseMountPointClicked)
|
|
grid.addMultiCellWidget(hbox,0,0,1,3)
|
|
|
|
label = TQLabel(i18n("Network Share:"),self)
|
|
grid.addWidget(label,1,0)
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
self.devicelineedit = KLineEdit(hbox)
|
|
hbox.setStretchFactor(self.devicelineedit,1)
|
|
self.devicelinebutton = KPushButton(i18n("Scan..."),hbox)
|
|
hbox.setStretchFactor(self.devicelinebutton,0)
|
|
self.connect(self.devicelinebutton,SIGNAL("clicked()"),self.slotBrowseDeviceLineClicked)
|
|
grid.addMultiCellWidget(hbox,1,1,1,3)
|
|
|
|
# Connect as:
|
|
connectaslabel = TQLabel(self)
|
|
connectaslabel.setText(i18n("Connect as:"))
|
|
grid.addWidget(connectaslabel,2,0)
|
|
|
|
self.guestradio = TQRadioButton(self)
|
|
self.guestradio.setChecked(True)
|
|
grid.addWidget(self.guestradio,2,1)
|
|
tmplabel = TQLabel(self)
|
|
tmplabel.setText(i18n("Guest"))
|
|
grid.addMultiCellWidget(tmplabel,2,2,2,3)
|
|
self.connect(self.guestradio,SIGNAL("stateChanged(int)"),self.slotGuestRadioClicked)
|
|
|
|
self.userradio = TQRadioButton(self)
|
|
grid.addWidget(self.userradio,3,1)
|
|
tmplabel = TQLabel(self)
|
|
tmplabel.setText(i18n("Username:"))
|
|
grid.addWidget(tmplabel,3,2)
|
|
self.connect(self.userradio,SIGNAL("stateChanged(int)"),self.slotUserRadioClicked)
|
|
|
|
self.usernameedit = KLineEdit(self)
|
|
grid.addWidget(self.usernameedit,3,3)
|
|
|
|
tmplabel = TQLabel(self)
|
|
tmplabel.setText(i18n("Password:"))
|
|
grid.addWidget(tmplabel,4,2)
|
|
|
|
self.passwordedit = KLineEdit(self)
|
|
grid.addWidget(self.passwordedit,4,3)
|
|
|
|
self.autocheckbox = TQCheckBox(i18n("Enable at start up"),self)
|
|
grid.addMultiCellWidget(self.autocheckbox,5,5,1,3)
|
|
|
|
# Security & Safety line.
|
|
hbox = TQHBox(self)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
tmplabel = TQLabel(hbox)
|
|
tmplabel.setPixmap(UserIcon("hi16-lock"))
|
|
hbox.setStretchFactor(tmplabel,0)
|
|
tmplabel = TQLabel(hbox)
|
|
tmplabel.setText(i18n("Security & Safety"))
|
|
hbox.setStretchFactor(tmplabel,0)
|
|
sep = KSeparator(KSeparator.Horizontal,hbox)
|
|
hbox.setStretchFactor(sep,1)
|
|
grid.addMultiCellWidget(hbox,6,6,0,3)
|
|
|
|
self.writeablecheckbox = TQCheckBox(i18n("Writeable"),self)
|
|
grid.addMultiCellWidget(self.writeablecheckbox,7,7,1,3)
|
|
|
|
label = TQLabel(i18n("Files belong to user:"),self)
|
|
grid.addWidget(label,8,0)
|
|
self.uidcombobox = UserComboBox(self)
|
|
grid.addMultiCellWidget(self.uidcombobox,8,8,1,3)
|
|
|
|
label = TQLabel(i18n("Files belong to group:"),self)
|
|
grid.addWidget(label,9,0)
|
|
self.gidcombobox = GroupComboBox(self)
|
|
grid.addMultiCellWidget(self.gidcombobox,9,9,1,3)
|
|
|
|
label = TQLabel(i18n("Mount Permission:"),self)
|
|
grid.addWidget(label,10,0)
|
|
self.usermountcombobox = KComboBox(self)
|
|
self.usermountcombobox.insertItem(i18n("Root user only may enable/disable"))
|
|
self.usermountcombobox.insertItem(i18n("One user at a time may enable/disable"))
|
|
self.usermountcombobox.insertItem(i18n("Any user may enable/disable anytime"))
|
|
self.usermountcombobox.insertItem(i18n("Device owner may enable/disable"))
|
|
grid.addMultiCellWidget(self.usermountcombobox,10,10,1,3)
|
|
|
|
button = KPushButton(i18n("Advanced..."),self)
|
|
button.setSizePolicy(TQSizePolicy.Fixed,TQSizePolicy.Fixed)
|
|
self.connect(button,SIGNAL("clicked()"),self.slotAdvancedClicked)
|
|
grid.addMultiCellWidget(button,13,13,1,3,TQt.AlignRight)
|
|
|
|
self.selectsmbdialog = None
|
|
|
|
########################################################################
|
|
def slotBrowseDeviceLineClicked(self):
|
|
if self.updatinggui:
|
|
return
|
|
self.updatinggui = True
|
|
|
|
if self.selectsmbdialog is None:
|
|
self.selectsmbdialog = SMBShareSelectDialog(None)
|
|
|
|
# This just converts a \\zootv\data\ share name to smb:/zootv/data
|
|
parts = [x.replace("/",'\\') for x in unicode(self.devicelineedit.text()).split('\\') if x!=""]
|
|
oldurl = u"smb:/"+("/".join(parts) )
|
|
|
|
urlobj = KURL(oldurl)
|
|
if self.userradio.isChecked():
|
|
urlobj.setUser(self.usernameedit.text())
|
|
urlobj.setPass(self.passwordedit.text())
|
|
|
|
newurlobj = self.selectsmbdialog.choose(urlobj)
|
|
# This just converts smb:/zootv/data to \\zootv\data.
|
|
plainurl = KURL(newurlobj)
|
|
plainurl.setUser(TQString.null)
|
|
plainurl.setPass(TQString.null)
|
|
parts = [x.replace('\\',"/") for x in unicode(plainurl.url())[4:].split("/") if x !=""]
|
|
#convert the first part to an IP address
|
|
nmboutput = subprocess.Popen(["nmblookup",parts[0]], stdout=subprocess.PIPE).stdout
|
|
nmboutput.readline()
|
|
ipaddress = nmboutput.readline().split(" ")[0]
|
|
parts[0] = ipaddress
|
|
self.devicelineedit.setText(r'\\'+('\\'.join(parts)))
|
|
|
|
if not newurlobj.hasUser():
|
|
self.guestradio.setChecked(True)
|
|
self.userradio.setChecked(False)
|
|
self.passwordedit.setEnabled(False)
|
|
self.usernameedit.setEnabled(False)
|
|
self.usernameedit.setText("")
|
|
self.passwordedit.setText("")
|
|
else:
|
|
self.guestradio.setChecked(False)
|
|
self.userradio.setChecked(True)
|
|
self.passwordedit.setEnabled(True)
|
|
self.usernameedit.setEnabled(True)
|
|
self.usernameedit.setText(newurlobj.user())
|
|
self.passwordedit.setText(newurlobj.pass_())
|
|
|
|
self.updatinggui = False
|
|
|
|
########################################################################
|
|
def displayMountEntry(self,entry):
|
|
self.devicelineedit.setText(entry.getDevice())
|
|
self.mountpointlineedit.setText(entry.getMountPoint())
|
|
self.options = entry.getExtraOptions()
|
|
self.fsfreq = entry.getFSFreq()
|
|
self.fspassno = entry.getFSPassno()
|
|
self.writeablecheckbox.setChecked(entry.getWritable())
|
|
self.autocheckbox.setChecked(entry.getMountAtBoot())
|
|
self.usermountcombobox.setCurrentItem(entry.getAllowUserMount())
|
|
self.uidcombobox.setUID(entry.getUID())
|
|
self.gidcombobox.setGID(entry.getGID())
|
|
|
|
if entry.getUsername() is None:
|
|
self.guestradio.setChecked(True)
|
|
self.userradio.setChecked(False)
|
|
self.passwordedit.setEnabled(False)
|
|
self.usernameedit.setEnabled(False)
|
|
self.usernameedit.setText("")
|
|
self.passwordedit.setText("")
|
|
else:
|
|
self.guestradio.setChecked(False)
|
|
self.userradio.setChecked(True)
|
|
self.passwordedit.setEnabled(True)
|
|
self.usernameedit.setEnabled(True)
|
|
self.usernameedit.setText(entry.getUsername())
|
|
self.passwordedit.setText(entry.getPassword())
|
|
|
|
########################################################################
|
|
def undisplayMountEntry(self,entry):
|
|
entry.setDevice( unicode(self.devicelineedit.text()) )
|
|
entry.setMountPoint( unicode(self.mountpointlineedit.text()) )
|
|
entry.setExtraOptions(self.options)
|
|
entry.setFSFreq(self.fsfreq)
|
|
entry.setFSPassno(self.fspassno)
|
|
entry.setMountAtBoot(self.autocheckbox.isChecked())
|
|
entry.setWritable(self.writeablecheckbox.isChecked())
|
|
entry.setAllowUserMount(self.usermountcombobox.currentItem())
|
|
entry.setUID(self.uidcombobox.UID())
|
|
entry.setGID(self.gidcombobox.GID())
|
|
|
|
if self.guestradio.isChecked():
|
|
entry.setUsername(None)
|
|
entry.setPassword(None)
|
|
else:
|
|
entry.setUsername( unicode(self.usernameedit.text()) )
|
|
entry.setPassword( unicode(self.passwordedit.text()) )
|
|
|
|
########################################################################
|
|
def slotAdvancedClicked(self):
|
|
(self.options, self.fsfreq, self.fspassno)\
|
|
= self.advanceddialog.do(self.options, self.fsfreq, self.fspassno)
|
|
|
|
########################################################################
|
|
def slotGuestRadioClicked(self,state):
|
|
if self.updatinggui:
|
|
return
|
|
self.updatinggui = True
|
|
|
|
if state==TQButton.Off:
|
|
self.guestradio.setChecked(True)
|
|
self.userradio.setChecked(False)
|
|
|
|
self.passwordedit.setEnabled(False)
|
|
self.usernameedit.setEnabled(False)
|
|
|
|
self.updatinggui = False
|
|
|
|
########################################################################
|
|
def slotUserRadioClicked(self,state):
|
|
if self.updatinggui:
|
|
return
|
|
self.updatinggui = True
|
|
if state==TQButton.Off:
|
|
self.userradio.setChecked(True)
|
|
self.guestradio.setChecked(False)
|
|
|
|
self.passwordedit.setEnabled(True)
|
|
self.usernameedit.setEnabled(True)
|
|
|
|
self.updatinggui = False
|
|
|
|
############################################################################
|
|
class ROListBoxItem(TQListBoxPixmap):
|
|
"""A read-only ListBox item that also uses the 'alternate' background colour
|
|
as background.
|
|
"""
|
|
def __init__(self,listbox,pix,text):
|
|
TQListBoxPixmap.__init__(self,listbox,pix,text)
|
|
self.setSelectable(False)
|
|
def paint(self,p):
|
|
boldfont = TQFont(p.font())
|
|
boldfont.setWeight(TQFont.Bold)
|
|
p.setFont(boldfont)
|
|
p.setBackgroundColor(TDEGlobalSettings.alternateBackgroundColor())
|
|
p.eraseRect(0,0,self.listBox().width(),self.height(self.listBox()))
|
|
TQListBoxPixmap.paint(self,p)
|
|
|
|
############################################################################
|
|
class MountEntryDialog(KDialogBase):
|
|
|
|
MountTypeEditorsDisk = {
|
|
'ext2' : MountEntryDialogOptionsCommonUnix,
|
|
'ext3' : MountEntryDialogOptionsCommonUnix,
|
|
'ext4' : MountEntryDialogOptionsCommonUnix,
|
|
'reiserfs' : MountEntryDialogOptionsCommonUnix,
|
|
'reiser4' : MountEntryDialogOptionsCommonUnix,
|
|
'xfs' : MountEntryDialogOptionsCommonUnix,
|
|
'jfs' : MountEntryDialogOptionsCommonUnix,
|
|
'vfat' : MountEntryDialogOptionsVFAT,
|
|
'ntfs' : MountEntryDialogOptionsVFAT,
|
|
'hfsplus' : MountEntryDialogOptionsVFAT,
|
|
'udf' : MountEntryDialogOptions,
|
|
'iso9660' : MountEntryDialogOptions,
|
|
}
|
|
MountTypeEditorsNetwork = {
|
|
'nfs' : MountEntryDialogOptionsNfs,
|
|
'cifs' : MountEntryDialogOptionsSMB,
|
|
}
|
|
MountTypeEditorsSystem = {
|
|
'proc' : MountEntryDialogOptionsSys,
|
|
'sysfs' : MountEntryDialogOptionsSys,
|
|
'rootfs' : MountEntryDialogOptions,
|
|
'bdev' : MountEntryDialogOptions,
|
|
'sockfs' : MountEntryDialogOptions,
|
|
'tmpfs' : MountEntryDialogOptions,
|
|
'shm' : MountEntryDialogOptions,
|
|
'pipefs' : MountEntryDialogOptions,
|
|
'ramfs' : MountEntryDialogOptionsSys,
|
|
'devfs' : MountEntryDialogOptions,
|
|
'devpts' : MountEntryDialogOptionsSys,
|
|
'auto' : MountEntryDialogOptionsCommonUnix,
|
|
'usbdevfs' : MountEntryDialogOptions,
|
|
'procbususb' : MountEntryDialogOptions,
|
|
'usbfs' : MountEntryDialogOptions,
|
|
'supermount' : MountEntryDialogOptions,
|
|
'swap' : MountEntryDialogOptionsSwap
|
|
}
|
|
|
|
########################################################################
|
|
def __init__(self,parent):
|
|
KDialogBase.__init__(self,parent,None,True,"Configuration",KDialogBase.Ok|KDialogBase.Cancel,
|
|
KDialogBase.Cancel)
|
|
|
|
self.updatingGUI = True
|
|
|
|
# Maps MountEntry classes to MountEntryDialogOptions objects
|
|
self.mountTypeToOptionWidget = {}
|
|
|
|
# Maps indexes in the combobox to mounttypes
|
|
self.comboIndexToMountType = []
|
|
self.currentOptionWidget = None
|
|
|
|
self.topvbox = TQVBox(self)
|
|
self.setMainWidget(self.topvbox)
|
|
self.topvbox.setSpacing(self.spacingHint())
|
|
|
|
hb = TQHBox(self.topvbox)
|
|
hb.setSpacing(self.spacingHint())
|
|
self.topvbox.setStretchFactor(hb,0)
|
|
|
|
label = TQLabel(i18n("Type:"),hb)
|
|
hb.setStretchFactor(label,0)
|
|
self.mounttypecombo = KComboBox(hb)
|
|
|
|
# Disk types
|
|
ROListBoxItem(self.mounttypecombo.listBox(),UserIcon("hi16-hdd"),i18n("Disk Filesystems"))
|
|
self.comboIndexToMountType.append(None)
|
|
items = self.MountTypeEditorsDisk.keys()
|
|
items.sort()
|
|
for mounttype in items:
|
|
self.mounttypecombo.insertItem(MountEntry.getMountTypeLongName(mounttype))
|
|
self.comboIndexToMountType.append(mounttype)
|
|
|
|
# Network types
|
|
ROListBoxItem(self.mounttypecombo.listBox(),UserIcon("hi16-network"),i18n("Network Filesystems"))
|
|
self.comboIndexToMountType.append(None)
|
|
items = self.MountTypeEditorsNetwork.keys()
|
|
items.sort()
|
|
for mounttype in items:
|
|
self.mounttypecombo.insertItem(MountEntry.getMountTypeLongName(mounttype))
|
|
self.comboIndexToMountType.append(mounttype)
|
|
|
|
# System types
|
|
ROListBoxItem(self.mounttypecombo.listBox(),UserIcon("hi16-blockdevice"),i18n("Operating System"))
|
|
self.comboIndexToMountType.append(None)
|
|
items = self.MountTypeEditorsSystem.keys()
|
|
items.sort()
|
|
for mounttype in items:
|
|
self.mounttypecombo.insertItem(MountEntry.getMountTypeLongName(mounttype))
|
|
self.comboIndexToMountType.append(mounttype)
|
|
|
|
self.MountTypeEditors = self.MountTypeEditorsDisk.copy()
|
|
self.MountTypeEditors.update(self.MountTypeEditorsNetwork)
|
|
self.MountTypeEditors.update(self.MountTypeEditorsSystem)
|
|
|
|
#hb.setStretchFactor(self.runlevelcombo,0)
|
|
self.connect(self.mounttypecombo, SIGNAL("activated(int)"), self.slotMountTypeChanged)
|
|
|
|
widget = TQWidget(hb)
|
|
hb.setStretchFactor(widget,1)
|
|
|
|
# Create the stack of option edit widgets.
|
|
gb = TQVGroupBox(self.topvbox)
|
|
self.topvbox.setStretchFactor(gb,1)
|
|
self.optionsstack = TQWidgetStack(gb)
|
|
|
|
for mounttype in self.MountTypeEditors:
|
|
editpage = self.MountTypeEditors[mounttype](self.optionsstack)
|
|
self.mountTypeToOptionWidget[mounttype] = editpage
|
|
self.optionsstack.addWidget(editpage)
|
|
|
|
self.fsunavailablelabel = TQHBox(gb)
|
|
self.fsunavailablelabel.setSpacing(KDialog.spacingHint())
|
|
tmplabel = TQLabel(self.fsunavailablelabel)
|
|
self.fsunavailablelabel.setStretchFactor(tmplabel,0)
|
|
tmplabel.setPixmap(SmallIcon('info'))
|
|
label = TQLabel(i18n("This filesystem type is currently unavailable on the running kernel."),
|
|
self.fsunavailablelabel)
|
|
self.fsunavailablelabel.setStretchFactor(label,1)
|
|
self.fsunavailablelabel.hide()
|
|
|
|
self.updatingGUI = False
|
|
|
|
#######################################################################
|
|
def doEditMount(self,mounttable,mountentry):
|
|
self.newEntry = False
|
|
self.mounttable = mounttable
|
|
self.originalMountEntry = mountentry
|
|
self.currentMountEntry = mountentry.copy()
|
|
|
|
self.updatingGUI = True
|
|
self.selectEntry(self.currentMountEntry.getMountType())
|
|
self.updatingGUI = False
|
|
if self.exec_loop()==TQDialog.Accepted:
|
|
# All of the update stuff is in slotOk()
|
|
return True
|
|
return False
|
|
|
|
#######################################################################
|
|
def doNewMount(self,mounttable,defaultdevice):
|
|
self.newEntry = True
|
|
self.mounttable = mounttable
|
|
self.currentMountEntry = MountEntry()
|
|
if defaultdevice is not None:
|
|
self.currentMountEntry.setDevice(defaultdevice)
|
|
self.updatingGUI = True
|
|
self.currentOptionWidget = None
|
|
self.selectEntry(self.currentMountEntry.mounttype)
|
|
self.updatingGUI = False
|
|
if self.exec_loop()==TQDialog.Accepted:
|
|
self.mounttable.allentries.append(self.currentMountEntry)
|
|
self.mounttable.updateFstabOnDisk()
|
|
return self.currentMountEntry
|
|
return None
|
|
|
|
#######################################################################
|
|
def selectEntry(self,mounttype):
|
|
#if self.currentOptionWidget!=None:
|
|
# # Update the mount entry from the
|
|
# self.currentOptionWidget.undisplayMountEntry(self.currentMountEntry)
|
|
self.currentMountEntry.setMountType(mounttype)
|
|
# Update GUI
|
|
self.mounttypecombo.setCurrentItem(self.comboIndexToMountType.index(mounttype))
|
|
self.currentOptionWidget = self.mountTypeToOptionWidget[mounttype]
|
|
self.currentOptionWidget.displayMountEntry(self.currentMountEntry)
|
|
self.optionsstack.raiseWidget(self.currentOptionWidget)
|
|
if microhal.isSupportedFileSystem(mounttype):
|
|
self.fsunavailablelabel.hide()
|
|
else:
|
|
self.fsunavailablelabel.show()
|
|
|
|
#######################################################################
|
|
def slotMountTypeChanged(self,index):
|
|
if self.updatingGUI==False:
|
|
self.updatingGUI = True
|
|
self.selectEntry(self.comboIndexToMountType[index])
|
|
self.updatingGUI = False
|
|
|
|
#######################################################################
|
|
def slotOk(self):
|
|
global allowlabel, allowuuid
|
|
self.currentOptionWidget.undisplayMountEntry(self.currentMountEntry)
|
|
if allowuuid:
|
|
if self.currentOptionWidget.uuidcheckbox.isChecked():
|
|
self.currentMountEntry.setUseAsDevice("uuid")
|
|
if allowlabel:
|
|
if self.currentOptionWidget.labelcheckbox.isChecked():
|
|
self.currentMountEntry.setUseAsDevice("label")
|
|
conflictentry = None
|
|
if self.newEntry:
|
|
for entry in self.mounttable:
|
|
if entry.getMountPoint()==self.currentMountEntry.getMountPoint():
|
|
# Conflict found.
|
|
conflictentry = entry
|
|
else:
|
|
# Check if the mountpoint is already in use elsewhere in the mounttable.
|
|
if self.originalMountEntry.getMountPoint()!=self.currentMountEntry.getMountPoint():
|
|
for entry in self.mounttable:
|
|
if (entry.getMountPoint()==self.currentMountEntry.getMountPoint()
|
|
and entry is not self.originalMountEntry):
|
|
# Conflict found.
|
|
conflictentry = entry
|
|
if conflictentry is not None:
|
|
if KMessageBox.warningContinueCancel(self, \
|
|
i18n("The mountpoint '%1' is already in use by another entry?\nContinue?").arg(
|
|
self.currentMountEntry.getMountPoint()), \
|
|
i18n("Mountpoint already in use"))!=KMessageBox.Continue:
|
|
return
|
|
|
|
if self.currentMountEntry.getMountType() in MountEntryDialog.MountTypeEditorsDisk.keys():
|
|
# If device is not in /dev and it's no bind mount, ask if that's meant this way ...
|
|
options = self.currentMountEntry.getFstabOptions()
|
|
if (not self.currentMountEntry.getDevice().startswith("/dev/")
|
|
and not ("loop" in options or "bind" in options)):
|
|
ask = KMessageBox.warningYesNoCancel(self,
|
|
i18n("'%1' does not seem to be a device and the option 'bind' has not been specified in the \
|
|
\"Advanced\" page?\n Should I add the 'loop' option?").arg(self.currentMountEntry.device),
|
|
i18n("Options may be missing"))
|
|
if ask==KMessageBox.Cancel:
|
|
return
|
|
elif ask==KMessageBox.Yes:
|
|
# Add loop option
|
|
extraoptions = self.currentMountEntry.getExtraOptions().split(',')
|
|
extraoptions.append('loop')
|
|
self.currentMountEntry.setExtraOptions(','.join(extraoptions))
|
|
|
|
if (not os.path.isdir(self.currentMountEntry.getMountPoint())
|
|
and not os.path.isfile(self.currentMountEntry.getMountPoint())
|
|
and not self.currentMountEntry.mounttype == 'swap'):
|
|
ask = KMessageBox.warningYesNoCancel(self,
|
|
i18n("""The mountpoint '%1' does not exist. You will not be able to enable it until it is created.\
|
|
\nShould I create the mountpoint?""").arg(self.currentMountEntry.getMountPoint()),
|
|
i18n("Mountpoint does not exist"))
|
|
if ask==KMessageBox.Cancel:
|
|
return
|
|
elif ask==KMessageBox.Yes:
|
|
os.mkdir(self.currentMountEntry.getMountPoint())
|
|
elif os.path.isfile(self.currentMountEntry.getMountPoint()):
|
|
if KMessageBox.warningContinueCancel(self,
|
|
i18n("""The mountpoint '%1' is a file, but it has to be a directory. You will probably not \
|
|
be able to enable it.\nContinue?""").arg(self.currentMountEntry.getMountPoint()),
|
|
i18n("Invalid mountpoint"))!=KMessageBox.Continue:
|
|
return
|
|
|
|
if self.newEntry==False:
|
|
# How to Change a Mount Entry.
|
|
# 1. Disable the exisiting entry (if needed)
|
|
# 2. Update existing entry from the mount table.
|
|
# 3. Enable the updated entry (if needed)
|
|
# 4. Write new fstab file.
|
|
# 5. Enable the new entry (if needed)
|
|
|
|
# 1. Disable the exisiting entry (if needed)
|
|
enabled = self.originalMountEntry.isEnabled()
|
|
if enabled:
|
|
self.disablingold = True
|
|
self.originalMountEntry.disable(self)
|
|
self.originalMountEntry.inPlaceCopyFrom(self.currentMountEntry)
|
|
self.mounttable.updateFstabOnDisk()
|
|
if enabled and self.originalMountEntry.isFileSystemAvailable():
|
|
self.originalMountEntry.enable(self)
|
|
self.accept()
|
|
|
|
############################################################################
|
|
class MountEntryAdvancedCommonUnixDialog(KDialogBase):
|
|
########################################################################
|
|
def __init__(self,parent,name=None):
|
|
KDialogBase.__init__(self,parent,name,1,"",KDialogBase.Ok|KDialogBase.Cancel)
|
|
|
|
grid = self.makeGridMainWidget(2,TQt.Horizontal)
|
|
grid.setSpacing(self.spacingHint())
|
|
|
|
TQWidget(grid)
|
|
self.accesstimecheckbox = TQCheckBox(i18n("Update file access timestamps"),grid)
|
|
|
|
TQWidget(grid)
|
|
self.allowexecutablecheckbox = TQCheckBox(i18n("Allow Executables"),grid)
|
|
|
|
TQWidget(grid)
|
|
self.allowsuidcheckbox = TQCheckBox(i18n("Allow the SUID and SGID attributes"),grid)
|
|
|
|
TQWidget(grid)
|
|
self.usedevpointscheckbox = TQCheckBox(i18n("Allow device points"),grid)
|
|
|
|
label = TQLabel(i18n("Options:"),grid)
|
|
self.optionslineedit = KLineEdit(grid)
|
|
|
|
label = TQLabel(i18n("fs_freq:"),grid)
|
|
self.fsfreqspinbox = KIntSpinBox (0,1000,1,0,10,grid)
|
|
|
|
label = TQLabel(i18n("fs_passno:"),grid)
|
|
self.fspassnospinbox = KIntSpinBox (0,1000,1,0,10,grid)
|
|
|
|
########################################################################
|
|
def do(self,atime,allowexecutable,allowsuid,usedevpoints,options,fsfreq,fspassno):
|
|
|
|
self.accesstimecheckbox.setChecked(atime)
|
|
self.allowexecutablecheckbox.setChecked(allowexecutable)
|
|
self.allowsuidcheckbox.setChecked(allowsuid)
|
|
self.usedevpointscheckbox.setChecked(usedevpoints)
|
|
self.optionslineedit.setText(options)
|
|
self.fsfreqspinbox.setValue(fsfreq)
|
|
self.fspassnospinbox.setValue(fspassno)
|
|
self.exec_loop()
|
|
return ( self.accesstimecheckbox.isChecked(),
|
|
self.allowexecutablecheckbox.isChecked(),
|
|
self.allowsuidcheckbox.isChecked(),
|
|
self.usedevpointscheckbox.isChecked(),
|
|
unicode(self.optionslineedit.text()),
|
|
self.fsfreqspinbox.value(),
|
|
self.fspassnospinbox.value())
|
|
|
|
############################################################################
|
|
class MountEntryAdvancedPlainDialog(KDialogBase):
|
|
########################################################################
|
|
def __init__(self,parent,name=None):
|
|
KDialogBase.__init__(self,parent,name,1,"",KDialogBase.Ok|KDialogBase.Cancel)
|
|
|
|
grid = self.makeGridMainWidget(2,TQt.Horizontal)
|
|
grid.setSpacing(self.spacingHint())
|
|
|
|
label = TQLabel(i18n("Options:"),grid)
|
|
self.optionslineedit = KLineEdit(grid)
|
|
|
|
label = TQLabel(i18n("fs_freq:"),grid)
|
|
self.fsfreqspinbox = KIntSpinBox (0,1000,1,0,10,grid)
|
|
|
|
label = TQLabel(i18n("fs_passno:"),grid)
|
|
self.fspassnospinbox = KIntSpinBox (0,1000,1,0,10,grid)
|
|
|
|
########################################################################
|
|
def do(self,options,fsfreq,fspassno):
|
|
self.optionslineedit.setText(options)
|
|
self.fsfreqspinbox.setValue(fsfreq)
|
|
self.fspassnospinbox.setValue(fspassno)
|
|
self.exec_loop()
|
|
return (unicode(self.optionslineedit.text()), self.fsfreqspinbox.value(), self.fspassnospinbox.value())
|
|
|
|
############################################################################
|
|
class MountListViewItem(TDEListViewItem):
|
|
########################################################################
|
|
def __init__(self,parentitem,mountentry,haldevice=None):
|
|
self.haldevice = haldevice
|
|
self.mountentry = mountentry
|
|
if self.mountentry is None:
|
|
# There is no mount entry right now. This acts as a place holder
|
|
# for now.
|
|
TDEListViewItem.__init__(self,parentitem,self.haldevice.getName(),"","",self.haldevice.getDev(),"")
|
|
else:
|
|
if mountentry.isEnabled():
|
|
enabled = i18n("Enabled")
|
|
else:
|
|
enabled = i18n("Disabled")
|
|
if self.haldevice is not None:
|
|
name = self.haldevice.getName()
|
|
else:
|
|
name = self.mountentry.getName()
|
|
TDEListViewItem.__init__(self, parentitem, \
|
|
name,
|
|
self.mountentry.getMountPoint(), \
|
|
self.mountentry.mounttype, \
|
|
self.mountentry.getDevice(), \
|
|
enabled)
|
|
|
|
if self.mountentry.isEnabled():
|
|
self.setPixmap(4,UserIcon("greenled"))
|
|
else:
|
|
self.setPixmap(4,UserIcon("greyled"))
|
|
self.__updateIcon()
|
|
|
|
########################################################################
|
|
def hasHAL(self):
|
|
return self.haldevice is not None
|
|
|
|
########################################################################
|
|
def getHAL(self): return self.haldevice
|
|
|
|
########################################################################
|
|
def updateDisplay(self):
|
|
if self.mountentry is not None:
|
|
if self.mountentry.isEnabled():
|
|
enabled = i18n("Enabled")
|
|
self.setPixmap(4,UserIcon("greenled"))
|
|
else:
|
|
enabled = i18n("Disabled")
|
|
self.setPixmap(4,UserIcon("greyled"))
|
|
|
|
if self.haldevice is not None:
|
|
self.setText(0,self.haldevice.getName())
|
|
else:
|
|
self.setText(0,self.mountentry.getMountPoint())
|
|
|
|
self.setText(1,self.mountentry.getMountPoint())
|
|
self.setText(2,self.mountentry.mounttype)
|
|
|
|
if self.mountentry.getDevice() is not None:
|
|
self.setText(3,self.mountentry.getDevice())
|
|
else:
|
|
uuid_device = microhal.getDeviceByUUID(self.mountentry.getUUID())
|
|
label_device = microhal.getDeviceByUUID(self.mountentry.getUUID())
|
|
if label_device is not None:
|
|
self.setText(3,label_device.getDev()+" (Label)")
|
|
elif real_device is not None:
|
|
self.setText(3,real_device.getDev()+" (UUID)")
|
|
else:
|
|
self.setText(3,"UUID="+self.mountentry.getUUID())
|
|
|
|
self.setText(4,enabled)
|
|
else:
|
|
self.setText(0,self.haldevice.getName())
|
|
self.setText(1,"")
|
|
self.setText(2,"")
|
|
self.setText(3,self.haldevice.getDev())
|
|
self.setText(4,"")
|
|
self.setPixmap(4,TQPixmap())
|
|
self.__updateIcon()
|
|
|
|
########################################################################
|
|
def setMountEntry(self,entry):
|
|
self.mountentry = entry
|
|
self.updateDisplay()
|
|
|
|
########################################################################
|
|
def getMountEntry(self):
|
|
return self.mountentry
|
|
|
|
########################################################################
|
|
def getDevice(self): return self.haldevice.getDev()
|
|
|
|
########################################################################
|
|
|
|
def __updateIcon(self):
|
|
if self.haldevice is not None:
|
|
self.setPixmap(0,UserIcon(self.haldevice.iconname))
|
|
else:
|
|
self.setPixmap(0,UserIcon(self.mountentry.getIconName()))
|
|
|
|
############################################################################
|
|
class MountGroupListViewItem(TDEListViewItem):
|
|
########################################################################
|
|
def __init__(self,parentitem,haldevice):
|
|
self.haldevice = haldevice
|
|
TDEListViewItem.__init__(self,parentitem,self.haldevice.getName(),"","","","")
|
|
|
|
if self.haldevice is not None:
|
|
iconname = self.haldevice.iconname
|
|
else:
|
|
iconname = self.mountentry.getIconName()
|
|
self.setPixmap(0,UserIcon(iconname))
|
|
|
|
########################################################################
|
|
def getMountEntry(self):
|
|
return None
|
|
|
|
########################################################################
|
|
def updateDisplay(self):
|
|
pass
|
|
|
|
def hasHAL(self):
|
|
return False
|
|
|
|
############################################################################
|
|
# Try translating this code to C++. I dare ya!
|
|
if standalone:
|
|
programbase = KDialogBase
|
|
else:
|
|
programbase = TDECModule
|
|
|
|
class MountConfigApp(programbase):
|
|
########################################################################
|
|
def __init__(self,parent=None,name=None):
|
|
global standalone,isroot
|
|
TDEGlobal.locale().insertCatalogue("guidance")
|
|
|
|
if standalone:
|
|
KDialogBase.__init__(self,KJanusWidget.Plain,i18n("Disk & Filesystems"),
|
|
KDialogBase.User1|KDialogBase.Close, KDialogBase.Close)
|
|
self.setButtonText(KDialogBase.User1,i18n("About"))
|
|
topwidget = self.plainPage()
|
|
else:
|
|
TDECModule.__init__(self,parent,name)
|
|
self.setButtons(0)
|
|
self.aboutdata = MakeAboutData()
|
|
topwidget = self
|
|
|
|
# Create a configuration object.
|
|
self.config = TDEConfig("mountconfigrc")
|
|
|
|
TDEGlobal.iconLoader().addAppDir("guidance")
|
|
self.updatingGUI = False
|
|
self.mounttable = MountTable('/etc/fstab','/etc/mtab')
|
|
self.selectedentry = None
|
|
self.aboutus = TDEAboutApplication(self)
|
|
self.sizeviewdialogs = {}
|
|
toplayout = TQVBoxLayout(topwidget, 0, KDialog.spacingHint())
|
|
#topwidget.setEnabled(isroot)
|
|
|
|
hb = TQHBox(topwidget)
|
|
hb.setSpacing(KDialog.spacingHint())
|
|
#if standalone:
|
|
# hb.setMargin(KDialog.marginHint())
|
|
|
|
toplayout.addWidget(hb)
|
|
|
|
label = TQLabel(hb)
|
|
label.setPixmap(UserIcon("kcmpartitions"))
|
|
hb.setStretchFactor(label,0)
|
|
|
|
label = TQLabel(i18n("Available Disks and Filesystems:"),hb)
|
|
hb.setStretchFactor(label,1)
|
|
|
|
self.mountlist = TDEListView(topwidget,"Mount list")
|
|
toplayout.addWidget(self.mountlist)
|
|
self.mountlist.addColumn(i18n("Name"))
|
|
self.mountlist.addColumn(i18n("Mount Point"))
|
|
self.mountlist.addColumn(i18n("Type"))
|
|
self.mountlist.addColumn(i18n("Device"))
|
|
self.mountlist.addColumn(i18n("Enabled"))
|
|
self.mountlist.setAllColumnsShowFocus(True)
|
|
self.mountlist.setSelectionMode(TQListView.Single)
|
|
self.mountlist.setRootIsDecorated(True)
|
|
self.mountlist.setSorting(-1)
|
|
self.connect(self.mountlist, SIGNAL("selectionChanged(TQListViewItem *)"), self.slotListClicked)
|
|
# Doubleclick in item opens modify dialogue.
|
|
self.connect(self.mountlist, SIGNAL("doubleClicked(TQListViewItem *)"), self.slotModifyClicked)
|
|
# Rightclick: Open ContextMenu
|
|
self.connect(self.mountlist, SIGNAL("contextMenu(TDEListView*,TQListViewItem*,const TQPoint&)"),
|
|
self.slotContextMenu)
|
|
|
|
hbox = TQHBox(topwidget)
|
|
toplayout.addWidget(hbox)
|
|
hbox.setSpacing(KDialog.spacingHint())
|
|
|
|
toplayout.setStretchFactor(hbox,0)
|
|
self.newbutton = KPushButton(i18n("New..."),hbox)
|
|
hbox.setStretchFactor(self.newbutton,1)
|
|
self.connect(self.newbutton,SIGNAL("clicked()"),self.slotNewClicked)
|
|
self.newbutton.setEnabled(isroot)
|
|
|
|
self.modifybutton = KPushButton(i18n("Modify..."),hbox)
|
|
hbox.setStretchFactor(self.modifybutton,1)
|
|
self.connect(self.modifybutton,SIGNAL("clicked()"),self.slotModifyClicked)
|
|
|
|
self.deletebutton = KPushButton(i18n("Delete..."),hbox)
|
|
hbox.setStretchFactor(self.deletebutton,1)
|
|
self.connect(self.deletebutton,SIGNAL("clicked()"),self.slotDeleteClicked)
|
|
|
|
self.enablebutton = KPushButton(i18n("Enable"),hbox)
|
|
hbox.setStretchFactor(self.enablebutton,1)
|
|
self.connect(self.enablebutton,SIGNAL("clicked()"),self.slotEnableClicked)
|
|
|
|
self.disablebutton = KPushButton(i18n("Disable"),hbox)
|
|
hbox.setStretchFactor(self.disablebutton,1)
|
|
self.connect(self.disablebutton,SIGNAL("clicked()"),self.slotDisableClicked)
|
|
|
|
self.detailsbutton = KPushButton(i18n("Details..."),hbox)
|
|
hbox.setStretchFactor(self.detailsbutton,1)
|
|
self.connect(self.detailsbutton,SIGNAL("clicked()"),self.slotDetailsClicked)
|
|
|
|
self.devstolistitems = None
|
|
self.uuidstolistitems = None
|
|
self.mountentriestolistitems = None
|
|
self.__updateMountList()
|
|
self.__selectEntry(self.mounttable[0])
|
|
|
|
self.configuredialog = MountEntryDialog(None)
|
|
|
|
########################################################################
|
|
def exec_loop(self):
|
|
global programbase
|
|
self.__loadOptions()
|
|
programbase.exec_loop(self)
|
|
self.__saveOptions()
|
|
|
|
########################################################################
|
|
def slotContextMenu(self,lv,lv_item,p):
|
|
|
|
hal_device = lv_item.haldevice
|
|
if hal_device is not None and not isinstance(hal_device,MicroHAL.FakeSystemDevice):
|
|
|
|
self.cmenu = TDEPopupMenu(self,"MyActions")
|
|
if isinstance(hal_device,MicroHAL.RemovableDisk) or isinstance(lv_item,MountListViewItem):
|
|
self.cmenu.insertItem(i18n("Modify..."), self.slotModifyClicked, 0, 0)
|
|
self.cmenu.insertItem(i18n("Delete..."), self.slotDeleteClicked, 0, 1)
|
|
if not isroot:
|
|
self.cmenu.setItemEnabled(0,False)
|
|
self.cmenu.setItemEnabled(1,False)
|
|
elif isinstance(hal_device,MicroHAL.Disk) or isinstance(hal_device,MicroHAL.USBDisk):
|
|
self.cmenu.insertItem(i18n("Show details..."), self.slotDetailsClicked, 0, 0)
|
|
self.cmenu.insertItem(i18n("New..."), self.slotNewClicked, 0, 1)
|
|
if not isroot:
|
|
self.cmenu.setItemEnabled(1,False)
|
|
|
|
self.cmenu.exec_loop(p)
|
|
|
|
########################################################################
|
|
def slotUser1(self):
|
|
self.aboutus.show()
|
|
|
|
########################################################################
|
|
def slotEnableClicked(self):
|
|
if self.selectedentry!=None:
|
|
self.selectedentry.enable(self)
|
|
self.mounttable.updateStatus(self.selectedentry)
|
|
self.__updateEntry(self.selectedentry)
|
|
self.enablebutton.setEnabled(not self.selectedentry.isEnabled())
|
|
self.disablebutton.setEnabled(self.selectedentry.isEnabled())
|
|
|
|
########################################################################
|
|
def slotDisableClicked(self):
|
|
if self.selectedentry!=None:
|
|
self.__disableEntry()
|
|
|
|
########################################################################
|
|
def slotModifyClicked(self):
|
|
global isroot
|
|
if not isroot:
|
|
return
|
|
|
|
if self.selectedentry!=None:
|
|
self.configuredialog.doEditMount(self.mounttable,self.selectedentry)
|
|
|
|
lvi = self.mountentriestolistitems[self.selectedentry]
|
|
if lvi.hasHAL():
|
|
if lvi.getHAL().getDev()!=self.selectedentry.getDevice():
|
|
# The (device-)item in the listview no longer matches this mount entry.
|
|
del self.mountentriestolistitems[self.selectedentry]
|
|
lvi.setMountEntry(None)
|
|
lvi.updateDisplay()
|
|
# Reinsert this mount entry into the list view.
|
|
self.__insertMountEntryIntoListView(self.selectedentry)
|
|
|
|
elif self.selectedentry.getDevice() is not None \
|
|
and self.selectedentry.getDevice() in self.devstolistitems:
|
|
# The mount entry can now merged with any existing (HAL-)item.
|
|
# Remove the existing lose item.
|
|
self.mountlist.takeItem(lvi)
|
|
del self.mountentriestolistitems[self.selectedentry]
|
|
del self.devstolistitems[self.selectedentry.getDevice()]
|
|
del lvi
|
|
# Reinsert this mount entry into the list view.
|
|
self.__insertMountEntryIntoListView(self.selectedentry)
|
|
|
|
elif self.selectedentry.getUUID() is not None \
|
|
and self.selectedentry.getUUID() in self.uuidstolistitems:
|
|
# The mount entry can now merged with any existing (HAL-)item.
|
|
# Remove the existing lose item.
|
|
self.mountlist.takeItem(lvi)
|
|
del self.mountentriestolistitems[self.selectedentry]
|
|
del self.uuidstolistitems[self.selectedentry.getUUID()]
|
|
del lvi
|
|
# Reinsert this mount entry into the list view.
|
|
self.__insertMountEntryIntoListView(self.selectedentry)
|
|
|
|
self.__updateEntry(self.selectedentry)
|
|
self.__selectEntry(self.selectedentry)
|
|
else:
|
|
self.slotNewClicked()
|
|
|
|
########################################################################
|
|
def slotNewClicked(self):
|
|
defaultdevice = None
|
|
if self.selectedentry is None:
|
|
lvi = self.mountlist.selectedItem()
|
|
if lvi is not None and lvi.hasHAL() and (lvi.getMountEntry() is None):
|
|
defaultdevice = lvi.getDevice()
|
|
newentry = self.configuredialog.doNewMount(self.mounttable,defaultdevice)
|
|
if newentry!=None:
|
|
self.updatingGUI = True
|
|
self.__insertMountEntryIntoListView(newentry)
|
|
self.__selectEntry(newentry)
|
|
self.updatingGUI = False
|
|
|
|
########################################################################
|
|
def slotDeleteClicked(self):
|
|
if self.selectedentry!=None:
|
|
if self.selectedentry.isEnabled():
|
|
if not self.__disableEntry():
|
|
return # If we couldn't disable it, then we can't continue.
|
|
message = i18n("Are you sure you want to delete mount '%1' of type %2 at '%3'?\n " +
|
|
"(This will only remove the mount, no data will be deleted.)") \
|
|
.arg(self.selectedentry.getMountPoint()).arg(self.selectedentry.mounttype).arg(
|
|
self.selectedentry.getDevice())
|
|
if KMessageBox.warningYesNo(self,message,i18n("Delete Mount?"))==KMessageBox.Yes:
|
|
lvi = self.mountentriestolistitems[self.selectedentry]
|
|
if not lvi.hasHAL():
|
|
self.mountlist.takeItem(lvi)
|
|
del lvi
|
|
del self.mountentriestolistitems[self.selectedentry]
|
|
else:
|
|
lvi.setMountEntry(None)
|
|
self.mounttable.remove(self.selectedentry)
|
|
self.mounttable.updateFstabOnDisk()
|
|
self.__selectEntry(None)
|
|
|
|
########################################################################
|
|
def slotDetailsClicked(self):
|
|
# Popup a dialog showing disklayout and a graphical represenation of 'df'
|
|
hal_device = self.mountlist.selectedItem().haldevice
|
|
if isinstance(hal_device,MicroHAL.Disk):
|
|
blk = hal_device.getDev()
|
|
devicepath, devicename = ('/'.join(blk.split('/')[0:-1])+'/', blk.split('/')[-1])
|
|
# We keep a dict with those widgets, that saves us some time reading out all the values.
|
|
if devicename not in self.sizeviewdialogs.keys():
|
|
self.sizeviewdialogs[devicename] = sizeview.SizeView(self,devicename,devicepath)
|
|
self.sizeviewdialogs[devicename].exec_loop()
|
|
else:
|
|
self.sizeviewdialogs[devicename].exec_loop()
|
|
else:
|
|
print "Sizeview doesn't support",blk.__class__," yet."
|
|
|
|
########################################################################
|
|
def slotListClicked(self,item):
|
|
if self.updatingGUI==False:
|
|
self.__selectEntry(item.getMountEntry())
|
|
|
|
########################################################################
|
|
def __disableEntry(self):
|
|
self.selectedentry.disable(self)
|
|
self.mounttable.updateStatus(self.selectedentry)
|
|
self.__updateEntry(self.selectedentry)
|
|
self.enablebutton.setEnabled(not self.selectedentry.isEnabled() and self.selectedentry.isFileSystemAvailable())
|
|
self.disablebutton.setEnabled(self.selectedentry.isEnabled())
|
|
return not self.selectedentry.isEnabled()
|
|
|
|
########################################################################
|
|
def __updateEntry(self,selectedentry):
|
|
# Update the display.
|
|
lvi = self.mountentriestolistitems[selectedentry]
|
|
lvi.updateDisplay()
|
|
|
|
########################################################################
|
|
def __loadOptions(self):
|
|
self.config.setGroup("General")
|
|
size = self.config.readSizeEntry("Geometry")
|
|
if size.isEmpty()==False:
|
|
self.resize(size)
|
|
|
|
#######################################################################
|
|
def __saveOptions(self):
|
|
global isroot
|
|
if isroot:
|
|
return
|
|
self.config.setGroup("General")
|
|
self.config.writeEntry("Geometry", self.size())
|
|
self.config.sync()
|
|
|
|
########################################################################
|
|
def __updateMountList(self):
|
|
self.mountentriestolistitems = {}
|
|
|
|
self.mountlist.clear()
|
|
|
|
self.listgroups = {}
|
|
self.devstolistitems = {}
|
|
self.uuidstolistitems = {}
|
|
|
|
lasttopitem = None
|
|
|
|
# Find out which disks are installed and should be shown in the
|
|
# listview. For real disks we put a 'group' in the listview and
|
|
# under the group we list the partitions, whether they are
|
|
# mounted or not.
|
|
for blockdevice in microhal.getDevices():
|
|
# We are looking for block devices that represent hard disks or
|
|
# things that have partitions and are not removable
|
|
if (blockdevice.major in microhal.partitionblockdevs and not blockdevice.removable) \
|
|
or isinstance(blockdevice,MicroHAL.USBDisk):
|
|
|
|
# We have a not removable block device.
|
|
# We want to create a listitem for the device and subitems
|
|
# for each partition.
|
|
groupitem = MountGroupListViewItem(self.mountlist,blockdevice)
|
|
groupitem.setOpen(True)
|
|
lasttopitem = groupitem
|
|
lvi = None
|
|
for partition in blockdevice.getPartitions():
|
|
# Try to find a matching mount entry for this partition.
|
|
lastlvi = lvi
|
|
lvi = MountListViewItem(groupitem,None,partition)
|
|
|
|
if partition.getUUID() is not None:
|
|
self.uuidstolistitems[partition.getUUID()] = lvi
|
|
if partition.getDev() is not None:
|
|
self.devstolistitems[partition.getDev()] = lvi
|
|
|
|
if lastlvi is not None:
|
|
lvi.moveItem(lastlvi)
|
|
elif blockdevice.getMajor() in microhal.cdromsdevs or blockdevice.isRemovable():
|
|
# Removable block device, assume CDROM (even if it's a partitionblockdevice)
|
|
lvi = MountListViewItem(self.mountlist,None,blockdevice)
|
|
if blockdevice.getUUID() is not None:
|
|
self.uuidstolistitems[blockdevice.getUUID()] = lvi
|
|
if blockdevice.getDev() is not None:
|
|
self.devstolistitems[blockdevice.getDev()] = lvi
|
|
lasttopitem = lvi
|
|
|
|
|
|
systemdevice = MicroHAL.FakeSystemDevice()
|
|
systemdevice.iconname = systemdevice.getIconName()
|
|
groupitem = MountGroupListViewItem(self.mountlist,systemdevice)
|
|
|
|
if lasttopitem is not None:
|
|
groupitem.moveItem(lasttopitem)
|
|
lasttopitem = groupitem
|
|
|
|
self.listgroups["system"] = groupitem
|
|
|
|
self.mountentriestolistitems = {}
|
|
for entry in self.mounttable:
|
|
self.__insertMountEntryIntoListView(entry)
|
|
|
|
########################################################################
|
|
def __insertMountEntryIntoListView(self,mountentry):
|
|
if mountentry.getDevice() in self.devstolistitems:
|
|
lvi = self.devstolistitems[mountentry.getDevice()]
|
|
lvi.setMountEntry(mountentry)
|
|
elif mountentry.getUUID() in self.uuidstolistitems:
|
|
lvi = self.uuidstolistitems[mountentry.getUUID()]
|
|
lvi.setMountEntry(mountentry)
|
|
else:
|
|
cat = mountentry.getCategory() # Place it under a special node?
|
|
if cat not in self.listgroups:
|
|
lvi = MountListViewItem(self.mountlist,mountentry)
|
|
item = self.mountlist.firstChild()
|
|
else:
|
|
lvi = MountListViewItem(self.listgroups[cat],mountentry)
|
|
item = self.listgroups[cat].firstChild()
|
|
|
|
# Move the item to the end of this (sub-list).
|
|
while item.nextSibling() is not None:
|
|
item = item.nextSibling()
|
|
lvi.moveItem(item)
|
|
|
|
self.mountentriestolistitems[mountentry] = lvi
|
|
|
|
########################################################################
|
|
def __selectEntry(self,mountentry):
|
|
if mountentry is not None and isroot:
|
|
lvi = self.mountentriestolistitems[mountentry]
|
|
self.mountlist.setSelected(lvi,True)
|
|
self.enablebutton.setEnabled(not mountentry.isEnabled() and mountentry.isFileSystemAvailable())
|
|
self.selectedentry = mountentry
|
|
# disable unsupported stuff, such as SystemEntries that canot be disabled and modified
|
|
if not mountentry.maydisable:
|
|
disable = False
|
|
else:
|
|
disable = mountentry.isEnabled()
|
|
if mountentry.notInFstab:
|
|
delete = False
|
|
modify = False
|
|
else:
|
|
delete = True
|
|
modify = True
|
|
|
|
self.disablebutton.setEnabled(disable)
|
|
self.deletebutton.setEnabled(delete)
|
|
self.modifybutton.setEnabled(modify)
|
|
|
|
else:
|
|
self.enablebutton.setEnabled(False)
|
|
self.disablebutton.setEnabled(False)
|
|
self.deletebutton.setEnabled(False)
|
|
self.modifybutton.setEnabled(False)
|
|
self.detailsbutton.setEnabled(False)
|
|
self.selectedentry = None
|
|
selected_item = self.mountlist.selectedItem()
|
|
if selected_item is not None:
|
|
self.detailsbutton.setEnabled(isinstance(selected_item.haldevice,MicroHAL.Disk) \
|
|
and not isinstance(selected_item.haldevice,MicroHAL.RemovableDisk))
|
|
else:
|
|
self.detailsbutton.setEnabled(False)
|
|
|
|
#######################################################################
|
|
# KControl virtual void methods
|
|
def load(self):
|
|
pass
|
|
def save(self):
|
|
pass
|
|
def defaults(self):
|
|
pass
|
|
def sysdefaults(self):
|
|
pass
|
|
|
|
def aboutData(self):
|
|
# Return the TDEAboutData object which we created during initialisation.
|
|
return self.aboutdata
|
|
def buttons(self):
|
|
# Only supply a Help button. Other choices are Default and Apply.
|
|
return TDECModule.Help
|
|
|
|
############################################################################
|
|
# Factory function for KControl
|
|
def create_mountconfig(parent,name):
|
|
global kapp, microhal
|
|
microhal = MicroHAL.MicroHAL()
|
|
kapp = TDEApplication.kApplication()
|
|
return MountConfigApp(parent, name)
|
|
|
|
############################################################################
|
|
def MakeAboutData():
|
|
aboutdata = TDEAboutData("mountconfig",programname,version,"Disk & Filesystem Configuration Tool",
|
|
TDEAboutData.License_GPL, "Copyright (C) 2003-2007 Simon Edwards")
|
|
aboutdata.addAuthor("Simon Edwards","Developer","simon@simonzone.com",
|
|
"http://www.simonzone.com/software/guidance")
|
|
aboutdata.addAuthor("Sebastian Kügler","Developer","sebas@kde.org","http://vizZzion.org");
|
|
return aboutdata
|
|
|
|
if standalone:
|
|
aboutdata = MakeAboutData()
|
|
TDECmdLineArgs.init(sys.argv,aboutdata)
|
|
|
|
microhal = MicroHAL.MicroHAL()
|
|
kapp = TDEApplication()
|
|
sysvapp = MountConfigApp()
|
|
sysvapp.exec_loop()
|