diff --git a/lib/Filesystem.hs b/lib/Filesystem.hs
--- a/lib/Filesystem.hs
+++ b/lib/Filesystem.hs
@@ -307,8 +307,9 @@
 #else
 listDirectory root = Exc.bracket alloc free list where
 	alloc = do
-		dirent <- c_alloc_dirent
 		dir <- openDir root
+		let Dir _ dirp = dir
+		dirent <- c_alloc_dirent dirp
 		return (dirent, dir)
 	free (dirent, dir) = do
 		c_free_dirent dirent
@@ -356,7 +357,7 @@
 	c_closedir :: Ptr () -> IO CInt
 
 foreign import ccall unsafe "hssystemfileio_alloc_dirent"
-	c_alloc_dirent :: IO (Ptr ())
+	c_alloc_dirent :: Ptr () -> IO (Ptr ())
 
 foreign import ccall unsafe "hssystemfileio_free_dirent"
 	c_free_dirent :: Ptr () -> IO ()
diff --git a/lib/hssystemfileio-unix.c b/lib/hssystemfileio-unix.c
--- a/lib/hssystemfileio-unix.c
+++ b/lib/hssystemfileio-unix.c
@@ -1,15 +1,43 @@
 #include "hssystemfileio-unix.h"
 
+/* Enable POSIX-compliant readdir_r on Solaris */
+#define _POSIX_PTHREAD_SEMANTICS
+
+/* Enable dirfd() */
+#define _BSD_SOURCE
+
+#include <dirent.h>
 #include <errno.h>
+#include <stddef.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 struct dirent *
-hssystemfileio_alloc_dirent()
+hssystemfileio_alloc_dirent(void *void_dir)
 {
-	return malloc(sizeof (struct dirent));
+	DIR *dir = (DIR *)void_dir;
+	long name_max;
+	size_t name_end;
+	
+	name_max = fpathconf(dirfd(dir), _PC_NAME_MAX);
+	if (name_max == -1)
+	{
+#if defined(NAME_MAX) && NAME_MAX > 255
+		name_max = NAME_MAX;
+#else
+		name_max = 4096;
+#endif
+	}
+	
+	name_end = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
+	if (name_end > sizeof(struct dirent))
+	{
+		return malloc(name_end);
+	}
+	
+	return malloc(sizeof(struct dirent));
 }
 
 void
@@ -19,9 +47,10 @@
 }
 
 int
-hssystemfileio_readdir(DIR *dir, struct dirent *dirent)
+hssystemfileio_readdir(void *void_dir, struct dirent *dirent)
 {
 	struct dirent *dirent_result;
+	DIR *dir = (DIR *)void_dir;
 	while (1)
 	{
 		int rc = readdir_r(dir, dirent, &dirent_result);
diff --git a/lib/hssystemfileio-unix.h b/lib/hssystemfileio-unix.h
--- a/lib/hssystemfileio-unix.h
+++ b/lib/hssystemfileio-unix.h
@@ -1,7 +1,7 @@
 #ifndef HSSYSTEMFILEIO_UNIX_H
 #define HSSYSTEMFILEIO_UNIX_H
 
-#include <dirent.h>
+struct dirent;
 
 struct dirent *
 hssystemfileio_alloc_dirent();
@@ -10,7 +10,7 @@
 hssystemfileio_free_dirent(struct dirent *);
 
 int
-hssystemfileio_readdir(DIR *dir, struct dirent *dirent);
+hssystemfileio_readdir(void *dir, struct dirent *dirent);
 
 char *
 hssystemfileio_dirent_name(struct dirent *dirent);
diff --git a/system-fileio.cabal b/system-fileio.cabal
--- a/system-fileio.cabal
+++ b/system-fileio.cabal
@@ -1,5 +1,5 @@
 name: system-fileio
-version: 0.3.8
+version: 0.3.9
 license: MIT
 license-file: license.txt
 author: John Millikin <jmillikin@gmail.com>
@@ -42,7 +42,7 @@
 source-repository this
   type: bazaar
   location: https://john-millikin.com/branches/system-fileio/0.3/
-  tag: system-fileio_0.3.8
+  tag: system-fileio_0.3.9
 
 library
   ghc-options: -Wall -O2
