Index: /trunk/src/emx/ChangeLog.LIBC
===================================================================
--- /trunk/src/emx/ChangeLog.LIBC	(revision 2322)
+++ /trunk/src/emx/ChangeLog.LIBC	(revision 2323)
@@ -2,4 +2,12 @@
 
 TODO: open replace on RAMFS fails with error 32!
+
+2005-09-25: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - libc:
+        o Implemented fchdir().
+        o Implemented inheritance of open directory handles. Unfortunately,
+          I ran out of size bits for the bundle type, so the SPM bit is no
+          longer compatible with earlier versions. The consequences
+          of this are related to inheritance and signaling - so recompile!
 
 2005-08-28: knut st. osmundsen <bird-gccos2-spam@anduin.net>
Index: /trunk/src/emx/include/InnoTekLIBC/backend.h
===================================================================
--- /trunk/src/emx/include/InnoTekLIBC/backend.h	(revision 2322)
+++ /trunk/src/emx/include/InnoTekLIBC/backend.h	(revision 2323)
@@ -235,4 +235,14 @@
  */
 int __libc_Back_fsDirCurrentSet(const char *pszPath, int fDrive);
+
+/**
+ * Changes the current directory of the process.
+ *
+ * @returns 0 on success.
+ * @returns Negative error code (errno.h) on failure.
+ * @param   fh          The handle of an open directory.
+ * @param   fDrive      Force a change of the current drive too.
+ */
+int __libc_Back_fsDirCurrentSetFH(int fh, int fDrive);
 
 /**
Index: /trunk/src/emx/include/InnoTekLIBC/sharedpm.h
===================================================================
--- /trunk/src/emx/include/InnoTekLIBC/sharedpm.h	(revision 2322)
+++ /trunk/src/emx/include/InnoTekLIBC/sharedpm.h	(revision 2323)
@@ -37,8 +37,8 @@
 
 /** The name of the shared semaphore protecting the memory. */
-#define SPM_MUTEX_NAME          "\\SEM32\\INNOTEKLIBC-V1.1"
+#define SPM_MUTEX_NAME          "\\SEM32\\INNOTEKLIBC-V1.3"
 
 /** The name of the shared memory. */
-#define SPM_MEMORY_NAME         "\\SHAREMEM\\INNOTEKLIBC-V1.1"
+#define SPM_MEMORY_NAME         "\\SHAREMEM\\INNOTEKLIBC-V1.3"
 
 /** The timeout for accessing the shared mem semaphore. */
@@ -60,5 +60,5 @@
  * The SPM version.
  */
-#define SPM_VERSION             0x00010002
+#define SPM_VERSION             0x00010003
 
 
@@ -163,13 +163,17 @@
 #define __LIBC_SPM_INH_FHB_TYPE_END         (0)
 /** Standard bundle. */
-#define __LIBC_SPM_INH_FHB_TYPE_STANDARD    (0x10 | (sizeof(unsigned) + sizeof(ino_t) + sizeof(dev_t)))
-/** The old standard bundle. */
-#define __LIBC_SPM_INH_FHB_TYPE_STANDARD_OLD (0x10 | sizeof(unsigned))
+#define __LIBC_SPM_INH_FHB_TYPE_STANDARD    (0xe0 | (sizeof(unsigned) + sizeof(ino_t) + sizeof(dev_t) + sizeof(unsigned)))
+/** Directory bundle. */
+#define __LIBC_SPM_INH_FHB_TYPE_DIRECTORY   (0xc0 | (sizeof(unsigned) + sizeof(ino_t) + sizeof(dev_t) + sizeof(unsigned) + sizeof(unsigned)))
 /** Socket bundle, using the BSD 4.4 backend. */
-#define __LIBC_SPM_INH_FHB_TYPE_SOCKET_44   (0x20 | (sizeof(unsigned) + sizeof(unsigned short)))
+#define __LIBC_SPM_INH_FHB_TYPE_SOCKET_44   (0xa0 | (sizeof(unsigned) + sizeof(unsigned short)))
 /** Socket bundle, using the BSD 4.3 backend. */
-#define __LIBC_SPM_INH_FHB_TYPE_SOCKET_43   (0x30 | (sizeof(unsigned) + sizeof(unsigned short)))
+#define __LIBC_SPM_INH_FHB_TYPE_SOCKET_43   (0x80 | (sizeof(unsigned) + sizeof(unsigned short)))
+/*#define __LIBC_SPM_INH_FHB_TYPE_            (0x60 | (sizeof(unsigned) + ))*/
+/*#define __LIBC_SPM_INH_FHB_TYPE_            (0x40 | (sizeof(unsigned) + ))*/
+/*#define __LIBC_SPM_INH_FHB_TYPE_            (0x20 | (sizeof(unsigned) + ))*/
+/*#define __LIBC_SPM_INH_FHB_TYPE_            (0x00 | (sizeof(unsigned) + ))*/
 /** Get the per file handle size from the bundle type. */
-#define __LIBC_SPM_INH_FHB_SIZE(type)   ((type) & 0x0f)
+#define __LIBC_SPM_INH_FHB_SIZE(type)   ((type) & 0x1f)
 /** @} */
 
@@ -182,5 +186,5 @@
     /** Bundle type. */
     unsigned char   uchType;
-    /** Cound of handles in this bundle. */
+    /** Count of handles in this bundle. */
     unsigned char   cHandles;
     /** Start handle number. */
@@ -204,5 +208,5 @@
     struct
     {
-        /** The flags */
+        /** The flags. */
         unsigned            fFlags;
         /** The inode number. */
@@ -210,4 +214,7 @@
         /** The device number. */
         dev_t               Dev;
+        /** String table offset of the native path. */
+        unsigned            offNativePath : 24;
+        unsigned            u8Reserved : 8;
     } aHandles[1];
 } __LIBC_SPMINHFHBSTD;
@@ -217,19 +224,32 @@
 
 /**
- * SPM standard filehandle inherit bundle
- * This is used for OS/2 filehandles which only needs flags
- * transfered.
+ * SPM directory filehandle inherit bundle.
  */
 #pragma pack(1)
-typedef struct __libc_SPMInhFHOld
+typedef struct __libc_SPMInhFHDir
 {
     /** The common bundle header. */
     __LIBC_SPMINHFHBHDR Hdr;
     /** Array of flags of Hdr.cHandles entries. */
-    unsigned            afFlags[1];
-} __LIBC_SPMINHFHBSTDOLD;
+    struct
+    {
+        /** The flags. */
+        unsigned            fFlags;
+        /** The inode number. */
+        ino_t               Inode;
+        /** The device number. */
+        dev_t               Dev;
+        /** String table offset of the native path. */
+        unsigned            offNativePath : 24;
+        /** Set if this path is in the unix tree. */
+        unsigned            fInUnixTree : 1;
+        unsigned            u7Reserved : 7;
+        /** The current position. */
+        unsigned            uCurEntry;
+    } aHandles[1];
+} __LIBC_SPMINHFHBDIR;
 #pragma pack()
