summaryrefslogtreecommitdiff
path: root/Propellor/Property/Docker/Shim.hs
blob: 402f1c122638c784720f861505ea91ad29483c17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
-- | Support for running propellor, as built outside a docker container,
-- inside the container.
--
-- Note: This is currently Debian specific, due to glibcLibs.

module Propellor.Property.Docker.Shim (setup, file) where

import Propellor
import Utility.LinuxMkLibs
import Utility.SafeCommand
import Utility.Path
import Utility.FileMode

import Data.List
import System.Posix.Files

-- | Sets up a shimmed version of the program, in a directory, and
-- returns its path.
setup :: FilePath -> FilePath -> IO FilePath
setup propellorbin dest = do
	createDirectoryIfMissing True dest

	libs <- parseLdd <$> readProcess "ldd" [propellorbin]
	glibclibs <- glibcLibs
	let libs' = nub $ libs ++ glibclibs
	libdirs <- map (dest ++) . nub . catMaybes
		<$> mapM (installLib installFile dest) libs'
	
	let linker = (dest ++) $ 
		fromMaybe (error "cannot find ld-linux linker") $
			headMaybe $ filter ("ld-linux" `isInfixOf`) libs'
	let linkerparams = ["--library-path", intercalate ":" libdirs ]
	let shim = file propellorbin dest
	writeFile shim $ unlines
		[ "#!/bin/sh"
		, "exec " ++ unwords (map shellEscape $ linker : linkerparams) ++ 
			" " ++ shellEscape propellorbin ++ " \"$@\""
		]
	modifyFileMode shim (addModes executeModes)
	return shim

file :: FilePath -> FilePath -> FilePath
file propellorbin dest = dest </> propellorbin

installFile :: FilePath -> FilePath -> IO ()
installFile top f = do
	createDirectoryIfMissing True destdir
	nukeFile dest
	createLink f dest `catchIO` (const copy)
  where
	copy = void $ boolSystem "cp" [Param "-a", Param f, Param dest]
	destdir = inTop top $ parentDir f
	dest = inTop top f