From 3cc64e84f33c0ec2ff03365e112e2120cb788c88 Mon Sep 17 00:00:00 2001
From: lars
Date: Wed, 20 Sep 2006 10:40:37 +0000
Subject: [PATCH] add (possible) config partition to 'partition' plugin
---
pythonrewrite/bin/CryptoBox.py | 18 +-
pythonrewrite/bin/CryptoBoxSettings.py | 2 +-
pythonrewrite/bin/cryptobox.conf | 5 +-
.../partition/current_partition_info.cs | 3 +
pythonrewrite/plugins/partition/lang/en.hdf | 15 ++
pythonrewrite/plugins/partition/partition.py | 202 +++++++++++++++---
.../plugins/partition/root_action.py | 50 ++++-
.../plugins/partition/select_device.cs | 7 +
.../plugins/partition/set_partitions.cs | 3 +-
9 files changed, 257 insertions(+), 48 deletions(-)
diff --git a/pythonrewrite/bin/CryptoBox.py b/pythonrewrite/bin/CryptoBox.py
index 4a3e9b2..f1769a5 100755
--- a/pythonrewrite/bin/CryptoBox.py
+++ b/pythonrewrite/bin/CryptoBox.py
@@ -100,7 +100,6 @@ class CryptoBox:
self.log.info(string)
-
# RFC: why should CryptoBoxProps inherit CryptoBox? [l]
# RFC: shouldn't we move all useful functions of CryptoBoxProps to CryptoBox? [l]
class CryptoBoxProps(CryptoBox):
@@ -119,12 +118,27 @@ class CryptoBoxProps(CryptoBox):
def reReadContainerList(self):
self.containers = []
for device in CryptoBoxTools.getAvailablePartitions():
- if self.isDeviceAllowed(device):
+ if self.isDeviceAllowed(device) and not self.isConfigPartition(device):
self.containers.append(CryptoBoxContainer.CryptoBoxContainer(device, self))
## sort by container name
self.containers.sort(cmp = lambda x,y: x.getName() < y.getName() and -1 or 1)
+ def isConfigPartition(self, device):
+ import subprocess
+ proc = subprocess.Popen(
+ shell = False,
+ stdout = subprocess.PIPE,
+ args = [
+ self.prefs["Programs"]["blkid"],
+ "-c", os.path.devnull,
+ "-o", "value",
+ "-s", "LABEL",
+ device])
+ (output, error) = proc.communicate()
+ return output.strip() == self.prefs["Main"]["ConfigVolumeLabel"]
+
+
def isDeviceAllowed(self, devicename):
"check if a device is white-listed for being used as cryptobox containers"
import types
diff --git a/pythonrewrite/bin/CryptoBoxSettings.py b/pythonrewrite/bin/CryptoBoxSettings.py
index dfa266a..f16a02f 100644
--- a/pythonrewrite/bin/CryptoBoxSettings.py
+++ b/pythonrewrite/bin/CryptoBoxSettings.py
@@ -164,6 +164,7 @@ class CryptoBoxSettings:
AllowedDevices = list(min=1)
DefaultVolumePrefix = string(min=1)
DefaultCipher = string(default="aes-cbc-essiv:sha256")
+ConfigVolumeLabel = string(min=1,default="cbox_config")
[Locations]
MountParentDir = directoryExists(default="/var/cache/cryptobox/mnt")
@@ -186,7 +187,6 @@ DocLanguage = string(min=1, default="en")
[Programs]
cryptsetup = fileExecutable(default="/sbin/cryptsetup")
mkfs-data = fileExecutable(default="/sbin/mkfs.ext3")
-mkfs-config = fileExecutable(default="/sbin/mkfs.ext2")
blkid = fileExecutable(default="/sbin/blkid")
mount = fileExecutable(default="/bin/mount")
umount = fileExecutable(default="/bin/umount")
diff --git a/pythonrewrite/bin/cryptobox.conf b/pythonrewrite/bin/cryptobox.conf
index c609f0d..7797d50 100644
--- a/pythonrewrite/bin/cryptobox.conf
+++ b/pythonrewrite/bin/cryptobox.conf
@@ -4,12 +4,16 @@
# beware: .e.g "/dev/hd" grants access to _all_ harddisks
AllowedDevices = /dev/loop
+
# the default name prefix of not unnamed containers
DefaultVolumePrefix = "Data "
# which cipher should cryptsetup-luks use?
DefaultCipher = aes-cbc-essiv:sha256
+# label of the configuration partition (you should never change this)
+ConfigVolumeLabel = cbox_config
+
[Locations]
# where should we mount volumes?
@@ -70,7 +74,6 @@ DocLanguage = de
[Programs]
cryptsetup = /sbin/cryptsetup
mkfs-data = /sbin/mkfs.ext3
-mkfs-config = /sbin/mkfs.ext2
blkid = /sbin/blkid
mount = /bin/mount
umount = /bin/umount
diff --git a/pythonrewrite/plugins/partition/current_partition_info.cs b/pythonrewrite/plugins/partition/current_partition_info.cs
index e896e23..eaeb349 100644
--- a/pythonrewrite/plugins/partition/current_partition_info.cs
+++ b/pythonrewrite/plugins/partition/current_partition_info.cs
@@ -5,4 +5,7 @@
+
+
+
diff --git a/pythonrewrite/plugins/partition/lang/en.hdf b/pythonrewrite/plugins/partition/lang/en.hdf
index fdd0a27..f3dca8c 100644
--- a/pythonrewrite/plugins/partition/lang/en.hdf
+++ b/pythonrewrite/plugins/partition/lang/en.hdf
@@ -45,8 +45,23 @@ WarningMessage {
Text = The partitioning of the device failed for some reason - sorry!
}
+ FormattingFailed {
+ Title = Formatting failed
+ Text = The formatting of the filesystems of the device failed - sorry!
+ }
+
DiskIsBusy {
Title = This disk is busy
Text = Please deactivate all containers of this disk before partitioning.
}
+
+ PartitionTooBig {
+ Title = Invalid size
+ Text = The container size you entered exceeded the available size of the disk.
+ }
+
+ PartitionTooSmall {
+ Title = Invalid size
+ Text = The minimum size of a container is 10 megabytes.
+ }
}
diff --git a/pythonrewrite/plugins/partition/partition.py b/pythonrewrite/plugins/partition/partition.py
index dbdf517..2dd3011 100644
--- a/pythonrewrite/plugins/partition/partition.py
+++ b/pythonrewrite/plugins/partition/partition.py
@@ -1,16 +1,20 @@
-import re
import subprocess
-import imp
import os
import logging
import CryptoBoxTools
PartTypes = {
- "linux" : "L",
- "windows" : "0xC"}
+ "windows" : ["0xC", "vfat"],
+ "linux" : ["L", "ext3"]}
+
+ConfigPartition = {
+ "size" : 5, # size of configuration partition (if necessary) in MB
+ "type" : "L",
+ "fs" : "ext2"}
logger = logging.getLogger("CryptoBox")
+
def doAction(hdf, cbox, **args):
try:
step = args["step"]
@@ -32,7 +36,6 @@ def getStatus(cbox):
def __isDeviceValid(device, cbox):
- ## TODO: also check for "is device busy" add output a warning
if not cbox.isDeviceAllowed(device):
return False
if not device in CryptoBoxTools.getParentBlockDevices():
@@ -42,6 +45,8 @@ def __isDeviceValid(device, cbox):
def __isDeviceBusy(device, cbox):
"""check if the device (or one of its partitions) is mounted"""
+ # TODO: the config partition is ignored, as it is not part of the container list - that is not good
+ import re
for c in cbox.getContainerList():
if re.match(device + "\d*$", c.getDevice()):
if c.isMounted(): return True
@@ -57,6 +62,8 @@ def __actionSelectDevice(hdf, cbox, args):
hdf["Data.Plugins.partition.BlockDevices.%d" % counter] = a
cbox.log.debug("found a suitable block device: %s" % a)
counter += 1
+ if __withConfigPartition(args):
+ hdf["Data.Plugins.partition.CreateConfigPartition"] = "1"
## there is no disk available
if not block_devices:
hdf["Data.Warning"] = "Plugins.partition.NoDisksAvailable"
@@ -72,11 +79,11 @@ def __actionAddPartition(hdf, cbox, args):
if __isDeviceBusy(device, cbox):
hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy"
return __actionSelectDevice(hdf, cbox, args)
- size = __getDeviceSize(device)
+ size = __getAvailableDeviceSize(device, __withConfigPartition(args))
hdf["Data.Plugins.partition.Device"] = device
hdf["Data.Plugins.partition.Device.Size"] = size
- parts = __getPartitionsFromArgs(args, size)
- __setPartitionData(hdf, parts, size)
+ parts = __getPartitionsFromArgs(hdf, args, size)
+ __setPartitionData(hdf, parts, size, __withConfigPartition(args))
return "set_partitions"
@@ -90,16 +97,16 @@ def __actionDelPartition(hdf, cbox, args):
if __isDeviceBusy(device, cbox):
hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy"
return __actionSelectDevice(hdf, cbox, args)
- size = __getDeviceSize(device)
+ size = __getAvailableDeviceSize(device, __withConfigPartition(args))
hdf["Data.Plugins.partition.Device"] = device
hdf["Data.Plugins.partition.Device.Size"] = size
- parts = __getPartitionsFromArgs(args, size)
+ parts = __getPartitionsFromArgs(hdf, args, size)
## valid partition number to be deleted?
if part_num < len(parts):
del parts[part_num]
else:
return __actionSelectDevice(hdf, cbox, args)
- __setPartitionData(hdf, parts, size)
+ __setPartitionData(hdf, parts, size, __withConfigPartition(args))
return "set_partitions"
@@ -112,21 +119,24 @@ def __actionFinish(hdf, cbox, args):
if __isDeviceBusy(device, cbox):
hdf["Data.Warning"] = "Plugins.partition.DiskIsBusy"
return __actionSelectDevice(hdf, cbox, args)
- size = __getDeviceSize(device)
- parts = __getPartitionsFromArgs(args, size)
+ size = __getAvailableDeviceSize(device, __withConfigPartition(args))
+ parts = __getPartitionsFromArgs(hdf, args, size)
if parts:
- if not __runFDisk(cbox, device, parts):
+ if not __runFDisk(cbox, device, parts, __withConfigPartition(args)):
hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
return __actionAddPartition(hdf, cbox, args)
else:
- hdf["Data.Success"] = "Plugins.partition.Partitioned"
+ if __formatPartitions(cbox, device, parts, __withConfigPartition(args)):
+ hdf["Data.Success"] = "Plugins.partition.Partitioned"
+ else:
+ hdf["Data.Warning"] = "Plugins.partition.FormattingFailed"
cbox.reReadContainerList()
return "form_system"
else:
return __actionSelectDevice(hdf, cbox, args)
-def __setPartitionData(hdf, parts, size):
+def __setPartitionData(hdf, parts, size, withConfigPartition):
availSize = size
i = 0
for part in parts:
@@ -136,11 +146,13 @@ def __setPartitionData(hdf, parts, size):
availSize -= part["size"]
i += 1
hdf["Data.Plugins.partition.availSize"] = availSize
+ if withConfigPartition:
+ hdf["Data.Plugins.partition.CreateConfigPartition"] = "1"
for t in PartTypes.keys():
hdf["Data.Plugins.partition.Types.%s" % t] = t
-def __getPartitionsFromArgs(args, maxSize):
+def __getPartitionsFromArgs(hdf, args, maxSize):
parts = []
done = False
availSize = maxSize
@@ -150,8 +162,12 @@ def __getPartitionsFromArgs(args, maxSize):
try:
size = int(args["part%d_size" % i])
partType = args["part%d_type" % i]
- if int(size) > availSize: continue
- if int(size) <= 0: continue
+ if int(size) > availSize:
+ hdf["Data.Warning"] = "Plugins.partition.PartitionTooBig"
+ continue
+ if int(size) < 10:
+ hdf["Data.Warning"] = "Plugins.partition.PartitionTooSmall"
+ continue
if not partType in PartTypes.keys(): continue
parts.append({"size":size, "type":partType})
availSize -= size
@@ -162,7 +178,9 @@ def __getPartitionsFromArgs(args, maxSize):
return parts
-def __getDeviceSize(device):
+def __getAvailableDeviceSize(device, withConfigPartition):
+ """calculate the available size (MB) of the device
+ also consider a (possible) configuration partition"""
rdev = os.stat(device).st_rdev
minor = os.minor(rdev)
major = os.major(rdev)
@@ -171,16 +189,34 @@ def __getDeviceSize(device):
elements = f.split()
if len(elements) != 4: continue
if (int(elements[0]) == major) and (int(elements[1]) == minor):
- return int(elements[2])/1024
+ deviceSize = int(elements[2])/1024
+ if withConfigPartition: deviceSize -= ConfigPartition["size"]
+ return deviceSize
except ValueError:
pass
return 0
-def __runFDisk(cbox, device, parts):
+def __withConfigPartition(args):
+ try:
+ if args["create_config_partition"]:
+ createConfig = True
+ else:
+ createConfig = False
+ except KeyError:
+ createConfig = False
+ return createConfig
+
+
+def __runFDisk(cbox, device, parts, withConfigPartition):
+ ## check if the device is completely filled (to avoid some empty last blocks)
+ avail_size = __getAvailableDeviceSize(device, withConfigPartition)
+ for d in parts: avail_size -= d["size"]
+ isFilled = avail_size == 0
proc = subprocess.Popen(
shell = False,
stdin = subprocess.PIPE,
+ stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
cbox.prefs["Programs"]["super"],
@@ -189,23 +225,123 @@ def __runFDisk(cbox, device, parts):
os.path.join(os.path.dirname(__file__), "root_action.py"),
"partition",
device])
- import logging
- logger = logging.getLogger("CryptoBox")
- for line in __getSFDiskLayout(parts): proc.stdin.write(line + "\n")
+ for line in __getSFDiskLayout(parts, withConfigPartition, isFilled):
+ proc.stdin.write(line + "\n")
(output, error) = proc.communicate()
- if error: logger.debug("partitioning failed: %s" % error)
+ if proc.returncode != 0: logger.debug("partitioning failed: %s" % error)
return proc.returncode == 0
-def __getSFDiskLayout(paramParts):
+def __getSFDiskLayout(paramParts, withConfigPartition, isFilled):
parts = paramParts[:]
- ## first a primary partition
- yield ",%d,%s,*" % (parts[0]["size"], PartTypes[parts[0]["type"]])
+ ## first a (possible) configuration partition - so it will be reusable
+ if withConfigPartition:
+ ## fill the main table (including a config partition)
+ yield ",%d,%s" % (ConfigPartition["size"], ConfigPartition["type"])
+ ## one primary partition
+ yield ",%d,%s,*" % (parts[0]["size"], PartTypes[parts[0]["type"]][0])
del parts[0]
+ ## no extended partition, if there is only one disk
if not parts: return
- yield ",,E" # extended container for the rest
- yield ";" # empty partition in main table
- yield ";" # another empty partition in main table
+ ## an extended container for the rest
+ yield ",,E"
+ ## an empty partition in main table
+ yield ";"
+ ## maybe another empty partition if there is no config partition
+ if not withConfigPartition: yield ";"
while parts:
- yield ",%d,%s" % (parts[0]["size"], PartTypes[parts[0]["type"]])
+ if isFilled and (len(parts) == 1):
+ yield ",,%s" % (PartTypes[parts[0]["type"]][0],)
+ else:
+ yield ",%d,%s" % (parts[0]["size"], PartTypes[parts[0]["type"]][0])
del parts[0]
+
+
+def __formatPartitions(cbox, device, paramParts, withConfigPartition):
+ success = True
+ parts = paramParts[:]
+ part_num = 1
+ ## maybe a config partition?
+ if withConfigPartition:
+ dev_name = device + str(part_num)
+ logger.info("formatting config partition (%s)" % dev_name)
+ if __formatOnePartition(cbox, dev_name, ConfigPartition["fs"]):
+ __setLabelOfPartition(cbox, dev_name, cbox.prefs["Main"]["ConfigVolumeLabel"])
+ else:
+ success = False
+ part_num += 1
+ ## the first data partition
+ dev_name = device + str(part_num)
+ partType = PartTypes[parts[0]["type"]][1]
+ logger.info("formatting partition (%s) as '%s'" % (dev_name, partType))
+ if not __formatOnePartition(cbox, dev_name, partType):
+ success = False
+ del parts[0]
+ ## other data partitions
+ part_num = 5
+ while parts:
+ dev_name = device + str(part_num)
+ partType = PartTypes[parts[0]["type"]][1]
+ logger.info("formatting partition (%s) as '%s'" % (dev_name, partType))
+ if not __formatOnePartition(cbox, dev_name, partType):
+ success = False
+ part_num += 1
+ del parts[0]
+ return success
+
+
+def __formatOnePartition(cbox, dev_name, type):
+ import time, sys
+ child_pid = os.fork()
+ ## we run formatting as a parallel thread
+ ## TODO: the parent thread still waits for the last child - that is not good for big harddisks
+ if child_pid == 0:
+ ## we are the child process
+ proc = subprocess.Popen(
+ shell = False,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.PIPE,
+ args = [
+ cbox.prefs["Programs"]["super"],
+ cbox.prefs["Programs"]["CryptoBoxRootActions"],
+ "plugin",
+ os.path.join(os.path.dirname(__file__), "root_action.py"),
+ "format",
+ dev_name,
+ type])
+ (output, error) = proc.communicate()
+ if proc.returncode != 0:
+ logger.warn("failed to create filesystem on %s: %s" % (dev_name, error))
+ sys.exit(1)
+ else:
+ sys.exit(0)
+ else:
+ time.sleep(1)
+ (pid, exit_state) = os.waitpid(child_pid, os.WNOHANG)
+ if ((pid == 0) and (exit_state == 0)) \
+ or ((pid == child_pid) and (exit_state == 0)):
+ return True
+ else:
+ return False
+
+
+def __setLabelOfPartition(cbox, dev_name, label):
+ proc = subprocess.Popen(
+ shell = False,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.PIPE,
+ args = [
+ cbox.prefs["Programs"]["super"],
+ cbox.prefs["Programs"]["CryptoBoxRootActions"],
+ "plugin",
+ os.path.join(os.path.dirname(__file__), "root_action.py"),
+ "label",
+ dev_name,
+ label])
+ (output, error) = proc.communicate()
+ if proc.returncode == 0:
+ return True
+ else:
+ logger.warn("failed to create filesystem on %s: %s" % (device + str(part_num), error))
+ return False
+
diff --git a/pythonrewrite/plugins/partition/root_action.py b/pythonrewrite/plugins/partition/root_action.py
index 96082cf..5601f43 100755
--- a/pythonrewrite/plugins/partition/root_action.py
+++ b/pythonrewrite/plugins/partition/root_action.py
@@ -4,6 +4,8 @@
PLUGIN_TYPE = "cryptobox"
SFDISK_BIN = "/sbin/sfdisk"
+MKFS_BIN = "/sbin/mkfs"
+LABEL_BIN = "/sbin/e2label"
import subprocess
import re
@@ -23,27 +25,55 @@ def __partitionDevice(device):
return proc.returncode == 0
+def __formatPartition(device, type):
+ proc = subprocess.Popen(
+ shell = False,
+ args = [
+ MKFS_BIN,
+ "-t", type,
+ device])
+ proc.communicate()
+ return proc.returncode == 0
+
+
+def __labelPartition(device, label):
+ proc = subprocess.Popen(
+ shell = False,
+ args = [
+ LABEL_BIN,
+ device,
+ label])
+ proc.communicate()
+ return proc.returncode == 0
+
+
if __name__ == "__main__":
args = sys.argv[1:]
self_bin =sys.argv[0]
- if len(args) > 2:
- sys.stderr.write("%s: too many arguments (%s)\n" % (self_bin, args))
- sys.exit(1)
-
if len(args) == 0:
sys.stderr.write("%s: no argument supplied\n" % self_bin)
sys.exit(1)
- if args[0] == "partition":
- if len(args) < 2:
- sys.stderr.write("%s: not enough arguments (%s)\n" % (self_bin, args))
+ try:
+ if args[0] == "partition":
+ if len(args) != 2: raise "InvalidArgNum"
+ result = __partitionDevice(args[1])
+ elif args[0] == "format":
+ if len(args) != 3: raise "InvalidArgNum"
+ result = __formatPartition(args[1], args[2])
+ elif args[0] == "label":
+ if len(args) != 3: raise "InvalidArgNum"
+ result = __labelPartition(args[1], args[2])
+ else:
+ sys.stderr.write("%s: invalid action (%s)\n" % (self_bin, args[0]))
sys.exit(1)
- if __partitionDevice(args[1]):
+ if result:
sys.exit(0)
else:
sys.exit(1)
- else:
+ except "InvalidArgNum":
+ sys.stderr.write("%s: invalid number of arguments (%s)\n" % (self_bin, args))
sys.exit(1)
-
+
diff --git a/pythonrewrite/plugins/partition/select_device.cs b/pythonrewrite/plugins/partition/select_device.cs
index 8da649a..adb39c0 100644
--- a/pythonrewrite/plugins/partition/select_device.cs
+++ b/pythonrewrite/plugins/partition/select_device.cs
@@ -13,6 +13,13 @@
+
+
+
diff --git a/pythonrewrite/plugins/partition/set_partitions.cs b/pythonrewrite/plugins/partition/set_partitions.cs
index 2774d76..9491718 100644
--- a/pythonrewrite/plugins/partition/set_partitions.cs
+++ b/pythonrewrite/plugins/partition/set_partitions.cs
@@ -36,7 +36,8 @@
|
|
- |
+ |
|