-/** Pointer to SPM standard filehandle inherit bundle. */
-typedef __LIBC_SPMINHFHBSTDOLD *__LIBC_PSPMINHFHBSTDOLD;
+/** Pointer to SPM directory filehandle inherit bundle. */
+typedef __LIBC_SPMINHFHBDIR *__LIBC_PSPMINHFHBDIR;
 
 /**
@@ -303,5 +323,7 @@
     /** Pointer to the signal part. If NULL default values are assumed. */
     __LIBC_PSPMINHSIG       pSig;
-
+    /** Pointer to strings (filenames++).
+     * All the strings are NULL terminated and referenced by offset. */
+    char                   *pszStrings;
 } __LIBC_SPMINHERIT;
 /** Pointer to inherit data. */
Index: /trunk/src/emx/include/fts.h
===================================================================
--- /trunk/src/emx/include/fts.h	(revision 2322)
+++ /trunk/src/emx/include/fts.h	(revision 2323)
@@ -49,9 +49,5 @@
 	dev_t fts_dev;			/* starting device # */
 	char *fts_path;			/* path for this descent */
-#ifdef __EMX__
-	char *fts_rdir;		        /* path of root */
-#else
 	int fts_rfd;			/* fd for root */
-#endif
 	int fts_pathlen;		/* sizeof(path) */
 	int fts_nitems;			/* elements in the sort array */
@@ -66,7 +62,5 @@
 #define	FTS_SEEDOT	0x020		/* return dot and dot-dot */
 #define	FTS_XDEV	0x040		/* don't cross devices */
-#ifndef __EMX__
 #define	FTS_WHITEOUT	0x080		/* return whiteout information */
-#endif
 #define	FTS_OPTIONMASK	0x0ff		/* valid user option mask */
 
@@ -86,7 +80,5 @@
 	char *fts_path;			/* root path */
 	int fts_errno;			/* errno for this node */
-#ifndef __EMX__
 	int fts_symfd;			/* fd for symlink */
-#endif
 	u_short fts_pathlen;		/* strlen(fts_path) */
 	u_short fts_namelen;		/* strlen(fts_name) */
@@ -113,14 +105,10 @@
 #define	FTS_SL		12		/* symbolic link */
 #define	FTS_SLNONE	13		/* symbolic link without target */
-#ifndef __EMX__
 #define	FTS_W		14		/* whiteout object */
-#endif
 	u_short fts_info;		/* user flags for FTSENT structure */
 
 #define	FTS_DONTCHDIR	 0x01		/* don't chdir .. to the parent */
 #define	FTS_SYMFOLLOW	 0x02		/* followed a symlink to get here */
-#ifndef __EMX__
 #define	FTS_ISW		 0x04		/* this is a whiteout object */
-#endif
 	u_short fts_flags;		/* private flags for FTSENT structure */
 
Index: /trunk/src/emx/include/unistd.h
===================================================================
--- /trunk/src/emx/include/unistd.h	(revision 2322)
+++ /trunk/src/emx/include/unistd.h	(revision 2323)
@@ -441,5 +441,5 @@
 /** @todo char	*ctermid(char *); */		/* XXX ??? */
 void	 encrypt(char *, int);                  /* bird: SuS say it returns void, and so does our implementation */
-/** @todo int	 fchdir(int); */
+int	 fchdir(int);
 /* tcpip: long	 gethostid(void); */
 pid_t	 getpgid(pid_t _pid);       /* bird: SuS say pid_r return. */
Index: /trunk/src/emx/src/lib/bsd/gen/fts.c
===================================================================
--- /trunk/src/emx/src/lib/bsd/gen/fts.c	(revision 2322)
+++ /trunk/src/emx/src/lib/bsd/gen/fts.c	(revision 2323)
@@ -40,5 +40,4 @@
 #endif
 #ifndef __EMX__
-# define HAVE_FCHDIR
 # define IS_SLASH(ch)   ( (ch) == '/' )
 #else
@@ -225,10 +224,6 @@
 	 * descriptor we run anyway, just more slowly.
 	 */
-#ifdef HAVE_FCHDIR
 	if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = _open(".", O_RDONLY, 0)) < 0)
-#else
-        if (!ISSET(FTS_NOCHDIR) && (sp->fts_rdir = getcwd(NULL, 0)) != NULL)
-#endif
-            SET(FTS_NOCHDIR);
+		SET(FTS_NOCHDIR);
 
 	return (sp);
@@ -319,11 +314,6 @@
 	/* Return to original directory, save errno if necessary. */
 	if (!ISSET(FTS_NOCHDIR)) {
-#ifdef HAVE_FCHDIR
 		saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
 		(void)_close(sp->fts_rfd);
-#else
-		saved_errno = chdir(sp->fts_rdir) ? errno : 0;
-                free(sp->fts_rdir); sp->fts_rdir = NULL;
-#endif
 
 		/* Set errno and return. */
@@ -340,5 +330,4 @@
 	return (0);
 }
