Index: trunk/src/emx/ChangeLog.LIBC
===================================================================
--- trunk/src/emx/ChangeLog.LIBC	(revision 2420)
+++ trunk/src/emx/ChangeLog.LIBC	(revision 2424)
@@ -2,4 +2,8 @@
 
 TODO: open replace on RAMFS fails with error 32!
+
+2005-10-26: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - libc:
+        o Implemented getdirents().
 
 2005-09-26: knut st. osmundsen <bird-gccos2-spam@anduin.net>
Index: trunk/src/emx/include/InnoTekLIBC/backend.h
===================================================================
--- trunk/src/emx/include/InnoTekLIBC/backend.h	(revision 2420)
+++ trunk/src/emx/include/InnoTekLIBC/backend.h	(revision 2424)
@@ -447,4 +447,21 @@
  */
 int __libc_Back_ioFileSizeSet(int fh, __off_t cbFile, int fZero);
+
+/**
+ * Reads directory entries from an open directory.
+ *
+ * @returns Number of bytes read.
+ * @returns Negative error code (errno.h) on failure.
+ *
+ * @param   fh      The file handle of an open directory.
+ * @param   pvBuf   Where to store the directory entries.
+ *                  The returned data is a series of dirent structs with
+ *                  variable name size. d_reclen must be used the offset
+ *                  to the next struct (from the start of the current one).
+ * @param   cbBuf   Size of the buffer.
+ * @param   poff    Where to store the lseek offset of the first entry.
+ *
+ */
+ssize_t __libc_Back_ioDirGetEntries(int fh, void *pvBuf, size_t cbBuf, __off_t *poff);
 
 /**
Index: trunk/src/emx/include/dirent.h
===================================================================
--- trunk/src/emx/include/dirent.h	(revision 2420)
+++ trunk/src/emx/include/dirent.h	(revision 2424)
@@ -128,6 +128,6 @@
 /** @todo DIR	*__opendir2(const char *, int); */
 /** @todo int	 alphasort(const void *, const void *); */
-/** @todo int	 getdents(int, char *, int); */
-/** @todo int	 getdirentries(int, char *, int, long *); */
+int	 getdents(int, char *, int);
+int	 getdirentries(int, char *, int, long *);
 #endif
 DIR	*opendir(const char *);
Index: trunk/src/emx/src/lib/libc.def
===================================================================
--- trunk/src/emx/src/lib/libc.def	(revision 2420)
+++ trunk/src/emx/src/lib/libc.def	(revision 2424)
@@ -1950,2 +1950,4 @@
     "___libc_Back_fsDirCurrentSetFH" @1948
     "__std_fchdir" @1949
+    "___libc_Back_ioDirGetEntries" @1950
+    "__std_getdirents" @1951
Index: trunk/src/emx/src/lib/sys/b_dir.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_dir.c	(revision 2420)
+++ trunk/src/emx/src/lib/sys/b_dir.c	(revision 2424)
@@ -44,4 +44,5 @@
 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_IO
 #include <InnoTekLIBC/logstrict.h>
+#include <InnoTekLIBC/libc.h>
 
 
@@ -132,6 +133,16 @@
 static int dirRead(__LIBC_PFH pFH, int fh, void *pvBuf, size_t cbRead, size_t *pcbRead)
 {
-    /** @todo */
-    return -ENOSYS;
+    LIBCLOG_ENTER("pFH=%p fh=%d pvBuf=%p cbRead=%d pcbRead=%p\n", (void *)pFH, fh, pvBuf, cbRead, (void *)pcbRead);
+    if (cbRead >= sizeof(struct dirent))
+    {
+        ssize_t cb = __libc_back_dirGetEntries((__LIBC_PFHDIR)pFH, pvBuf, cbRead);
+        if (cb >= 0)
+        {
+            *pcbRead = cb;
+            LIBCLOG_RETURN_INT(0);
+        }
+        LIBCLOG_ERROR_RETURN_INT(cb);
+    }
+    LIBCLOG_ERROR_RETURN_INT(-EOVERFLOW); /* not a proper read error, but it's the best I can think of for this situation. */
 }
 
@@ -308,8 +319,4 @@
     return 0;
 }
-
-
-
-int __libc_Back_dirOpen(const char *pszPath);
 
 
@@ -509,2 +516,124 @@
 }
 
