Last active
August 29, 2015 14:01
-
-
Save gregorycollins/00c51e7e33cf1f9c8cc0 to your computer and use it in GitHub Desktop.
Directory traversal with io-streams
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE OverloadedStrings #-} | |
module Main where | |
import qualified Control.Exception as E | |
import Control.Monad ((>=>)) | |
import qualified Data.ByteString.Char8 as S | |
import System.IO.Streams (InputStream) | |
import qualified System.IO.Streams as Streams | |
import System.Posix.ByteString.FilePath (RawFilePath) | |
import qualified System.Posix.Directory.ByteString as D | |
traverseDirectory :: RawFilePath -> (InputStream RawFilePath -> IO a) -> IO a | |
traverseDirectory fp m = E.bracket (D.openDirStream fp) D.closeDirStream go | |
where | |
go d = Streams.makeInputStream (readDirStr d) >>= m | |
readDirStr d = do s <- D.readDirStream d | |
return $! if S.null s then Nothing else Just s | |
main :: IO () | |
main = traverseDirectory "." $ Streams.map (`S.append` "\n") >=> | |
Streams.connectTo Streams.stdout |
Yes, if closedir ever fails, you already have memory corruption. Otherwise this pattern would be unsafe.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just in case this code is going to be used in production somewhere: the deallocation code is not exception safe. If one of the
closedir
calls fails, then all succeeding calls will not be called. In practice, it's likely impossible for that situation to arise, since (according to the man page) the only timeclosedir
will fail is when it's passed an invalid structure, but I'd still be cautious of it.