{- Linux library copier and binary shimmer - - Copyright 2013 Joey Hess - - License: BSD-2-clause -} module Utility.LinuxMkLibs where import System.IO import System.Directory (doesFileExist) import Data.Maybe import System.FilePath import Data.List.Utils import System.Posix.Files import Data.Char import Control.Monad.IfElse import Control.Applicative import System.Process import Prelude {- Installs a library. If the library is a symlink to another file, - install the file it links to, and update the symlink to be relative. -} installLib :: (FilePath -> FilePath -> IO ()) -> FilePath -> FilePath -> IO (Maybe FilePath) installLib installfile top lib = go =<< doesFileExist lib where go False = return Nothing go True = do installfile top lib checksymlink lib return $ Just $ takeDirectory lib checksymlink f = whenM (isSymbolicLink <$> getSymbolicLinkStatus (inTop top f)) $ do l <- readSymbolicLink (inTop top f) let absl = takeDirectory f l --target <- relPathDirToFile (takeDirectory f) absl installfile top absl --removeLink (top ++ f) --createSymbolicLink target (inTop top f) checksymlink absl -- Note that f is not relative, so cannot use inTop :: FilePath -> FilePath -> FilePath inTop top f = top ++ f {- Parse ldd output, getting all the libraries that the input files - link to. Note that some of the libraries may not exist - (eg, linux-vdso.so) -} parseLdd :: String -> [FilePath] parseLdd = concatMap (getlib . dropWhile isSpace) . lines where getlib = concatMap (take 1) . map words . take 1 . reverse . split " => " {- Get all glibc libs and other support files, including gconv files - - XXX Debian specific. -} glibcLibs :: IO [FilePath] glibcLibs = lines <$> readProcess "sh" ["-c", "dpkg -L libc6:$(dpkg --print-architecture) libgcc1:$(dpkg --print-architecture) | egrep '\\.so|gconv'"] mempty