git-annex-10.20261113: Annex/Magic.hs
{- Interface to libmagic
-
- Copyright 2019-2026 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE CPP #-}
module Annex.Magic (
Magic,
MimeType,
MimeEncoding,
initMagicMime,
getMagicMime,
getMagicMimeType,
getMagicMimeEncoding,
parseMagicMime,
magicFileLocation,
) where
import Common
import Types.Mime
import Control.Monad.IO.Class
import qualified Data.ByteString as B
import Data.Char
import Utility.Env
import Annex.Path
#ifdef WITH_MAGICMIME
import Magic
import qualified Data.List.NonEmpty as NE
import qualified System.OsString.Internal as OS
#else
type Magic = ()
#endif
magicFileLocation :: IO (Maybe OsPath)
magicFileLocation =
gitAnnexInstallDir >>= \case
Nothing -> do
#ifndef mingw32_HOST_OS
pure Nothing
#else
-- On windows, the magic file is
-- in ../share/misc/ relative
-- to the program.
pd <- takeDirectory <$> programPath
use $
pd
</> literalOsPath ".."
</> literalOsPath "share"
</> literalOsPath "misc"
</> literalOsPath "magic.mgc"
#endif
Just d -> use $
d
</> literalOsPath "magic"
</> literalOsPath "magic.mgc"
where
use p = Just . maybe p toOsPath <$> getEnv "MAGIC"
initMagicMime :: IO (Maybe Magic)
#ifdef WITH_MAGICMIME
initMagicMime = catchMaybeIO $ do
m <- magicOpen [MagicMime]
magicFileLocation >>= \case
Nothing -> magicLoadDefault m
Just d -> do
p <- OS.encodeFS $ fromOsPath d
magicLoad m $ NE.singleton p
return m
#else
initMagicMime = return Nothing
#endif
getMagicMime :: Magic -> OsPath -> IO (Maybe (MimeType, MimeEncoding))
#ifdef WITH_MAGICMIME
getMagicMime m f = Just . parseMagicMime
<$> (magicFile m =<< OS.encodeFS (fromOsPath f))
#else
getMagicMime _ _ = return Nothing
#endif
parseMagicMime :: B.ByteString -> (MimeType, MimeEncoding)
parseMagicMime b = (decodeBS mimetype, decodeBS mimeencoding)
where
(mimetype, rest) = B.break (== semicolon) b
mimeencoding = fromMaybe mempty (B.stripPrefix "; charset=" rest)
semicolon = fromIntegral (ord ';')
getMagicMimeType :: MonadIO m => Magic -> OsPath -> m (Maybe MimeType)
getMagicMimeType m f = liftIO $ fmap fst <$> getMagicMime m f
getMagicMimeEncoding :: MonadIO m => Magic -> OsPath -> m(Maybe MimeEncoding)
getMagicMimeEncoding m f = liftIO $ fmap snd <$> getMagicMime m f