diff --git a/System/Posix/Directory.hsc b/System/Posix/Directory.hsc
index 10dcbb4c45d1d83f0217e76e0df4ae65c91f107b..7273f3020f5b67ca0eec4b8ac166fd905a8a4ffb 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 b5ea462c58282788f64cee49042c8d7f4997dcc2..dc032126b86dfe5696dc1064eb1d07cada299511 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 7c72a341cbbdabeea820b4acd375ffbd1da30e17..5ba9fdc60cf44d843f61b0b44ef05390e20578cb 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 4bbeeb374a208bbd6f1a29d6e54a05009d26a876..d1bc198666efa98a9306c2332cd00214e914db89 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.