packages feed

haskus-system-build-0.7.0.0: src/apps/Haskus/Apps/System/Build/Disk.hs

module Haskus.Apps.System.Build.Disk
   ( withDisk
   , makeDisk
   , makeDevice
   )
where

import Haskus.Apps.System.Build.Config
import Haskus.Apps.System.Build.Utils
import Haskus.Apps.System.Build.Ramdisk
import Haskus.Apps.System.Build.Linux
import Haskus.Apps.System.Build.Syslinux

import System.IO.Temp
import System.FilePath
import System.Directory
import qualified Data.Text as Text
import qualified Data.Text.IO as Text
import Control.Exception (finally)


-- | Create a temp directory containing the system and call the callback
withDisk :: SystemConfig -> (FilePath -> IO a) -> IO a
withDisk config callback = do

   withSystemTempDirectory "haskus-system-build" $ \tmpfp -> do
      -- create the disk
      makeDisk config tmpfp

      -- call the callback
      callback tmpfp

-- | Mount a device and install a system in it
makeDevice :: SystemConfig -> FilePath -> IO ()
makeDevice config dev = do
   -- TODO: allow the selection of another boot partition
   -- TODO: ensure that the partition is bootable
   -- TODO: check filesystem 
   let dev' = dev ++ "1"
   showStep $ "Installing in partition " ++ dev' ++"..."
   withDisk config $ \disk -> do
      withSystemTempDirectory "haskus-system-build" $ \tmpfp -> do
         shellWaitErr ("sudo mount "++dev'++" "++tmpfp++" -o rw")
            $ failWith "Unable to mount device"
         (do
            shellWaitErr ("sudo cp -r " ++ disk ++"/* "++tmpfp)
               (failWith "Cannot copy files on the mounted device")
            syslinuxInstall (syslinuxConfig config) dev tmpfp
            ) `finally`
               shellWaitErr ("sudo umount "++tmpfp)
                  (failWith "Unable to umount device")
      


-- | Create a disk in the given folder
makeDisk :: SystemConfig -> FilePath -> IO ()
makeDisk config tmpfp = do
   showStep "Creating system disk..."

   -- create directories
   let syslinuxfp = tmpfp </> "boot" </> "syslinux"
   createDirectoryIfMissing True syslinuxfp

   -- copy Syslinux
   syslinuxPath <- syslinuxMain (syslinuxConfig config)
   -- copy *.c32 files
   copyDirectory (syslinuxPath </> "bios") syslinuxfp True
      (return . (== ".c32") . takeExtension)
   -- copy isolinux.bin
   copyFile (syslinuxPath </> "bios" </> "core" </> "isolinux.bin")
            (syslinuxfp </> "isolinux.bin")

   -- copy linux
   srcLinuxFile <- linuxKernelFile (linuxConfig config)
   let
      kernelPath   = "boot" </> takeFileName srcLinuxFile
      linuxFile    = tmpfp </> kernelPath
   copyFile srcLinuxFile linuxFile

   -- copy the ramdisk
   srcRamdiskFile <- ramdiskGetPath (ramdiskConfig config)
   let
      ramdiskPath    = "boot" </> takeFileName srcRamdiskFile
      ramdiskFile    = tmpfp </> ramdiskPath
   copyFile srcRamdiskFile ramdiskFile

   -- configure Syslinux
   let 
      cfg     = syslinuxConfigFile config (Text.pack kernelPath)
                                          (Text.pack ramdiskPath)
      cfgPath = syslinuxfp </> "syslinux.cfg"
   Text.writeFile cfgPath cfg