module Propellor.Property.Parted.Types where import qualified Propellor.Property.Partition as Partition import Utility.DataUnits import Data.Char import qualified Data.Semigroup as Sem import Data.Monoid import Prelude class PartedVal a where pval :: a -> String -- | Types of partition tables supported by parted. data TableType = MSDOS | GPT | AIX | AMIGA | BSD | DVH | LOOP | MAC | PC98 | SUN deriving (Show) instance PartedVal TableType where pval = map toLower . show -- | A disk's partition table. data PartTable = PartTable TableType Alignment [Partition] deriving (Show) instance Sem.Semigroup PartTable where -- | uses the TableType of the second parameter -- and the larger alignment, PartTable _l1 a1 ps1 <> PartTable l2 a2 ps2 = PartTable l2 (max a1 a2) (ps1 ++ ps2) instance Monoid PartTable where -- | default TableType is MSDOS, with a `safeAlignment`. mempty = PartTable MSDOS safeAlignment [] mappend = (Sem.<>) -- | A partition on the disk. data Partition = Partition { partType :: PartType , partSize :: PartSize , partFs :: Maybe Partition.Fs , partMkFsOpts :: Partition.MkfsOpts , partFlags :: [(PartFlag, Bool)] -- ^ flags can be set or unset (parted may set some flags by default) , partName :: Maybe String -- ^ optional name for partition (only works for GPT, PC98, MAC) } deriving (Show) -- | Makes a Partition with defaults for non-important values. mkPartition :: Maybe Partition.Fs -> PartSize -> Partition mkPartition fs sz = Partition { partType = Primary , partSize = sz , partFs = fs , partMkFsOpts = [] , partFlags = [] , partName = Nothing } -- | Type of a partition. data PartType = Primary | Logical | Extended deriving (Show) instance PartedVal PartType where pval Primary = "primary" pval Logical = "logical" pval Extended = "extended" -- | Size of a partition. data PartSize -- Since disk sizes are typically given in MB, not MiB, this -- uses SI MegaBytes (powers of 10). = MegaBytes Integer -- For more control, the partition size can be given in bytes. -- Note that this will prevent any automatic alignment from -- being done. | Bytes Integer deriving (Show) -- | Rounds up to the nearest MegaByte. toPartSize :: ByteSize -> PartSize toPartSize = toPartSize' ceiling toPartSize' :: (Double -> Integer) -> ByteSize -> PartSize toPartSize' rounder b = MegaBytes $ rounder (fromInteger b / 1000000 :: Double) fromPartSize :: PartSize -> ByteSize fromPartSize (MegaBytes b) = b * 1000000 fromPartSize (Bytes n) = n instance Sem.Semigroup PartSize where MegaBytes a <> MegaBytes b = MegaBytes (a + b) Bytes a <> b = Bytes (a + fromPartSize b) a <> Bytes b = Bytes (b + fromPartSize a) instance Monoid PartSize where mempty = MegaBytes 0 mappend = (Sem.<>) reducePartSize :: PartSize -> PartSize -> PartSize reducePartSize (MegaBytes a) (MegaBytes b) = MegaBytes (a - b) reducePartSize (Bytes a) b = Bytes (a - fromPartSize b) reducePartSize a (Bytes b) = Bytes (fromPartSize a - b) -- | Partitions need to be aligned for optimal efficiency. -- The alignment is a number of bytes. newtype Alignment = Alignment ByteSize deriving (Show, Eq, Ord) -- | 4MiB alignment is optimal for inexpensive flash drives and -- is a good safe default for all drives. safeAlignment :: Alignment safeAlignment = Alignment (4*1024*1024) fromAlignment :: Alignment -> ByteSize fromAlignment (Alignment n) = n -- | Flags that can be set on a partition. data PartFlag = BootFlag | RootFlag | SwapFlag | HiddenFlag | RaidFlag | LvmFlag | LbaFlag | LegacyBootFlag | IrstFlag | EspFlag | PaloFlag | BiosGrubFlag deriving (Show) instance PartedVal PartFlag where pval BootFlag = "boot" pval RootFlag = "root" pval SwapFlag = "swap" pval HiddenFlag = "hidden" pval RaidFlag = "raid" pval LvmFlag = "lvm" pval LbaFlag = "lba" pval LegacyBootFlag = "legacy_boot" pval IrstFlag = "irst" pval EspFlag = "esp" pval PaloFlag = "palo" pval BiosGrubFlag = "bios_grub" instance PartedVal Bool where pval True = "on" pval False = "off" -- This is used for creating partitions, not formatting partitions, -- so it's ok to use eg, fat32 for both FAT and VFAT. instance PartedVal Partition.Fs where pval Partition.EXT2 = "ext2" pval Partition.EXT3 = "ext3" pval Partition.EXT4 = "ext4" pval Partition.BTRFS = "btrfs" pval Partition.REISERFS = "reiserfs" pval Partition.XFS = "xfs" pval Partition.FAT = "fat32" pval Partition.VFAT = "fat32" pval Partition.NTFS = "ntfs" pval Partition.LinuxSwap = "linux-swap"