{-# LANGUAGE RecordWildCards #-}
module Main where
import Control.Monad
import qualified Data.ByteString.Base16 as B16
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy as BL
import System.Console.GetOpt
import System.Environment
import System.Exit
import System.IO
import qualified Crypto.Hash.SHA256 as H
data Options = Options
{ optBinary :: Bool
, optHelp :: Bool
, optTag :: Bool
} deriving Show
defOptions :: Options
defOptions = Options
{ optBinary = True
, optHelp = False
, optTag = False
}
options :: [OptDescr (Options -> Options)]
options = [ Option ['b'] ["binary"]
(NoArg (\o -> o { optBinary = True}))
"read in binary mode (default)"
, Option ['t'] ["text"]
(NoArg (\o -> o { optBinary = False}))
"read in text mode (ignored)"
, Option [] ["help"]
(NoArg (\o -> o { optHelp = True}))
"display help and exit"
, Option [] ["tag"]
(NoArg (\o -> o { optTag = True}))
"create a BSD-style checksum"
]
main :: IO ()
main = do
argv <- getArgs
let Options{..} = foldl (flip id) defOptions optset
(optset,args0,cliErr) = getOpt Permute options argv
args | null args0 = ["-"]
| otherwise = args0
unless (null cliErr) $ do
hPutStrLn stderr ("sha256sum: " ++ head cliErr ++ "Try 'sha256sum --help' for more information.")
exitFailure
when optHelp $ do
putStrLn (usageInfo "Usage: sha256sum [OPTION]... [FILE]...\nPrint or check SHA-256 hashes\n" options)
exitSuccess
forM_ args $ \fn -> do
h <- (B16.encode . H.hashlazy) `fmap` bReadFile fn
case optTag of
False -> do
B.hPutStr stdout h
hPutStrLn stdout (' ':' ':fn)
True -> do
hPutStrLn stdout $ concat [ "SHA256 (", fn, ") = ", B.unpack h ]
return ()
bReadFile :: FilePath -> IO BL.ByteString
bReadFile "-" = do
clsd <- hIsClosed stdin
if clsd then return BL.empty else BL.getContents
bReadFile fn = BL.readFile fn