libmagic (empty) → 1.2
raw patch · 10 files changed
+493/−0 lines, 10 filesdep +basedep +bytestringdep +filepath
Dependencies added: base, bytestring, filepath, os-string
Files
- CHANGELOG +11/−0
- COPYING +26/−0
- Magic.hs +33/−0
- Magic/Data.hsc +77/−0
- Magic/Init.hsc +69/−0
- Magic/Operations.hsc +90/−0
- Magic/Types.hs +28/−0
- Magic/TypesLL.hsc +41/−0
- Magic/Utils.hsc +76/−0
- libmagic.cabal +42/−0
+ CHANGELOG view
@@ -0,0 +1,11 @@+haskell-libmagic (1.2) unstable; urgency=medium++ * Initial release, forked from John Goerzen's magic package.+ * Don't use unsafe FFI calls for blocking I/O+ (thanks, Niklas Hambüchen)+ * Made the Magic handle thread safe.+ * magicLoad takes a list of paths.+ * Convert from FilePath to OsPath.+ * Remove magicCompile.++ -- Joey Hess <id@joeyh.name> Mon, 26 Oct 2026 10:02:59 -0400
+ COPYING view
@@ -0,0 +1,26 @@+Copyright (c) 2005 John Goerzen.+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.+3. Neither the name of John Goerzen nor the names of contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Magic.hs view
@@ -0,0 +1,33 @@+{- -*- Mode: haskell; -*-+Haskell Magic Interface+Copyright (C) 2005 John Goerzen <jgoerzen@complete.org>++This code is under a 3-clause BSD license; see COPYING for details.+-}++{- |+ Module : Magic+ Copyright : Copyright (C) 2005 John Goerzen+ License : BSD++ Maintainer : Joey Hess,+ Maintainer : id\@joeyh.name+ Stability : provisional+ Portability: portable++Top-level Magic module.++Written by John Goerzen, jgoerzen\@complete.org+-}++module Magic (-- * Basic Types+ module Magic.Types,+ -- * Initialization+ module Magic.Init,+ -- * Operation+ module Magic.Operations+ )+where+import Magic.Types+import Magic.Init+import Magic.Operations
+ Magic/Data.hsc view
@@ -0,0 +1,77 @@+-- AUTO-GENERATED FILE, DO NOT EDIT. GENERATED BY utils/genconsts.hs+{- |+ Module : Magic.Data+ Copyright : Copyright (C) 2005 John Goerzen+ License : BSD++ Maintainer : Joey Hess,+ Maintainer : id\@joeyh.name+ Stability : provisional+ Portability: portable++Haskell types for libmagic constants++Written by John Goerzen, jgoerzen\@complete.org+-}++module Magic.Data (module Magic.Data) where++#include "magic.h"+++data MagicFlag =+ MagicNone+ | MagicDebug+ | MagicSymlink+ | MagicCompress+ | MagicDevices+ | MagicMimeType+ | MagicMimeEncoding+ | MagicMime+ | MagicContinue+ | MagicCheck+ | MagicPreserveAtime+ | MagicRaw+ | MagicError+ | UnknownMagicFlag Int++ deriving (Show)++instance Enum MagicFlag where+ toEnum (#{const MAGIC_NONE}) = MagicNone+ toEnum (#{const MAGIC_DEBUG}) = MagicDebug+ toEnum (#{const MAGIC_SYMLINK}) = MagicSymlink+ toEnum (#{const MAGIC_COMPRESS}) = MagicCompress+ toEnum (#{const MAGIC_DEVICES}) = MagicDevices+ toEnum (#{const MAGIC_MIME_TYPE}) = MagicMimeType+ toEnum (#{const MAGIC_MIME_ENCODING}) = MagicMimeEncoding+ toEnum (#{const MAGIC_MIME}) = MagicMime+ toEnum (#{const MAGIC_CONTINUE}) = MagicContinue+ toEnum (#{const MAGIC_CHECK}) = MagicCheck+ toEnum (#{const MAGIC_PRESERVE_ATIME}) = MagicPreserveAtime+ toEnum (#{const MAGIC_RAW}) = MagicRaw+ toEnum (#{const MAGIC_ERROR}) = MagicError+ toEnum x = UnknownMagicFlag x++ fromEnum MagicNone = (#{const MAGIC_NONE})+ fromEnum MagicDebug = (#{const MAGIC_DEBUG})+ fromEnum MagicSymlink = (#{const MAGIC_SYMLINK})+ fromEnum MagicCompress = (#{const MAGIC_COMPRESS})+ fromEnum MagicDevices = (#{const MAGIC_DEVICES})+ fromEnum MagicMimeType = (#{const MAGIC_MIME_TYPE})+ fromEnum MagicMimeEncoding = (#{const MAGIC_MIME_ENCODING})+ fromEnum MagicMime = (#{const MAGIC_MIME})+ fromEnum MagicContinue = (#{const MAGIC_CONTINUE})+ fromEnum MagicCheck = (#{const MAGIC_CHECK})+ fromEnum MagicPreserveAtime = (#{const MAGIC_PRESERVE_ATIME})+ fromEnum MagicRaw = (#{const MAGIC_RAW})+ fromEnum MagicError = (#{const MAGIC_ERROR})+ fromEnum (UnknownMagicFlag x) = x++instance Ord MagicFlag where+ compare x y = compare (fromEnum x) (fromEnum y)++instance Eq MagicFlag where+ x == y = (fromEnum x) == (fromEnum y)++
+ Magic/Init.hsc view
@@ -0,0 +1,69 @@+{- -*- Mode: haskell; -*-+Haskell magic Interface+Copyright (C) 2005 John Goerzen <jgoerzen@complete.org>++This code is under a 3-clause BSD license; see COPYING for details.+-}++{- |+ Module : Magic.Init+ Copyright : Copyright (C) 2005 John Goerzen+ License : BSD++ Maintainer : Joey Hess,+ Maintainer : id\@joeyh.name+ Stability : provisional+ Portability: portable++Initialization and shutdown for magic programs++Written by John Goerzen, jgoerzen\@complete.org+-}++{-# LANGUAGE OverloadedStrings #-}++module Magic.Init(magicOpen, magicLoad, magicLoadDefault)+where++import Foreign.Ptr+import Foreign.C.String+import Magic.Types+import Foreign.C.Types+import Magic.Utils+import Magic.TypesLL+import qualified Data.List.NonEmpty as NE+import System.OsPath.Types+import System.OsString.Internal.Types+import Data.Coerce+import qualified Data.ByteString.Short as SBS++{- | Create a Magic object. You must call either 'magicLoadDefault'+or 'magicLoad' after this.+-}+magicOpen :: [MagicFlag] -> IO Magic+magicOpen mfl =+ fromMagicPtr "magicOpen" (magic_open flags)+ where flags = flaglist2int mfl++{- | Load the system's default magic database. -}+magicLoadDefault :: Magic -> IO ()+magicLoadDefault m = withMagicPtr m $ \cmagic ->+ checkIntError "magicLoadDefault" cmagic $ magic_load cmagic nullPtr++{- | Load the specified magic databases. -}+magicLoad :: Magic -> NE.NonEmpty OsPath -> IO ()+magicLoad m l = withMagicPtr m $ \cmagic ->+ SBS.useAsCString s $ \cs ->+ checkIntError "magicLoad" cmagic $ magic_load cmagic cs+ where+ s = SBS.intercalate ":" (map conv (NE.toList l))++ conv p = case coercionToPlatformTypes of+ Right _ -> getWindowsString (coerce p)+ Left _ -> getPosixString (coerce p)++foreign import ccall unsafe "magic.h magic_open"+ magic_open :: CInt -> IO (Ptr CMagic)++foreign import ccall safe "magic.h magic_load"+ magic_load :: Ptr CMagic -> CString -> IO CInt
+ Magic/Operations.hsc view
@@ -0,0 +1,90 @@+{- -*- Mode: haskell; -*-+Haskell magic Interface+Copyright (C) 2005 John Goerzen <jgoerzen@complete.org>++This code is under a 3-clause BSD license; see COPYING for details.+-}++{- |+ Module : Magic.Init+ Copyright : Copyright (C) 2005 John Goerzen+ License : BSD++ Maintainer : Joey Hess,+ Maintainer : id\@joeyh.name+ Stability : provisional+ Portability: portable++Initialization and shutdown for magic programs++Written by John Goerzen, jgoerzen\@complete.org+-}++module Magic.Operations(-- * Guessing the type+ magicFile, magicStdin,+ magicString, magicCString,+ -- * Other operations+ magicSetFlags)+where++import Foreign.Ptr+import Foreign.C.String+import Magic.Types+import Foreign.C.Types+import Data.Word+import Magic.Utils+import Magic.TypesLL+import System.OsPath.Types+import System.OsString.Internal.Types+import Data.Coerce+import qualified Data.ByteString.Short as SBS++{- | Calls the Magic system on the specified file. -}+magicFile :: Magic -> OsPath -> IO String+magicFile magic fp =+ withMagicPtr magic $ \cmagic ->+ SBS.useAsCString sbsfp $ \cfp -> do+ res <- throwErrorIfNull "magicFile" cmagic (magic_file cmagic cfp)+ peekCString res+ where+ sbsfp = case coercionToPlatformTypes of+ Right _ -> getWindowsString (coerce fp)+ Left _ -> getPosixString (coerce fp)++{- | Calls the Magic system on stdin. -}+magicStdin :: Magic -> IO String+magicStdin magic =+ withMagicPtr magic $ \cmagic ->+ do res <- throwErrorIfNull "magicStdin" cmagic (magic_file cmagic nullPtr)+ peekCString res++{- | Calls the Magic system to process the given String. Please note:+it is not evaluated lazily. -}+magicString :: Magic -> String -> IO String+magicString m s = withCStringLen s (magicCString m)++{- | Lower-level function used to call the Magic system to process a C +string. -}+magicCString :: Magic -> CStringLen -> IO String+magicCString magic (cstr, len) =+ withMagicPtr magic $ \cmagic ->+ do res <- throwErrorIfNull "magicCString" cmagic (magic_buffer cmagic cstr (fromIntegral len))+ peekCString res++{- | Change the flags on an already-created object. -}+magicSetFlags :: Magic -> [MagicFlag] -> IO ()+magicSetFlags m mfl = withMagicPtr m $ \cmagic ->+ checkIntError "magicSetFlags" cmagic $ magic_setflags cmagic flags+ where flags = flaglist2int mfl++-- Does file I/O -> safe+foreign import ccall safe "magic.h magic_file"+ magic_file :: Ptr CMagic -> CString -> IO CString++-- Does not do I/O -> unsafe+foreign import ccall unsafe "magic.h magic_buffer"+ magic_buffer :: Ptr CMagic -> CString -> #{type size_t} -> IO CString++-- Does not do I/O -> unsafe+foreign import ccall unsafe "magic.h magic_setflags"+ magic_setflags :: Ptr CMagic -> CInt -> IO CInt
+ Magic/Types.hs view
@@ -0,0 +1,28 @@+{- -*- Mode: haskell; -*-+Haskell magic Interface+Copyright (C) 2005 John Goerzen <jgoerzen@complete.org>++This code is under a 3-clause BSD license; see COPYING for details.+-}++{- |+ Module : Magic.Types+ Copyright : Copyright (C) 2005 John Goerzen+ License : BSD++ Maintainer : Joey Hess,+ Maintainer : id\@joeyh.name+ Stability : provisional+ Portability: portable++Types for magic programs.++Written by John Goerzen, jgoerzen\@complete.org+-}++module Magic.Types(Magic,+ MagicFlag(..))+where++import Magic.TypesLL+import Magic.Data
+ Magic/TypesLL.hsc view
@@ -0,0 +1,41 @@+{- -*- Mode: haskell; -*-+Haskell magic Interface+Copyright (C) 2005 John Goerzen <jgoerzen@complete.org>++This code is under a 3-clause BSD license; see COPYING for details.+-}++{- |+ Module : Magic.TypesLL+ Copyright : Copyright (C) 2005 John Goerzen+ License : BSD++ Maintainer : Joey Hess,+ Maintainer : id\@joeyh.name+ Stability : provisional+ Portability: portable++Low-Types for magic programs.++Written by John Goerzen, jgoerzen\@complete.org+-}++module Magic.TypesLL(CMagic, Magic(..))+where++import Foreign.ForeignPtr+import Control.Concurrent.MVar++#include <magic.h>++data CMagic++{- | Main Magic handle.++Magic objects are automatically closed (and memory freed) when they are+garbage-collected by Haskell. There is no need to explicitly close them.++Access to the C library is serialized, so multiple threads may safely+use the same Magic handle.+-}+newtype Magic = Magic (MVar (ForeignPtr CMagic))
+ Magic/Utils.hsc view
@@ -0,0 +1,76 @@+{- -*- Mode: haskell; -*-+Haskell magic Interface+Copyright (C) 2005 John Goerzen <jgoerzen@complete.org>++This code is under a 3-clause BSD license; see COPYING for details.+-}++{- |+ Module : Magic.Utils+ Copyright : Copyright (C) 2005 John Goerzen+ License : BSD++ Maintainer : Joey Hess,+ Maintainer : id\@joeyh.name+ Stability : provisional+ Portability: portable++Utils++Written by John Goerzen, jgoerzen\@complete.org+-}++module Magic.Utils (flaglist2int, fromMagicPtr, withMagicPtr, checkIntError,+ throwErrorIfNull)+where++import Foreign+import Foreign.C.Error+import Foreign.C.String+import Magic.TypesLL+import Magic.Types+import Foreign.C.Types+import Control.Concurrent.MVar++flaglist2int :: [MagicFlag] -> CInt+flaglist2int mfl =+ foldl (\c f -> c .|. (fromIntegral . fromEnum $ f)) 0 mfl++fromMagicPtr :: String -> IO (Ptr CMagic) -> IO Magic+fromMagicPtr caller action =+ do ptr <- throwErrnoIfNull caller action+ m <- newForeignPtr magic_close ptr+ mvar <- newMVar m+ return (Magic mvar)++throwErrorIfNull :: String -> Ptr CMagic -> IO (Ptr a) -> IO (Ptr a)+throwErrorIfNull caller m action =+ do res <- action+ if res == nullPtr+ then throwError caller m+ else return res++withMagicPtr :: Magic -> (Ptr CMagic -> IO a) -> IO a+withMagicPtr (Magic mvar) a = withMVar mvar $ \m -> withForeignPtr m a++throwError :: String -> Ptr CMagic -> IO a+throwError caller cmagic =+ do errormsg <- magic_error cmagic+ if errormsg /= nullPtr+ then do em <- peekCString errormsg+ fail $ caller ++ ": " ++ em+ else fail $ caller ++ ": got error code but no error message"++checkIntError :: String -> Ptr CMagic -> IO CInt -> IO ()+checkIntError caller cmagic action = + do res <- action+ if res == 0+ then return ()+ else throwError caller cmagic+++foreign import ccall unsafe "magic.h &magic_close"+ magic_close :: FunPtr (Ptr CMagic -> IO ())++foreign import ccall unsafe "magic.h magic_error"+ magic_error :: Ptr CMagic -> IO CString
+ libmagic.cabal view
@@ -0,0 +1,42 @@+Name: libmagic+Version: 1.2+Cabal-Version: >= 1.10+License: BSD3+Maintainer: Joey Hess <id@joeyh.name>+Author: John Goerzen+Stability: Stable+Copyright: Copyright (c) 2005-2009 John Goerzen+Build-Type: Simple+license-file: COPYING+Category: Text+Synopsis: Interface to C file/magic library+Description: This package provides a Haskell interface to the C libmagic library.+ With it, you can determine the type of a file by examining its contents+ rather than its name. The Haskell interface provides a full-featured+ binding.+Extra-Source-Files: CHANGELOG++Library+ Extra-Libraries: magic+ Exposed-Modules:+ Magic,+ Magic.Data,+ Magic.Types,+ Magic.Init,+ Magic.Operations+ Other-Modules:+ Magic.Utils,+ Magic.TypesLL+ Build-Depends:+ base >= 3 && < 5,+ filepath >= 1.4.100 && < 1.6,+ os-string >= 2.0.0 && < 2.1,+ bytestring < 0.13+ GHC-Options: -O2 -Wall+ Default-Language: Haskell2010+ Default-Extensions: ForeignFunctionInterface, TypeSynonymInstances,+ EmptyDataDecls++source-repository head+ type: git+ location: https://git.joeyh.name/git/haskell-libmagic.git