packages feed

crypt-sha512-0: test/System/POSIX/Crypt.hsc

 {-# LANGUAGE Trustworthy, CApiFFI #-}
module System.POSIX.Crypt (crypt) where

#include <unistd.h>

import Control.Concurrent.MVar (MVar, newMVar, withMVar)
import Foreign (nullPtr)
import Foreign.C (CString)
import System.IO.Unsafe (unsafePerformIO)

import qualified Data.ByteString as BS

-- crypt is not re-entrable
lock :: MVar ()
lock = unsafePerformIO $ newMVar ()
{-# NOINLINE lock #-}

foreign import ccall unsafe "crypt"
   c_crypt :: CString -> CString -> IO CString

-- | Calls @crypt@.
crypt
    :: BS.ByteString  -- ^ key
    -> BS.ByteString  -- ^ salt
    -> Maybe BS.ByteString
crypt key salt = unsafePerformIO $ withMVar lock $ \_ ->
    BS.useAsCString key $ \ckey ->
    BS.useAsCString salt $ \csalt -> do
        res <- c_crypt ckey csalt
        if res == nullPtr
            then return Nothing
            else do
                bs <- BS.packCString res
                bs `seq` return (Just bs)
{-# NOINLINE crypt #-}