-
 
 /*
@@ -386,5 +375,4 @@
 		p->fts_info = fts_stat(sp, p, 1);
 		if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
-#ifdef HAVE_FCHDIR
 			if ((p->fts_symfd = _open(".", O_RDONLY, 0)) < 0) {
 				p->fts_errno = errno;
@@ -392,5 +380,4 @@
 			} else
 				p->fts_flags |= FTS_SYMFOLLOW;
-#endif
 		}
 		return (p);
@@ -402,8 +389,6 @@
 		if (instr == FTS_SKIP ||
 		    (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
-#ifdef HAVE_FCHDIR
 			if (p->fts_flags & FTS_SYMFOLLOW)
 				(void)_close(p->fts_symfd);
-#endif
 			if (sp->fts_child) {
 				fts_lfree(sp->fts_child);
@@ -462,9 +447,5 @@
 		 */
 		if (p->fts_level == FTS_ROOTLEVEL) {
-#ifdef HAVE_FCHDIR
 			if (FCHDIR(sp, sp->fts_rfd)) {
-#else
-			if (FCHDIR(sp, sp->fts_rdir)) {
-#endif
 				SET(FTS_STOP);
 				return (NULL);
@@ -484,5 +465,4 @@
 			p->fts_info = fts_stat(sp, p, 1);
 			if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
-#ifdef HAVE_FCHDIR
 				if ((p->fts_symfd =
 				    _open(".", O_RDONLY, 0)) < 0) {
@@ -491,5 +471,4 @@
 				} else
 					p->fts_flags |= FTS_SYMFOLLOW;
-#endif
 			}
 			p->fts_instr = FTS_NOINSTR;
@@ -525,13 +504,8 @@
 	 */
 	if (p->fts_level == FTS_ROOTLEVEL) {
-#ifdef HAVE_FCHDIR
 		if (FCHDIR(sp, sp->fts_rfd)) {
-#else
-		if (FCHDIR(sp, sp->fts_rdir)) {
-#endif
 			SET(FTS_STOP);
 			return (NULL);
 		}
-#ifdef HAVE_FCHDIR
 	} else if (p->fts_flags & FTS_SYMFOLLOW) {
 		if (FCHDIR(sp, p->fts_symfd)) {
@@ -543,7 +517,4 @@
 		}
 		(void)_close(p->fts_symfd);
-#else
-        (void)saved_errno;
-#endif
 	} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
 	    fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
@@ -583,10 +554,6 @@
 {
 	FTSENT *p;
-#ifdef HAVE_FCHDIR
 	int fd;
-#else
-	char *pszRoot;
-        int rc;
-#endif
+
 	if (instr != 0 && instr != FTS_NAMEONLY) {
 		errno = EINVAL;
@@ -640,21 +607,10 @@
 		return (sp->fts_child = fts_build(sp, instr));
 
-#ifdef HAVE_FCHDIR
 	if ((fd = _open(".", O_RDONLY, 0)) < 0)
-#else
-        if ((pszRoot = getcwd(NULL, 0)) == NULL)
-#endif
 		return (NULL);
 	sp->fts_child = fts_build(sp, instr);
-#ifdef HAVE_FCHDIR
 	if (fchdir(fd))
 		return (NULL);
 	(void)_close(fd);
-#else
-        rc = chdir(pszRoot);
-        free(pszRoot);
-        if (rc)
-            return NULL;
-#endif
 	return (sp->fts_child);
 }
@@ -725,5 +681,5 @@
 	 * If being called from fts_read, set the fts_info field.
 	 */
-#ifdef FTS_WHITEOUT
+#if defined(FTS_WHITEOUT) && !defined(__EMX__)
 	if (ISSET(FTS_WHITEOUT))
 		oflag = DTF_NODUP | DTF_REWIND;
@@ -784,9 +740,5 @@
 	cderrno = 0;
 	if (nlinks || type == BREAD) {
-#ifdef HAVE_FCHDIR
 		if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
-#else
-		if (fts_safe_changedir(sp, cur, dirfd(dirp), cur->fts_accpath)) {
-#endif
 			if (nlinks && type == BREAD)
 				cur->fts_errno = errno;
@@ -953,9 +905,5 @@
 	if (descend && (type == BCHILD || !nitems) &&
 	    (cur->fts_level == FTS_ROOTLEVEL ?
-#ifdef HAVE_FCHDIR
 	    FCHDIR(sp, sp->fts_rfd) :
-#else
-	    FCHDIR(sp, sp->fts_rdir) :
-#endif
 	    fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
 		cur->fts_info = FTS_ERR;
@@ -1259,12 +1207,7 @@
 	if (ISSET(FTS_NOCHDIR))
 		return (0);
-#ifdef HAVE_FCHDIR
 	if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0)
 		return (-1);
 	if (_fstat(newfd, &sb)) {
-#else
-        (void)newfd;
-	if (_stat(path, &sb)) {
-#endif
 		ret = -1;
 		goto bail;
@@ -1275,18 +1218,10 @@
 		goto bail;
 	}
-#ifdef HAVE_FCHDIR
 	ret = fchdir(newfd);
-#else
-	ret = chdir(path);
-#endif
 bail:
-#ifdef HAVE_FCHDIR
 	oerrno = errno;
 	if (fd < 0)
 		(void)_close(newfd);
 	errno = oerrno;
-#else
-        (void)oerrno;
-#endif
 	return (ret);
 }
Index: /trunk/src/emx/src/lib/libc.def
===================================================================
--- /trunk/src/emx/src/lib/libc.def	(revision 2322)
+++ /trunk/src/emx/src/lib/libc.def	(revision 2323)
@@ -1948,2 +1948,4 @@
     "__hstrdup" @1946
     "___libc_Back_dirOpenNative" @1947
+    "___libc_Back_fsDirCurrentSetFH" @1948
+    "__std_fchdir" @1949
Index: /trunk/src/emx/src/lib/misc/fchdir.c
===================================================================
--- /trunk/src/emx/src/lib/misc/fchdir.c	(revision 2323)
+++ /trunk/src/emx/src/lib/misc/fchdir.c	(revision 2323)
@@ -0,0 +1,54 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC - fchdir.
+ *
+ * Copyright (c) 2005 knut st. osmundsen <bird@innotek.de>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "libc-alias.h"
+#include <unistd.h>
+#include <errno.h>
+#include <InnoTekLIBC/backend.h>
+#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_MISC
+#include <InnoTekLIBC/logstrict.h>
+
+
+/**
+ * Changes the current directory and drive.
+ *
+ * @returns 0 on success.
+ * @returns -1 and errno on failure.
+ * @param   fh      The handle of an open directory.
+ */
+int _STD(fchdir)(int fh)
+{
+    LIBCLOG_ENTER("fh=%d\n", fh);
+    int rc = __libc_Back_fsDirCurrentSetFH(fh, 1);
+    if (!rc)
+        LIBCLOG_RETURN_INT(0);
+    errno = -rc;
+    LIBCLOG_ERROR_RETURN_INT(-1);
+}
+
Index: /trunk/src/emx/src/lib/sys/__spawnve.c
===================================================================
--- /trunk/src/emx/src/lib/sys/__spawnve.c	(revision 2322)
+++ /trunk/src/emx/src/lib/sys/__spawnve.c	(revision 2323)
@@ -42,4 +42,6 @@
     LIBCLOG_ENTER("\n");
     __LIBC_PSPMINHERIT      pRet = NULL;
+    size_t                  cbStrings = 0;
+    char                   *pszStrings = NULL;
 
     /*
@@ -48,5 +50,5 @@
     size_t                  cbFH;
     __LIBC_PSPMINHFHBHDR    pFH;
-    pFH = __libc_fhInheritPack(&cbFH);
+    pFH = __libc_fhInheritPack(&cbFH, &pszStrings, &cbStrings);
     if (pFH)
     {
@@ -68,11 +70,15 @@
                  * Allocate shared memory.
                  */
-                size_t  cb = sizeof(__LIBC_SPMINHERIT) + ((cbFH + 3) & ~3) + ((cbFS + 3) & ~3) + ((cbSig + 3) & ~3);
+                #define ALIGNIT(cb) (((cb) + 3) & ~3)
+                size_t  cb = sizeof(__LIBC_SPMINHERIT) + ALIGNIT(cbFH) + ALIGNIT(cbFS) + ALIGNIT(cbSig) + ALIGNIT(cbStrings);
                 pRet = __libc_spmAlloc(cb);
                 if (pRet)
                 {
+                    pRet->cb = sizeof(*pRet);
+                    char *p = (char *)(pRet + 1);
+
                     /* fh */
-                    pRet->cb = sizeof(*pRet);
-                    pRet->pFHBundles = (__LIBC_PSPMINHFHBHDR)(pRet + 1);
+                    pRet->pFHBundles = (__LIBC_PSPMINHFHBHDR)p;
+                    p += ALIGNIT(cbFH);
                     memcpy(pRet->pFHBundles, pFH, cbFH);
                     free(pFH);
@@ -81,5 +87,6 @@
                     if (pFS)
                     {
-                        pRet->pFS = (__LIBC_PSPMINHFS)((char *)pRet->pFHBundles + ((cbFH + 3) & ~3));
+                        pRet->pFS = (__LIBC_PSPMINHFS)p;
+                        p += ALIGNIT(cbFS);
                         memcpy(pRet->pFS, pFS, cbFS);
                         free(pFS);
@@ -91,8 +98,22 @@
                     if (pSig)
                     {
-                        pRet->pSig = (__LIBC_PSPMINHSIG)((char *)pRet->pFHBundles + ((cbFH + 3) & ~3) + ((cbFS + 3) & ~3));
+                        pRet->pSig = (__LIBC_PSPMINHSIG)p;
+                        p += ALIGNIT(cbSig);
                         memcpy(pRet->pSig, pSig, cbSig);
                         free(pSig);
                     }
+                    else
+                        pRet->pSig = NULL;
+
+                    /* strings */
+                    if (pszStrings)
+                    {
+                        pRet->pszStrings = p;
+                        /*p += ALIGNIT(cbStrings);*/
+                        memcpy(pRet->pszStrings, pszStrings, cbStrings);
+                        free(pszStrings);
+                    }
+                    else
+                        pRet->pszStrings = NULL;
 
                     /* done! */
@@ -108,4 +129,5 @@
         free(pFH);
     }
+    free(pszStrings);
 
     LIBCLOG_RETURN_P(pRet);
Index: /trunk/src/emx/src/lib/sys/b_dir.c
===================================================================
--- /trunk/src/emx/src/lib/sys/b_dir.c	(revision 2322)
+++ /trunk/src/emx/src/lib/sys/b_dir.c	(revision 2323)
@@ -39,4 +39,5 @@
 #include <limits.h>
 #include <sys/fcntl.h>
+#include <sys/dirent.h>
 #include <emx/umalloc.h>
 #include <emx/io.h>
@@ -54,6 +55,8 @@
 static int dirFileControl(__LIBC_PFH pFH, int fh, int iRequest, int iArg, int *prc);
 static int dirIOControl(__LIBC_PFH pFH, int fh, int iIOControl, int iArg, int *prc);
+static int dirSeek(__LIBC_PFH pFH, int fh, off_t off, int iMethod, off_t *poffNew);
 static int dirSelect(int cFHs, struct fd_set *pRead, struct fd_set *pWrite, struct fd_set *pExcept, struct timeval *tv, int *prc);
 static int dirForkChild(__LIBC_PFH pFH, int fh, __LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation);
+static int dirOpen(const char *pszNativePath, unsigned fLibc, int *pfh, __LIBC_PFHDIR *ppFHDir);
 
 
@@ -73,4 +76,5 @@
     dirFileControl,
     dirIOControl,
+    //dirSeek,
     dirSelect,
     NULL,
@@ -200,4 +204,21 @@
     LIBCLOG_ENTER("pFH=%p fh=%d iIOControl=%d iArg=%d prc=%p\n", (void *)pFH, fh, iIOControl, iArg, (void *)prc);
     LIBCLOG_ERROR_RETURN_INT(-EOPNOTSUPP);
+}
+
+
+/** Seek to a new position in the 'file'.
+ *
+ * @returns 0 on success.
+ * @returns OS/2 error code or negated errno on failure.
+ * @param   pFH         Pointer to the handle structure to operate on.
+ * @param   fh          It's associated filehandle.
+ * @param   off         The offset to seek. The meaning depends on SEEK_.
+ * @param   iMethod     The seek method, any of the SEEK_* macros.
+ * @param   poffNew     Where to store the new file offset.
+ */
+static int dirSeek(__LIBC_PFH pFH, int fh, off_t off, int iMethod, off_t *poffNew)
+{
+    /** @todo Implement reading and seeking. */
+    return -1;
 }
 
@@ -238,5 +259,51 @@
 static int dirForkChild(__LIBC_PFH pFH, int fh, __LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation)
 {
-    /** @todo reopen the handle, same as for duplicate! */
+    switch (enmOperation)
+    {
+        case __LIBC_FORK_OP_FORK_CHILD:
+        {
+            __LIBC_PFHDIR pFHDir = (__LIBC_PFHDIR)pFH;
+
+            /* make pattern */
+            char szNativePath[PATH_MAX + 5];
+            size_t cch = strlen(pFH->pszNativePath);
+            memcpy(szNativePath, pFH->pszNativePath, cch);
+            szNativePath[cch] = '/';
+            szNativePath[cch + 1] = '*';
+            szNativePath[cch + 2] = '\0';
+
+            pFHDir->hDir   = HDIR_CREATE;
+            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;
+            bzero(pFHDir->uBuf.pv, pFHDir->cbBuf);
+
+            int rc = DosFindFirst((PCSZ)szNativePath,
+                                  &pFHDir->hDir,
+                                  FILE_NORMAL | FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED,
+                                  pFHDir->uBuf.pv,
+                                  pFHDir->cbBuf,
+                                  &pFHDir->cFiles,
+                                  pFHDir->fType);
+            if (rc)
+            {
+                pFHDir->hDir = HDIR_CREATE;
+                return rc;
+            }
+            if (pFHDir->uCurEntry)
+            {
+                unsigned uCurEntry = pFHDir->uCurEntry;
+                pFHDir->uCurEntry = 0;
+                dirSeek(&pFHDir->Core, fh, uCurEntry * sizeof(struct dirent), SEEK_SET, NULL);
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
     return 0;
 }
@@ -248,37 +315,18 @@
 
 /**
- * Opens a directory specified by a path already made native.
- *
- * @returns File handle (>=0) on success.
- * @returns negative error code (errno.h) on failure.
+ * Opens a directory.
+ * Internal worker used by the other open/inherit calls.
+ *
+ * @returns 0 on success.
+ * @returns Negated errno on failure.
  * @param   pszNativePath       Pointer to the native path. The buffer must be on stack
  *                              and must have space for 4 extra bytes!
- * @param   fInUnixTree         Set if the native path is in the unix tree.
- * @param   fLibc               The LIBC open() flags.
- * @param   pStat               Pointer to the stat structure for the directory.
- */
-int __libc_Back_dirOpenNative(char *pszNativePath, unsigned fInUnixTree, unsigned fLibc, struct stat *pStat)
-{
-    LIBCLOG_ENTER("pszNativePath=%p:{%s} fInUnixTree=%d fLibc=%#x pStat=%p\n", (void *)pszNativePath, pszNativePath, fInUnixTree, fLibc, (void *)pStat);
-
-    /*
-     * Validate input.
-     */
-    if (!S_ISDIR(pStat->st_mode))
-        LIBCLOG_ERROR_RETURN_INT(-ENOTDIR);
-    if ((fLibc & O_ACCMODE) != O_RDONLY)
-        LIBCLOG_ERROR_RETURN_INT(-EISDIR);
-    if ((fLibc & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))
-        LIBCLOG_ERROR_RETURN_INT(-EEXIST);
-    if (fLibc & (O_TRUNC | O_APPEND))
-        LIBCLOG_ERROR_RETURN_INT(-EPERM);
-    if (fLibc & (O_TRUNC | O_APPEND | O_SIZE))
-        LIBCLOG_ERROR_RETURN_INT(-EINVAL);
-
-    /*
-     * Directory handles are binary, period.
-     */
-    fLibc &= ~O_TEXT;
-    fLibc |= O_BINARY;
+ * @param   pfh                 On input the requested filehandle. -1 means any.
+ *                              On output (success only) the allocated file handle.
+ * @param   ppFHDir             Where to store the handle structure pointer on success.
+ */
+static int dirOpen(const char *pszNativePath, unsigned fLibc, int *pfh, __LIBC_PFHDIR *ppFHDir)
+{
+    LIBC_ASSERT((fLibc & (O_BINARY | __LIBC_FH_TYPEMASK)) == (O_BINARY | F_DIR));
 
     /*
@@ -327,10 +375,8 @@
             if (!rc)
             {
-                int fh;
                 __LIBC_PFH pFH;
-                rc = __libc_FHAllocate(-1, fLibc, sizeof(__LIBC_FHDIR), &gDirOps, &pFH, &fh);
+                rc = __libc_FHAllocate(*pfh, fLibc, sizeof(__LIBC_FHDIR), &gDirOps, &pFH, pfh);
                 if (!rc)
                 {
-                    pFH->Dev            = __libc_back_fsPathCalcInodeAndDev(pszNativePath, &pFH->Inode);
                     pFH->pFsInfo        = __libc_back_fsInfoObjByDev(pFH->Dev);
                     pFH->pszNativePath  = Tmp.Core.pszNativePath;
@@ -343,9 +389,9 @@
                     pFHDir->cFiles      = Tmp.cFiles;
                     pFHDir->cbBuf       = Tmp.cbBuf;
-
+                    pFHDir->uCurEntry   = 0;
+
+                    *ppFHDir = pFHDir;
                     FS_RESTORE();
-                    LIBCLOG_MSG("pFHDir=%p:{.hDir=%#lx, .fType=%d, .cFiles=%ld, .cbBuf=%#x} fh=%d\n",
-                                (void *)pFHDir, pFHDir->hDir, pFHDir->fType, pFHDir->cFiles, pFHDir->cbBuf, fh);
-                    LIBCLOG_RETURN_INT(fh);
+                    return 0;
                 }
 
@@ -361,5 +407,104 @@
     if (rc > 0)
         rc = -__libc_native2errno(rc);
+    return rc;
+}
+
+
+/**
+ * Re-opens a directory we inherited from our parent process.
+ *
+ * @returns 0 on success.
+ * @returns Negated error code (errno.h) on failure.
+ * @param   fh                  The file handle this directory shall have.
+ * @param   pszNativePath       Pointer to the native path.
+ * @param   fInUnixTree         Flag indicating whether the open() call was referencing a path in the unix tree or not.
+ * @param   fFlags              Filehandle flags.
+ * @param   Inode               The inode number of the directory.
+ * @param   Dev                 The device number of the device with the directory.
+ * @param   uCurEntry           The current position.
+ */
+int __libc_back_dirInherit(int fh, const char *pszNativePath, unsigned fInUnixTree, unsigned fFlags, ino_t Inode, dev_t Dev, unsigned uCurEntry)
+{
+    LIBCLOG_ENTER("fh=%d pszNativePath=%p:{%s} fInUnixTree=%d fFlags=%#x Inode=%#llx Dev=%#x uCurEntry=%d\n",
+                  fh, (void *)pszNativePath, pszNativePath, fInUnixTree, fFlags, (unsigned long long)Inode, Dev, uCurEntry);
+
+    /*
+     * Open the directory.
+     */
+    __LIBC_PFHDIR pFHDir;
+    char szNativePath[PATH_MAX + 5];
+    strcpy(szNativePath, pszNativePath);
+    int rc = dirOpen(szNativePath, fFlags, &fh, &pFHDir);
+    if (!rc)
+    {
+        pFHDir->Core.Inode = Inode;
+        pFHDir->Core.Dev   = Dev;
+
+        /*
+         * Seek to the current positions.
+         */
+        if (uCurEntry)
+            dirSeek(&pFHDir->Core, fh, uCurEntry * sizeof(struct dirent), SEEK_SET, NULL);
+
+        LIBCLOG_MSG("pFHDir=%p:{.hDir=%#lx, .fType=%d, .cFiles=%ld, .cbBuf=%#x, .uCurEntry=%d} fh=%d\n",
+                    (void *)pFHDir, pFHDir->hDir, pFHDir->fType, pFHDir->cFiles, pFHDir->cbBuf, pFHDir->uCurEntry, fh);
+        LIBCLOG_RETURN_INT(0);
+    }
     LIBCLOG_ERROR_RETURN_INT(rc);
-}
-
+
+}
+
+
+/**
+ * Opens a directory specified by a path already made native.
+ *
+ * @returns File handle (>=0) on success.
+ * @returns negative error code (errno.h) on failure.
+ * @param   pszNativePath       Pointer to the native path. The buffer must be on stack
+ *                              and must have space for 4 extra bytes!
+ * @param   fInUnixTree         Set if the native path is in the unix tree.
+ * @param   fLibc               The LIBC open() flags.
+ * @param   pStat               Pointer to the stat structure for the directory.
+ */
+int __libc_Back_dirOpenNative(char *pszNativePath, unsigned fInUnixTree, unsigned fLibc, struct stat *pStat)
+{
+    LIBCLOG_ENTER("pszNativePath=%p:{%s} fInUnixTree=%d fLibc=%#x pStat=%p\n", (void *)pszNativePath, pszNativePath, fInUnixTree, fLibc, (void *)pStat);
+
+    /*
+     * Validate input.
+     */
+    if (!S_ISDIR(pStat->st_mode))
+        LIBCLOG_ERROR_RETURN_INT(-ENOTDIR);
+    if ((fLibc & O_ACCMODE) != O_RDONLY)
+        LIBCLOG_ERROR_RETURN_INT(-EISDIR);
+    if ((fLibc & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))
+        LIBCLOG_ERROR_RETURN_INT(-EEXIST);
+    if (fLibc & (O_TRUNC | O_APPEND))
+        LIBCLOG_ERROR_RETURN_INT(-EPERM);
+    if (fLibc & (O_TRUNC | O_APPEND | O_SIZE))
+        LIBCLOG_ERROR_RETURN_INT(-EINVAL);
+
+    /*
+     * Directory handles are binary, period.
+     */
+    fLibc &= ~(O_TEXT | __LIBC_FH_TYPEMASK | __LIBC_FH_FDFLAGS_MASK);
+    fLibc |= O_BINARY | F_DIR;
+
+    /*
+     * Open the directory.
+     */
+    int fh = -1;
+    __LIBC_PFHDIR pFHDir;
+    int rc = dirOpen(pszNativePath, fLibc, &fh, &pFHDir);
+    if (!rc)
+    {
+        pFHDir->Core.Inode = pStat->st_ino;
+        pFHDir->Core.Dev   = pStat->st_dev;
+
+        LIBCLOG_MSG("pFHDir=%p:{.hDir=%#lx, .fType=%d, .cFiles=%ld, .cbBuf=%#x} fh=%d\n",
+                    (void *)pFHDir, pFHDir->hDir, pFHDir->fType, pFHDir->cFiles, pFHDir->cbBuf, fh);
+        LIBCLOG_RETURN_INT(fh);
+    }
+    LIBCLOG_ERROR_RETURN_INT(rc);
+}
+
Index: /trunk/src/emx/src/lib/sys/b_dir.h
===================================================================
--- /trunk/src/emx/src/lib/sys/b_dir.h	(revision 2322)
+++ /trunk/src/emx/src/lib/sys/b_dir.h	(revision 2323)
@@ -65,4 +65,6 @@
     /** The size of the find buffer. */
     unsigned        cbBuf;
+    /** Current entry number (total, for seeking). */
+    unsigned        uCurEntry;
 } __LIBC_FHDIR;
 /** Pointer to the a directory handle. */
@@ -71,4 +73,6 @@
 
 int __libc_Back_dirOpenNative(char *pszNativePath, unsigned fInUnixTree, unsigned fLibc, struct stat *pStat);
+int __libc_back_dirInherit(int fh, const char *pszNativePath, unsigned fInUnixTree, unsigned fFlags,
+                           ino_t Inode, dev_t Dev, unsigned uCurEntry);
 
 
Index: /trunk/src/emx/src/lib/sys/b_fsDirCurrentSet.c
===================================================================
--- /trunk/src/emx/src/lib/sys/b_fsDirCurrentSet.c	(revision 2322)
+++ /trunk/src/emx/src/lib/sys/b_fsDirCurrentSet.c	(revision 2323)
@@ -49,5 +49,4 @@
 {
     LIBCLOG_ENTER("pszPath=%p:{%s} fDrive=%d\n", (void *)pszPath, pszPath, fDrive);
-    FS_VAR();
 
     /*
@@ -73,7 +72,6 @@
          * when in the unix compartement or when fDrive is set.
          */
-        FS_SAVE_LOAD();
+        FS_VAR_SAVE_LOAD();
         int rc = DosSetCurrentDir((PCSZ)&szNativePath[0]);
-        FS_RESTORE();
         if (!rc)
         {
@@ -84,5 +82,5 @@
                     ULONG ulDrive = szNativePath[0] - (szNativePath[0] >= 'A' && szNativePath[0] <= 'Z' ? 'A' - 1 : 'a' -1);
                     rc = DosSetDefaultDisk(ulDrive);
-                    LIBC_ASSERTM(!rc, "DosSetDefaultDisk(%ld) -> %d. unix drive is %c\n", ulDrive, rc, szNativePath[0]);
+                    LIBC_ASSERTM(!rc, "DosSetDefaultDisk(%ld) -> %d. drive is %c\n", ulDrive, rc, szNativePath[0]);
                     rc = 0;             /* ignore this kind of errors. */
                     __libc_gfInUnixTree = fInUnixTree;
@@ -92,4 +90,5 @@
         else
             rc = -__libc_native2errno(rc);
+        FS_RESTORE();
     }
 
Index: /trunk/src/emx/src/lib/sys/b_fsDirCurrentSetFH.c
===================================================================
--- /trunk/src/emx/src/lib/sys/b_fsDirCurrentSetFH.c	(revision 2323)
+++ /trunk/src/emx/src/lib/sys/b_fsDirCurrentSetFH.c	(revision 2323)
@@ -0,0 +1,107 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC SYS Backend - fchdir.
+ *
+ * Copyright (c) 2005 knut st. osmundsen <bird@innotek.de>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "libc-alias.h"
+#define INCL_FSMACROS
+#include <os2emx.h>
+#include "b_fs.h"
+#include "b_dir.h"
+#include <errno.h>
+#include <emx/io.h>
+#include <InnoTekLIBC/backend.h>
+#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_FS
+#include <InnoTekLIBC/logstrict.h>
+
+
+/**
+ * Changes the current directory of the process.
+ *
+ * @returns 0 on success.
+ * @returns Negative error code (errno.h) on failure.
+ * @param   fh          The handle of an open directory.
+ * @param   fDrive      Force a change of the current drive too.
+ */
+int __libc_Back_fsDirCurrentSetFH(int fh, int fDrive)
+{
+    LIBCLOG_ENTER("fh=%d fDrive=%d\n", fh, fDrive);
+    FS_VAR();
+
+    /*
+     * Validate the file handle.
+     */
+    __LIBC_PFH pFH;
+    int rc = __libc_FHEx(fh, &pFH);
+    if (rc)
+        LIBCLOG_ERROR_RETURN_INT(rc);
+    if ((pFH->fFlags & __LIBC_FH_TYPEMASK) != F_DIR)
+        LIBCLOG_ERROR_RETURN_INT(-ENOTDIR);
+    __LIBC_PFHDIR pFHDir = (__LIBC_PFHDIR)pFH;
+
+    /*
+     * Lock the fs global state.
+     */
+    rc = __libc_back_fsMutexRequest();
+    if (rc)
+        LIBCLOG_ERROR_RETURN_INT(rc);
+
+    /*
+     * Change the current directory.
+     *
+     * If we change into or out of the unix root, we must make sure the
+     * default disk is changed too. We'll only do unix chdir behaviour
+     * when in the unix compartement or when fDrive is set.
+     */
+    FS_SAVE_LOAD();
+    rc = DosSetCurrentDir((PCSZ)pFHDir->Core.pszNativePath);
+    if (!rc)
+    {
+        if (fDrive || __libc_gcchUnixRoot)
+        {
+            if (fDrive || pFHDir->fInUnixTree != __libc_gfInUnixTree)
+            {
+                const char *psz = pFHDir->Core.pszNativePath;
+                ULONG ulDrive = psz[0] - (psz[0] >= 'A' && psz[0] <= 'Z' ? 'A' - 1 : 'a' -1);
+                rc = DosSetDefaultDisk(ulDrive);
+                LIBC_ASSERTM(!rc, "DosSetDefaultDisk(%ld) -> %d. drive is %c\n", ulDrive, rc, psz[0]);
+                rc = 0;             /* ignore this kind of errors. */
+                __libc_gfInUnixTree = pFHDir->fInUnixTree;
+            }
+        }
+    }
+    else
+        rc = -__libc_native2errno(rc);
+    FS_RESTORE();
+
+    __libc_back_fsMutexRelease();
+    if (!rc)
+        LIBCLOG_RETURN_INT(rc);
+    LIBCLOG_ERROR_RETURN_INT(rc);
+}
+
Index: /trunk/src/emx/src/lib/sys/filehandles.c
===================================================================
--- /trunk/src/emx/src/lib/sys/filehandles.c	(revision 2322)
+++ /trunk/src/emx/src/lib/sys/filehandles.c	(revision 2323)
@@ -53,5 +53,7 @@
 #include "syscalls.h"
 #include "b_fs.h"
-
+#include "b_dir.h"
+
+#include <InnoTekLIBC/backend.h>
 #define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_INITTERM
 #include <InnoTekLIBC/logstrict.h>
@@ -170,5 +172,5 @@
             __LIBC_PSPMINHFHBHDR    pHdr;
             __LIBC_PSPMINHFHBSTD    pStds;
-            __LIBC_PSPMINHFHBSTDOLD pStdsOld;
+            __LIBC_PSPMINHFHBDIR    pDirs;
             __LIBC_PSPMINHFHBSOCK   pSockets;
             uintptr_t               u;
@@ -189,5 +191,5 @@
                         if (fhAllocate(iFH, u.pStds->aHandles[i].fFlags, sizeof(__LIBC_FH), NULL, &pFH, NULL, 0))
                         {
-                            LIBC_ASSERTM_FAILED("Failed to allocated inherited file handle! iFH=%d\n", iFH);
+                            __libc_Back_panic(0, NULL, "Failed to allocated inherited file handle! iFH=%d\n", iFH);
                             __libc_spmInheritRelease();
                             return -1;
@@ -196,20 +198,25 @@
                         pFH->Dev = u.pStds->aHandles[i].Dev;
                         pFH->pFsInfo = __libc_back_fsInfoObjByDev(pFH->Dev);
-                        pFH->pszNativePath = NULL;
+                        pFH->pszNativePath = u.pStds->aHandles[i].offNativePath
+                            ? _hstrdup(pInherit->pszStrings + u.pStds->aHandles[i].offNativePath) : NULL;
                     }
                     u.pv = &u.pStds->aHandles[c];
                     break;
 
-                case __LIBC_SPM_INH_FHB_TYPE_STANDARD_OLD:
+                case __LIBC_SPM_INH_FHB_TYPE_DIRECTORY:
                     for (i = 0; i < c; i++)
                     {
-                        if (fhAllocate(iFH, u.pStdsOld->afFlags[i], sizeof(__LIBC_FH), NULL, NULL, NULL, 0))
+                        const char *pszPath = u.pDirs->aHandles[i].offNativePath ? pInherit->pszStrings + u.pDirs->aHandles[i].offNativePath : NULL;
+                        int rc = __libc_back_dirInherit(iFH, pszPath, u.pDirs->aHandles[i].fInUnixTree,
+                                                        u.pDirs->aHandles[i].fFlags, u.pDirs->aHandles[i].Inode,
+                                                        u.pDirs->aHandles[i].Dev, u.pDirs->aHandles[i].uCurEntry);
+                        if (rc)
                         {
-                            LIBC_ASSERTM_FAILED("Failed to allocated inherited file handle! iFH=%d\n", iFH);
+                            __libc_Back_panic(0, NULL, "Failed to allocated inherited directory handle! rc=%d iFH=%d path=%s\n", rc, iFH, pszPath);
                             __libc_spmInheritRelease();
                             return -1;
                         }
                     }
-                    u.pv = &u.pStdsOld->afFlags[c];
+                    u.pv = &u.pDirs->aHandles[c];
                     break;
 
@@ -220,6 +227,6 @@
                         if (rc)
                         {
-                            LIBC_ASSERTM_FAILED("Failed to allocated inherited socket (4.4) handle! rc=%d iFH=%d iSocket=%d\n",
-                                                rc, iFH, u.pSockets->aHandles[i].usSocket);
+                            __libc_Back_panic(0, NULL, "Failed to allocated inherited socket (4.4) handle! rc=%d iFH=%d iSocket=%d\n",
+                                              rc, iFH, u.pSockets->aHandles[i].usSocket);
                             __libc_spmInheritRelease();
                             return -1;
@@ -235,6 +242,6 @@
                         if (rc)
                         {
-                            LIBC_ASSERTM_FAILED("Failed to allocated inherited socket (4.3) handle! rc=%d iFH=%d iSocket=%d\n",
-                                                rc, iFH, u.pSockets->aHandles[i].usSocket);
+                            __libc_Back_panic(0, NULL, "Failed to allocated inherited socket (4.3) handle! rc=%d iFH=%d iSocket=%d\n",
+                                              rc, iFH, u.pSockets->aHandles[i].usSocket);
                             __libc_spmInheritRelease();
                             return -1;
@@ -295,4 +302,38 @@
 
 /**
+ * Adds a string to the string table.
+ */
+static inline unsigned fhAddString(const char *pszString, char **ppszStrings, size_t *pcbAlloc, size_t *pcb)
+{
+    if (!pszString)
+        return 0;
+
+    size_t      cb  = strlen(pszString) + 1;
+    unsigned    off = *pcb;
+
+    /* need more space? */
+    if (cb + off > *pcbAlloc)
+    {
+        size_t cbAlloc = (cb + off + !off + 0xfff) & ~0xfff;
+        void *pv = _hrealloc(*ppszStrings, cbAlloc);
+        if (!pv)
+            return 0;
+        *ppszStrings = (char *)pv;
+        *pcbAlloc = cbAlloc;
+        if (!off)
+        {
+            *pcb = off = 1;
+            **ppszStrings = '\0';
+        }
+    }
+
+    /* copy */
+    memcpy(*ppszStrings + off, pszString, cb);
+    *pcb += cb;
+    return off;
+}
+
+
+/**
  * Pack down file handles for exec.
  *
@@ -303,8 +344,9 @@
  * @param   pcb     Where to store the size of the returned data.
  */
-__LIBC_PSPMINHFHBHDR    __libc_fhInheritPack(size_t *pcb)
+__LIBC_PSPMINHFHBHDR    __libc_fhInheritPack(size_t *pcb, char **ppszStrings, size_t *pcbStrings)
 {
     LIBCLOG_ENTER("pcb=%p\n", (void *)pcb);
-    size_t                  cb = 0x1000;
+    size_t                  cbStringAlloc = *pcbStrings;
+    size_t                  cb = 0x2000;
     unsigned                iFH;
     unsigned                cFHs;
@@ -314,4 +356,5 @@
     {
         __LIBC_PSPMINHFHBHDR    pHdr;
+        __LIBC_PSPMINHFHBDIR    pDirs;
         __LIBC_PSPMINHFHBSTD    pStds;
         __LIBC_PSPMINHFHBSOCK   pSockets;
@@ -321,6 +364,7 @@
 
     /*
-     * Allocate buffer.
-     */
+     * Allocate buffers.
+     */
+    LIBC_ASSERT(cb > sizeof(u.pDirs->aHandles[0]) * 256 + sizeof(*u.pDirs));
     pRet = _hmalloc(cb);
     if (!pRet)
@@ -361,7 +405,7 @@
          */
         /* Ensure space for max sized bundle and termination record. */
-        if ( ((uintptr_t)&u.pSockets->aHandles[256] + sizeof(__LIBC_SPMINHFHBHDR) - (uintptr_t)pRet) > cb)
-        {
-            void *pv = realloc(pRet, cb + 0x1000);
+        if ( ((uintptr_t)&u.pDirs->aHandles[256] + sizeof(__LIBC_SPMINHFHBHDR) - (uintptr_t)pRet) > cb )
+        {
+            void *pv = realloc(pRet, cb + 0x2000);
             if (!pv)
             {
@@ -372,5 +416,5 @@
             u.u += (uintptr_t)pv - (uintptr_t)pv;
             pRet = pv;
-            cb += 0x1000;
+            cb += 0x2000;
         }
         /* init the bundle. */
@@ -388,4 +432,5 @@
                     u.pStds->aHandles[i].Inode  = gpapFHs[iFH]->Inode;
                     u.pStds->aHandles[i].Dev    = gpapFHs[iFH]->Dev;
+                    u.pStds->aHandles[i].offNativePath = fhAddString(gpapFHs[iFH]->pszNativePath, ppszStrings, &cbStringAlloc, pcbStrings);
                     /* next */
                     i++; iFH++;
@@ -400,4 +445,40 @@
                 u.pStds->Hdr.cHandles = i;
                 u.pv = &u.pStds->aHandles[i];
+                break;
+            }
+
+            case enmFH_Directory:
+            {
+                u.pDirs->Hdr.uchType = __LIBC_SPM_INH_FHB_TYPE_DIRECTORY;
+                u.pDirs->Hdr.StartFH = iFH;
+                /* walk file handles. */
+                for (i = 0; ; )
+                {
+                    u.pDirs->aHandles[i].fFlags        = gpapFHs[iFH]->fFlags;
+                    u.pDirs->aHandles[i].Inode         = gpapFHs[iFH]->Inode;
+                    u.pDirs->aHandles[i].Dev           = gpapFHs[iFH]->Dev;
+                    LIBC_ASSERT(gpapFHs[iFH]->pszNativePath && *gpapFHs[iFH]->pszNativePath);
+                    u.pDirs->aHandles[i].offNativePath = fhAddString(gpapFHs[iFH]->pszNativePath, ppszStrings, &cbStringAlloc, pcbStrings);
+                    if (!u.pDirs->aHandles[i].offNativePath)
+                    {
+                        _fmutex_release(&gmtx);
+                        free(pRet);
+                        LIBCLOG_ERROR_RETURN_P(NULL);
+                    }
+                    u.pDirs->aHandles[i].fInUnixTree   = !!((__LIBC_PFHDIR)gpapFHs[iFH])->fInUnixTree;
+                    u.pDirs->aHandles[i].uCurEntry     = ((__LIBC_PFHDIR)gpapFHs[iFH])->uCurEntry;
+                    /* next */
+                    i++; iFH++;
+                    if (    i >= 255
+                        ||  iFH >= cFHs
+                        ||  !gpapFHs[iFH]
+                        ||  !gpapFHs[iFH]->pOps
+                        ||  (gpapFHs[iFH]->pOps->enmType != enmType)
+                        ||  (gpapFHs[iFH]->fFlags & ((FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT) | O_NOINHERIT)) )
+                        break;
+                }
+                /* commit the bundle. */
+                u.pStds->Hdr.cHandles = i;
+                u.pv = &u.pDirs->aHandles[i];
                 break;
             }
Index: /trunk/src/emx/src/lib/sys/syscalls.h
===================================================================
--- /trunk/src/emx/src/lib/sys/syscalls.h	(revision 2322)
+++ /trunk/src/emx/src/lib/sys/syscalls.h	(revision 2323)
@@ -126,5 +126,5 @@
 /** @defgroup grp_sys_inherit   Inherit Function
  * @{ */
-__LIBC_PSPMINHFHBHDR    __libc_fhInheritPack(size_t *pcb);
+__LIBC_PSPMINHFHBHDR    __libc_fhInheritPack(size_t *pcb, char **ppszStrings, size_t *pcbStrings);
 void                    __libc_fhInheritDone(void);
 /** @} */