+
+
+/**
+ * Reads directory entries.
+ *
+ * @returns Number of bytes read.
+ * @returns Negative error code (errno.h) on failure.
+ *
+ * @param   fh      The file handle of an open directory.
+ * @param   pvBuf   Where to store the directory entries.
+ *                  The returned data is a series of dirent structs with
+ *                  variable name size. d_reclen must be used the offset
+ *                  to the next struct (from the start of the current one).
+ * @param   cbBuf   Size of the buffer.
+ *
+ */
+ssize_t __libc_back_dirGetEntries(__LIBC_PFHDIR pFHDir, void *pvBuf, size_t cbBuf)
+{
+    /* prepare the native path */
+    char szNativePath[PATH_MAX + 5];
+    size_t cch = strlen(pFHDir->Core.pszNativePath);
+    memcpy(szNativePath, pFHDir->Core.pszNativePath, cch);
+    szNativePath[cch++] = '/';
+
+    /* copy data */
+    ssize_t cbRet = 0;
+    while (cbBuf >= sizeof(struct dirent))
+    {
+        /*
+         * Fill the buffer?
+         */
+        if (pFHDir->cFiles <= 0)
+        {
+            FS_VAR_SAVE_LOAD();
+            pFHDir->cFiles = pFHDir->cbBuf / 40;
+#if OFF_MAX > LONG_MAX
+            if (pFHDir->fType == FIL_QUERYEASIZEL)  /* the L version is buggy!! Make sure there is enough space. */
+                pFHDir->cFiles = pFHDir->cbBuf / sizeof(FILEFINDBUF4L);
+#endif
+            pFHDir->uCur.pv = pFHDir->uBuf.pv;
+
+            int rc = DosFindNext(pFHDir->hDir,
+                                 pFHDir->uBuf.pv,
+                                 pFHDir->cbBuf,
+                                 &pFHDir->cFiles);
+            FS_RESTORE();
+            if (rc)
+            {
+                /** @todo verify that ERROR_NO_MORE_FILES is returned repeatedly. */
+                if (!cbRet && rc != ERROR_NO_MORE_FILES)
+                    cbRet = -__libc_native2errno(rc);
+                pFHDir->cFiles = 0;
+                break;
+            }
+            LIBC_ASSERT(pFHDir->cFiles);
+            if (!pFHDir->cFiles) /* paranoia */
+                break;
+        }
+
+        /*
+         * Fill the return buffer.
+         */
+        struct dirent *pDir = (struct dirent *)pvBuf;
+        pDir->d_reclen = sizeof(struct dirent);
+        pDir->d_type = DT_UNKNOWN;
+        pDir->d_fileno = -1; /** @todo */
+        int fMayHaveEAs;
+        if (__predict_true(pFHDir->fType == FIL_QUERYEASIZEL))
+        {
+            fMayHaveEAs = pFHDir->uCur.p4L->cbList > sizeof(USHORT) * 2 + 1;
+            if (pFHDir->uCur.p4L->attrFile & FILE_DIRECTORY)
+                pDir->d_type = DT_DIR;
+            pDir->d_namlen = pFHDir->uCur.p4L->cchName;
+            memcpy(&pDir->d_name[0], &pFHDir->uCur.p4L->achName[0], pDir->d_namlen);
+        }
+        else
+        {
+            LIBC_ASSERT(pFHDir->fType == FIL_QUERYEASIZE);
+            fMayHaveEAs = pFHDir->uCur.p4->cbList > sizeof(USHORT) * 2 + 1;
+            if (pFHDir->uCur.p4->attrFile & FILE_DIRECTORY)
+                pDir->d_type = DT_DIR;
+            pDir->d_namlen = pFHDir->uCur.p4->cchName;
+            memcpy(&pDir->d_name[0], &pFHDir->uCur.p4->achName[0], pDir->d_namlen);
+        }
+        pDir->d_name[pDir->d_namlen] = '\0';
+
+        /*
+         * Get unix attributes mode and ino, try EAs first.
+         */
+        memcpy(&szNativePath[cch], pDir->d_name, pDir->d_namlen + 1);
+        if (fMayHaveEAs)
+        {
+            if (!__libc_gfNoUnix)
+            {
+                /** @todo */
+                /** @todo */
+                fMayHaveEAs = 0;
+            }
+            else
+                fMayHaveEAs = 0;
+        }
+        if (!fMayHaveEAs)
+        {
+            ino_t Inode; /** @todo use d_ino directly when we've corrected the structure. */
+            __libc_back_fsPathCalcInodeAndDev(szNativePath, &Inode);
+            pDir->d_fileno = Inode;
+            if (pDir->d_type == DT_UNKNOWN)
+                pDir->d_type = DT_REG;
+        }
+
+        /*
+         * Advance buffers.
+         */
+        cbBuf -= sizeof(struct dirent);
+        cbRet += sizeof(struct dirent);
+        pvBuf = (char *)pvBuf + sizeof(struct dirent);
+        pFHDir->cFiles--;
+        pFHDir->uCur.pu8 += pFHDir->uCur.p4->oNextEntryOffset;
+    }
+    return cbRet;
+}
+
Index: trunk/src/emx/src/lib/sys/b_dir.h
===================================================================
--- trunk/src/emx/src/lib/sys/b_dir.h	(revision 2420)
+++ trunk/src/emx/src/lib/sys/b_dir.h	(revision 2424)
@@ -75,5 +75,5 @@
 int __libc_back_dirInherit(int fh, const char *pszNativePath, unsigned fInUnixTree, unsigned fFlags,
                            ino_t Inode, dev_t Dev, unsigned uCurEntry);
-
+ssize_t __libc_back_dirGetEntries(__LIBC_PFHDIR pFHDir, void *pvBuf, size_t cbBuf);
 
 #endif
Index: trunk/src/emx/src/lib/sys/b_ioFileOpen.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_ioFileOpen.c	(revision 2420)
+++ trunk/src/emx/src/lib/sys/b_ioFileOpen.c	(revision 2424)
@@ -198,5 +198,9 @@
                     rc = __libc_Back_dirOpenNative(szNativePath, fInUnixTree, fLibc, &st);
                     if (rc >= 0)
+                    {
+                        if (ppFH)
+                            *ppFH = __libc_FH(rc);
                         LIBCLOG_RETURN_INT(rc);
+                    }
                     LIBCLOG_ERROR_RETURN_INT(rc);
                     break;
