[commit: packages/unix] readdirstream-maybe-patch: Update readDirStream to use Maybe (7c89170)
git at git.haskell.org
git at git.haskell.org
Wed Jul 19 22:04:38 UTC 2017
Repository : ssh://git@git.haskell.org/unix
On branch : readdirstream-maybe-patch
Link : http://ghc.haskell.org/trac/ghc/changeset/7c89170c19db81b76fbcda8c73e6c6fd9f364f00/unix
>---------------------------------------------------------------
commit 7c89170c19db81b76fbcda8c73e6c6fd9f364f00
Author: Eric Mertens <emertens at galois.com>
Date: Tue Dec 6 23:22:53 2016 -0800
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
>---------------------------------------------------------------
7c89170c19db81b76fbcda8c73e6c6fd9f364f00
System/Posix/Directory.hsc | 32 +++++++++++---------------------
System/Posix/Directory/ByteString.hsc | 32 +++++++++++---------------------
cbits/HsUnix.c | 3 ++-
changelog.md | 4 ++++
4 files changed, 28 insertions(+), 43 deletions(-)
diff --git a/System/Posix/Directory.hsc b/System/Posix/Directory.hsc
index 10dcbb4..7273f30 100644
--- a/System/Posix/Directory.hsc
+++ b/System/Posix/Directory.hsc
@@ -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"
diff --git a/System/Posix/Directory/ByteString.hsc b/System/Posix/Directory/ByteString.hsc
index b5ea462..dc03212 100644
--- a/System/Posix/Directory/ByteString.hsc
+++ b/System/Posix/Directory/ByteString.hsc
@@ -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"
diff --git a/cbits/HsUnix.c b/cbits/HsUnix.c
index 7c72a34..5ba9fdc 100644
--- a/cbits/HsUnix.c
+++ b/cbits/HsUnix.c
@@ -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;
diff --git a/changelog.md b/changelog.md
index 4bbeeb3..d1bc198 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,9 @@
# 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.
More information about the ghc-commits
mailing list