Commit 7c89170c authored by emertens's avatar emertens
Browse files

Update readDirStream to use Maybe

This patch changes `readDirStream` to signal end of directory with a
Nothing value. In addition it changes the wrapped readdir function to
only return -1 in the case of an actual error. This change allows the
errno handling logic to take advantage of helpers from Foreign.C.Error,
simplifying the logic.

Fixes #81
parent fb1efd1f
......@@ -87,28 +87,18 @@ foreign import capi unsafe "HsUnix.h opendir"
-- | @readDirStream dp@ calls @readdir@ to obtain the
-- next directory entry (@struct dirent@) for the open directory
-- stream @dp@, and returns the @d_name@ member of that
-- structure.
readDirStream :: DirStream -> IO FilePath
-- structure. 'Nothing' is returned upon reaching the end
-- of the directory.
readDirStream :: DirStream -> IO (Maybe FilePath)
readDirStream (DirStream dirp) =
alloca $ \ptr_dEnt -> loop ptr_dEnt
where
loop ptr_dEnt = do
resetErrno
r <- c_readdir dirp ptr_dEnt
if (r == 0)
then do dEnt <- peek ptr_dEnt
if (dEnt == nullPtr)
then return []
else do
entry <- (d_name dEnt >>= peekFilePath)
c_freeDirEnt dEnt
return entry
else do errno <- getErrno
if (errno == eINTR) then loop ptr_dEnt else do
let (Errno eo) = errno
if (eo == 0)
then return []
else throwErrno "readDirStream"
alloca $ \ptr_dEnt ->
do throwErrnoIfMinus1Retry_ "readdir" (c_readdir dirp ptr_dEnt)
dEnt <- peek ptr_dEnt
if dEnt == nullPtr
then return Nothing
else do entry <- peekFilePath =<< d_name dEnt
c_freeDirEnt dEnt
return (Just entry)
-- traversing directories
foreign import ccall unsafe "__hscore_readdir"
......
......@@ -88,28 +88,18 @@ foreign import capi unsafe "HsUnix.h opendir"
-- | @readDirStream dp@ calls @readdir@ to obtain the
-- next directory entry (@struct dirent@) for the open directory
-- stream @dp@, and returns the @d_name@ member of that
-- structure.
readDirStream :: DirStream -> IO RawFilePath
-- structure. 'Nothing' is returned upon reaching the end
-- of the directory.
readDirStream :: DirStream -> IO (Maybe RawFilePath)
readDirStream (DirStream dirp) =
alloca $ \ptr_dEnt -> loop ptr_dEnt
where
loop ptr_dEnt = do
resetErrno
r <- c_readdir dirp ptr_dEnt
if (r == 0)
then do dEnt <- peek ptr_dEnt
if (dEnt == nullPtr)
then return BC.empty
else do
entry <- (d_name dEnt >>= peekFilePath)
c_freeDirEnt dEnt
return entry
else do errno <- getErrno
if (errno == eINTR) then loop ptr_dEnt else do
let (Errno eo) = errno
if (eo == 0)
then return BC.empty
else throwErrno "readDirStream"
alloca $ \ptr_dEnt ->
do throwErrnoIfMinus1Retry_ "readdir" (c_readdir dirp ptr_dEnt)
dEnt <- peek ptr_dEnt
if dEnt == nullPtr
then return Nothing
else do entry <- peekFilePath =<< d_name dEnt
c_freeDirEnt dEnt
return (Just entry)
-- traversing directories
foreign import ccall unsafe "__hscore_readdir"
......
......@@ -94,8 +94,9 @@ int __hscore_readdir( DIR *dirPtr, struct dirent **pDirEnt )
return -1;
}
errno = 0;
*pDirEnt = readdir(dirPtr);
if (*pDirEnt == NULL) {
if (*pDirEnt == NULL && errno != 0) {
return -1;
} else {
return 0;
......
# Changelog for [`unix` package](http://hackage.haskell.org/package/unix)
## next
* Change type of `readDirStream` and use `Nothing` to signal end of directory
## 2.7.2.1 *Sep 2016*
* Don't use `readdir_r` if its deprecated.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment