Index: trunk/src/emx/include/emx/syscalls.h
===================================================================
--- trunk/src/emx/include/emx/syscalls.h	(revision 1533)
+++ trunk/src/emx/include/emx/syscalls.h	(revision 1534)
@@ -61,4 +61,8 @@
     /** File attributes. */
     unsigned char   attr;
+#if 0 /// @todo DT_LNK & d_ino
+    /** Directory entry type. */
+    unsigned char   dt_type;
+#endif
     /** File name */
     char            szName[257];
Index: trunk/src/emx/src/lib/io/lstat.c
===================================================================
--- trunk/src/emx/src/lib/io/lstat.c	(revision 1533)
+++ trunk/src/emx/src/lib/io/lstat.c	(revision 1534)
@@ -1,12 +1,61 @@
-/* lstat.c (libc) -- Copyright (c) 2003 knut st. osmundsen */
+/* $Id$ *//* lstat.c (libc) -- Copyright (c) 2003 knut st. osmundsen */
+/** @file
+ *
+ * lstat().
+ *
+ * Copyright (c) 2004 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 <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <emx/syscalls.h>
+#include <emx/time.h>
+#include <InnoTekLIBC/backend.h>
+#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_MISC
+#include <InnoTekLIBC/logstrict.h>
 
-int _STD(lstat) (const char *name, struct stat *buffer)
+
+int _STD(lstat)(const char *name, struct stat *buffer)
 {
-    return stat(name, buffer);
+    LIBCLOG_ENTER("name=%p:{%s} buffer=%p\n", (void *)name, name, (void *)buffer);
+    int rc = __libc_Back_fsSymlinkStat(name, buffer);
+    if (!rc)
+    {
+        if (!_tzset_flag)
+            tzset();
+        _loc2gmt(&buffer->st_atime, -1);
+        _loc2gmt(&buffer->st_mtime, -1);
+        _loc2gmt(&buffer->st_ctime, -1);
+    }
+    else
+    {
+        errno = -rc;
+        rc = -1;
+    }
+    LIBCLOG_RETURN_INT(rc);
 }
 
+
Index: trunk/src/emx/src/lib/io/stat.c
===================================================================
--- trunk/src/emx/src/lib/io/stat.c	(revision 1533)
+++ trunk/src/emx/src/lib/io/stat.c	(revision 1534)
@@ -2,42 +2,29 @@
 
 #include "libc-alias.h"
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <io.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <emx/io.h>
 #include <emx/time.h>
-#include <emx/syscalls.h>
 #include <InnoTekLIBC/backend.h>
+#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_MISC
+#include <InnoTekLIBC/logstrict.h>
 
 int _STD(stat) (const char *name, struct stat *buffer)
 {
-  int rc = __libc_Back_fsFileStat (name, buffer);
-  if (rc == 0)
+    LIBCLOG_ENTER("name=%p:{%s} buffer=%p\n", (void *)name, name, (void *)buffer);
+    int rc = __libc_Back_fsFileStat (name, buffer);
+    if (!rc)
     {
-      if (!_tzset_flag)
-        tzset ();
-      _loc2gmt (&buffer->st_atime, -1);
-      _loc2gmt (&buffer->st_mtime, -1);
-      _loc2gmt (&buffer->st_ctime, -1);
-      if ((buffer->st_mode & (S_IFMT | ((S_IEXEC >> 6) * 0111))) == S_IFREG)
-        {
-          const char *tmp = _getext (name);
-          if (tmp != NULL &&
-              (stricmp (tmp, ".exe") == 0 ||
-               stricmp (tmp, ".com") == 0 ||
-               stricmp (tmp, ".cmd") == 0 ||
-               stricmp (tmp, ".bat") == 0))
-            buffer->st_mode |= (S_IEXEC >> 6) * 0111;
-        }
+        if (!_tzset_flag)
+            tzset ();
+        _loc2gmt (&buffer->st_atime, -1);
+        _loc2gmt (&buffer->st_mtime, -1);
+        _loc2gmt (&buffer->st_ctime, -1);
     }
-  else
+    else
     {
-      errno = -rc;
-      rc = -1;
+        errno = -rc;
+        rc = -1;
     }
-  return rc;
+    LIBCLOG_RETURN_INT(rc);
 }
Index: trunk/src/emx/src/lib/misc/symlink.c
===================================================================
--- trunk/src/emx/src/lib/misc/symlink.c	(revision 1533)
+++ trunk/src/emx/src/lib/misc/symlink.c	(revision 1534)
@@ -52,5 +52,5 @@
     int rc = __libc_Back_fsSymlinkCreate(target, symlink);
     if (!rc)
-        LIBCLOG_RETURN_INT(!rc);
+        LIBCLOG_RETURN_INT(0);
     errno = -rc;
     LIBCLOG_RETURN_INT(-1);
Index: trunk/src/emx/src/lib/sys/b_fsDirCreate.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_fsDirCreate.c	(revision 1533)
+++ trunk/src/emx/src/lib/sys/b_fsDirCreate.c	(revision 1534)
@@ -71,5 +71,5 @@
     if (!rc)
     {
-        __libc_back_fsSetUnixAttribs(-1, &szNativePath[0], Mode);
+        __libc_back_fsUnixAttribsSet(-1, &szNativePath[0], Mode);
         LIBCLOG_RETURN_INT(0);
     }
Index: trunk/src/emx/src/lib/sys/b_fsFileStatFH.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_fsFileStatFH.c	(revision 1533)
+++ trunk/src/emx/src/lib/sys/b_fsFileStatFH.c	(revision 1534)
@@ -42,4 +42,5 @@
 #include <limits.h>
 #include "syscalls.h"
+#include <InnoTekLIBC/libc.h>
 #include <InnoTekLIBC/backend.h>
 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_IO
@@ -89,85 +90,5 @@
         }
 
-        FS_VAR();
-        FS_SAVE_LOAD();
-        if (pStat->st_mode == S_IFREG)
-        {
-            union
-            {
-                FILESTATUS3     fsts3;
-                FILESTATUS3L    fsts3L;
-            } info;
-#if OFF_MAX > LONG_MAX
-            int     fLarge = 0;
-#endif
-
-            /*
-             * Get file info.
-             */
-#if OFF_MAX > LONG_MAX
-            if (__libc_gpfnDosOpenL)
-            {
-                rc = DosQueryFileInfo(fh, FIL_STANDARDL, &info, sizeof(info.fsts3L));
-                fLarge = 1;
-            }
-            else
-#endif
-                rc = DosQueryFileInfo(fh, FIL_STANDARD, &info, sizeof(info.fsts3));
-            if (rc)
-            {
-                FS_RESTORE();
-                rc = -__libc_native2errno(rc);
-                LIBCLOG_RETURN_INT(rc);
-            }
-
-            /*
-             * Format stats struct.
-             *      We know the info struct layouts!
-             *      Only cbFile, cbFileAlloc and attrFile need be accessed
-             *      using the specific structure.
-             */
-            /* Times: FAT might not return create and access time. */
-            pStat->st_mtime = _sys_p2t(info.fsts3.ftimeLastWrite, info.fsts3.fdateLastWrite);
-            if (    FTIMEZEROP(info.fsts3.ftimeCreation)
-                &&  FDATEZEROP(info.fsts3.fdateCreation))
-                pStat->st_ctime = pStat->st_mtime;
-            else
-                pStat->st_ctime = _sys_p2t(info.fsts3.ftimeCreation, info.fsts3.fdateCreation);
-            if (    FTIMEZEROP(info.fsts3.ftimeLastAccess)
-                &&  FDATEZEROP(info.fsts3.fdateLastAccess))
-                pStat->st_atime = pStat->st_mtime;
-            else
-                pStat->st_atime = _sys_p2t(info.fsts3.ftimeLastAccess, info.fsts3.fdateLastAccess);
-
-#if OFF_MAX > LONG_MAX
-            if (fLarge)
-            {
-                pStat->st_size = info.fsts3L.cbFile;
-                pStat->st_blocks = info.fsts3L.cbFileAlloc / S_BLKSIZE;
-                rc = info.fsts3L.attrFile;
-            }
-            else
-#endif
-            {
-                pStat->st_size = info.fsts3.cbFile;
-                pStat->st_blocks = info.fsts3.cbFileAlloc / S_BLKSIZE;
-                rc = info.fsts3.attrFile;
-            }
-            pStat->st_attr = rc;
-            if (rc & FILE_READONLY)
-                pStat->st_mode |= (S_IREAD >> 6) * 0111;
-            else
-                pStat->st_mode |= ((S_IREAD|S_IWRITE) >> 6) * 0111;
-        }
-        else
-        {
-            if ((pFH->fFlags & O_ACCMODE) == O_RDONLY)
-                pStat->st_mode |= (S_IREAD >> 6) * 0111;
-            else
-                pStat->st_mode |= ((S_IREAD|S_IWRITE) >> 6) * 0111;
-        }
-
-        /* default fake stuff */
-        /** @todo read EAs containing this info! */
+        /* fake unix stuff */
         pStat->st_uid = 0;
         pStat->st_gid = 0;
@@ -179,4 +100,89 @@
         pStat->st_nlink = 1;
         pStat->st_blksize = 4096*12; /* 48KB */
+
+        FS_VAR();
+        FS_SAVE_LOAD();
+        if (pStat->st_mode == S_IFREG)
+        {
+            union
+            {
+                FILESTATUS4     fsts4;
+                FILESTATUS4L    fsts4L;
+            } info;
+#if OFF_MAX > LONG_MAX
+            int     fLarge = 0;
+#endif
+
+            /*
+             * Get file info.
+             */
+#if OFF_MAX > LONG_MAX
+            if (__libc_gpfnDosOpenL)
+            {
+                rc = DosQueryFileInfo(fh, FIL_QUERYEASIZEL, &info, sizeof(info.fsts4L));
+                fLarge = 1;
+            }
+            else
+#endif
+                rc = DosQueryFileInfo(fh, FIL_QUERYEASIZE, &info, sizeof(info.fsts4));
+            if (rc)
+            {
+                FS_RESTORE();
+                rc = -__libc_native2errno(rc);
+                LIBCLOG_RETURN_INT(rc);
+            }
+
+            /*
+             * Format stats struct.
+             *      We know the info struct layouts!
+             *      Only cbFile, cbFileAlloc and attrFile need be accessed
+             *      using the specific structure.
+             */
+            /* Times: FAT might not return create and access time. */
+            pStat->st_mtime = _sys_p2t(info.fsts4.ftimeLastWrite, info.fsts4.fdateLastWrite);
+            if (    FTIMEZEROP(info.fsts4.ftimeCreation)
+                &&  FDATEZEROP(info.fsts4.fdateCreation))
+                pStat->st_ctime = pStat->st_mtime;
+            else
+                pStat->st_ctime = _sys_p2t(info.fsts4.ftimeCreation, info.fsts4.fdateCreation);
+            if (    FTIMEZEROP(info.fsts4.ftimeLastAccess)
+                &&  FDATEZEROP(info.fsts4.fdateLastAccess))
+                pStat->st_atime = pStat->st_mtime;
+            else
+                pStat->st_atime = _sys_p2t(info.fsts4.ftimeLastAccess, info.fsts4.fdateLastAccess);
+
+#if OFF_MAX > LONG_MAX
+            if (fLarge)
+            {
+                pStat->st_size = info.fsts4L.cbFile;
+                pStat->st_blocks = info.fsts4L.cbFileAlloc / S_BLKSIZE;
+                rc = info.fsts4L.attrFile;
+            }
+            else
+#endif
+            {
+                pStat->st_size = info.fsts4.cbFile;
+                pStat->st_blocks = info.fsts4.cbFileAlloc / S_BLKSIZE;
+                rc = info.fsts4.attrFile;
+            }
+            pStat->st_attr = rc;
+            if (rc & FILE_READONLY)
+                pStat->st_mode |= (S_IREAD >> 6) * 0111;
+            else
+                pStat->st_mode |= ((S_IREAD|S_IWRITE) >> 6) * 0111;
+
+            /* If in unix mode we'll check the EAs (if any). */
+            if (    !__libc_gfNoUnix
+                && (fLarge ? info.fsts4L.cbList : info.fsts4.cbList) >= LIBC_UNIX_EA_MIN)
+                __libc_back_fsUnixAttribsGet(fh, 0, pStat);
+        }
+        else
+        {
+            if ((pFH->fFlags & O_ACCMODE) == O_RDONLY)
+                pStat->st_mode |= (S_IREAD >> 6) * 0111;
+            else
+                pStat->st_mode |= ((S_IREAD|S_IWRITE) >> 6) * 0111;
+        }
+
         FS_RESTORE();
     }
Index: trunk/src/emx/src/lib/sys/b_fsNativeFileStat.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_fsNativeFileStat.c	(revision 1533)
+++ trunk/src/emx/src/lib/sys/b_fsNativeFileStat.c	(revision 1534)
@@ -38,6 +38,8 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <stdlib.h>
 #include <limits.h>
 #include "syscalls.h"
+#include <InnoTekLIBC/libc.h>
 #include <InnoTekLIBC/pathrewrite.h>
 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_FS
@@ -59,6 +61,6 @@
     union
     {
-        FILESTATUS3     fsts3;
-        FILESTATUS3L    fsts3L;
+        FILESTATUS4     fsts4;
+        FILESTATUS4L    fsts4L;
     } info;
 #if OFF_MAX > LONG_MAX
@@ -88,10 +90,10 @@
     if (__libc_gpfnDosOpenL)
     {
-        rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_STANDARDL, &info, sizeof(info.fsts3L));
+        rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASIZEL, &info, sizeof(info.fsts4L));
         fLarge = 1;
     }
     else
 #endif
-        rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_STANDARD, &info, sizeof(info.fsts3));
+        rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASIZE, &info, sizeof(info.fsts4));
     FS_RESTORE();
     if (rc)
@@ -108,20 +110,20 @@
      */
     /* Times: FAT might not return create and access time. */
-    pStat->st_mtime = _sys_p2t(info.fsts3.ftimeLastWrite, info.fsts3.fdateLastWrite);
-    if (   FTIMEZEROP(info.fsts3.ftimeCreation)
-        && FDATEZEROP(info.fsts3.fdateCreation))
+    pStat->st_mtime = _sys_p2t(info.fsts4.ftimeLastWrite, info.fsts4.fdateLastWrite);
+    if (   FTIMEZEROP(info.fsts4.ftimeCreation)
+        && FDATEZEROP(info.fsts4.fdateCreation))
         pStat->st_ctime = pStat->st_mtime;
     else
-        pStat->st_ctime = _sys_p2t(info.fsts3.ftimeCreation, info.fsts3.fdateCreation);
-    if (   FTIMEZEROP(info.fsts3.ftimeLastAccess)
-        && FDATEZEROP(info.fsts3.fdateLastAccess))
+        pStat->st_ctime = _sys_p2t(info.fsts4.ftimeCreation, info.fsts4.fdateCreation);
+    if (   FTIMEZEROP(info.fsts4.ftimeLastAccess)
+        && FDATEZEROP(info.fsts4.fdateLastAccess))
         pStat->st_atime = pStat->st_mtime;
     else
-        pStat->st_atime = _sys_p2t(info.fsts3.ftimeLastAccess, info.fsts3.fdateLastAccess);
+        pStat->st_atime = _sys_p2t(info.fsts4.ftimeLastAccess, info.fsts4.fdateLastAccess);
 
 #if OFF_MAX > LONG_MAX
-    ULONG fAttributtes = fLarge ? info.fsts3L.attrFile : info.fsts3.attrFile;
+    ULONG fAttributtes = fLarge ? info.fsts4L.attrFile : info.fsts4.attrFile;
 #else
-    ULONG fAttributtes = info.fsts3.attrFile;
+    ULONG fAttributtes = info.fsts4.attrFile;
 #endif
     pStat->st_attr = fAttributtes;
@@ -138,12 +140,12 @@
         if (fLarge)
         {
-            pStat->st_size = info.fsts3L.cbFile;
-            pStat->st_blocks = info.fsts3L.cbFileAlloc / S_BLKSIZE;
+            pStat->st_size = info.fsts4L.cbFile;
+            pStat->st_blocks = info.fsts4L.cbFileAlloc / S_BLKSIZE;
         }
         else
 #endif
         {
-            pStat->st_size = info.fsts3.cbFile;
-            pStat->st_blocks = info.fsts3.cbFileAlloc / S_BLKSIZE;
+            pStat->st_size = info.fsts4.cbFile;
+            pStat->st_blocks = info.fsts4.cbFileAlloc / S_BLKSIZE;
         }
         pStat->st_mode = S_IFREG;
@@ -152,9 +154,17 @@
         else
             pStat->st_mode |= ((S_IREAD|S_IWRITE) >> 6) * 0111;
+
+        /* Mark .exe, .com, .cmd and .bat as executables. */
+        if ((pStat->st_mode & (S_IFMT | ((S_IEXEC >> 6) * 0111))) == S_IFREG)
+        {
+            const char *pszExt = _getext(pszNativePath);
+            if (   pszExt++
+                && strstr("exeExeEXeEXEExEeXeeXEexEcomComCOmCOMCoMcOmcOMcoMbatBatBAtBATBaTbAtbATbaTcmdCmdCMdCMDCmDcMdcMDcmD",
+                          pszExt))
+                pStat->st_mode |= (S_IEXEC >> 6) * 0111;
+        }
     }
-    /** @todo rewrite this to check for the LIBC.MODE, LIBC.GID,
-     * LIBC.UID, LIBC.RDEV, LIBC.DEV and LIBC.INO EAs.
-     */
-    /* default fake stuff */
+
+    /* fake unix stuff */
     pStat->st_uid = 0;
     pStat->st_gid = 0;
@@ -166,4 +176,8 @@
     pStat->st_nlink = 1;
     pStat->st_blksize = 4096 * 12; /* 48kb */
+    /* If in unix mode we'll check the EAs (if any). */
+    if (    !__libc_gfNoUnix
+        && (fLarge ? info.fsts4L.cbList : info.fsts4.cbList) >= LIBC_UNIX_EA_MIN)
+        __libc_back_fsUnixAttribsGet(-1, pszNativePath, pStat);
 
     LIBCLOG_MSG("st_dev:     %#x\n",  pStat->st_dev);
Index: trunk/src/emx/src/lib/sys/b_ioFileOpen.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_ioFileOpen.c	(revision 1533)
+++ trunk/src/emx/src/lib/sys/b_ioFileOpen.c	(revision 1534)
@@ -180,5 +180,5 @@
         if (   (ulAction == FILE_CREATED)
             && !__libc_gfNoUnix)
-            __libc_back_fsSetUnixAttribs(hFile, NULL, Mode);
+            __libc_back_fsUnixAttribsSet(hFile, NULL, Mode);
 
         /*
Index: trunk/src/emx/src/lib/sys/filefind.c
===================================================================
--- trunk/src/emx/src/lib/sys/filefind.c	(revision 1533)
+++ trunk/src/emx/src/lib/sys/filefind.c	(revision 1534)
@@ -40,5 +40,5 @@
 }
 
-/* Build a `struct _find' structure from a FILEFINDBUF3 structure and
+/* Build a `struct _find' structure from a FILEFINDBUF4 structure and
    move to the next one. */
 
@@ -54,6 +54,6 @@
     {
         const char             *pch;
-        const FILEFINDBUF3     *pFindbuf3;
-        const FILEFINDBUF3L    *pFindbuf3L;
+        const FILEFINDBUF4     *pFindbuf4;
+        const FILEFINDBUF4L    *pFindbuf4L;
     } u;
     u.pch = pFD->pchNext;
@@ -76,19 +76,28 @@
      *      cbFile, cbFileAlloc, attrFile, cchName, achName.
      */
-    fp->time = XUSHORT(u.pFindbuf3->ftimeLastWrite);
-    fp->date = XUSHORT(u.pFindbuf3->fdateLastWrite);
+    fp->time = XUSHORT(u.pFindbuf4->ftimeLastWrite);
+    fp->date = XUSHORT(u.pFindbuf4->fdateLastWrite);
 #if OFF_MAX > LONG_MAX
-    if (pFD->fType == FIL_STANDARDL)
-    {
-        fp->cbFile = u.pFindbuf3L->cbFile;
-        fp->attr   = (unsigned char)u.pFindbuf3L->attrFile;
-        strcpy(fp->szName, &u.pFindbuf3L->achName[0]);
+    if (pFD->fType == FIL_QUERYEASIZEL)
+    {
+        fp->cbFile = u.pFindbuf4L->cbFile;
+        fp->attr   = (unsigned char)u.pFindbuf4L->attrFile;
+        strcpy(fp->szName, &u.pFindbuf4L->achName[0]);
+#if 0 //@todo DT_LNK
+        if (u.pFindbuf4L->cbList >= LIBC_UNIX_EA_MIN
+            && find_is_symlink(u.pFindbuf4L->achName))
+            fp->attr |= 0xf0;
+#endif
     }
     else
 #endif
     {
-        fp->cbFile = u.pFindbuf3->cbFile;
-        fp->attr   = (unsigned char)u.pFindbuf3->attrFile;
-        strcpy(fp->szName, &u.pFindbuf3->achName[0]);
+        fp->cbFile = u.pFindbuf4->cbFile;
+        fp->attr   = (unsigned char)u.pFindbuf4->attrFile;
+        strcpy(fp->szName, &u.pFindbuf4->achName[0]);
+        if (u.pFindbuf4L->cbList >= LIBC_UNIX_EA_MIN)
+        {
+
+        }
     }
 
@@ -96,7 +105,7 @@
      * Next entry.
      */
-    if (pFD->cFiles && u.pFindbuf3->oNextEntryOffset)
-    {
-        pFD->pchNext = u.pch + u.pFindbuf3->oNextEntryOffset;
+    if (pFD->cFiles && u.pFindbuf4->oNextEntryOffset)
+    {
+        pFD->pchNext = u.pch + u.pFindbuf4->oNextEntryOffset;
         pFD->cFiles--;
     }
@@ -124,5 +133,5 @@
     LIBCLOG_ENTER("pszName=%s attr=%#x fp=%p\n", pszName, attr, (void *)fp);
     int                 rc;
-    int                 cch;
+    char                szNativePath[PATH_MAX];
     struct find_data   *pFD = &__libc_threadCurrent()->b.sys.fd;
     FS_VAR();
@@ -131,22 +140,9 @@
      * Rewrite the specified file path.
      */
-    cch = __libc_PathRewrite(pszName, NULL, 0);
-    if (cch > 0)
-    {
-        char *pszRewritten = alloca(cch);
-        if (!pszRewritten)
-        {
-            errno = ENOMEM;
-            LIBCLOG_RETURN_INT(-1);
-        }
-        cch = __libc_PathRewrite(pszName, pszRewritten, cch);
-        if (cch > 0)
-            pszName = pszRewritten;
-        /* else happens when someone changes the rules between the two calls. */
-        else if (cch < 0)
-        {
-            errno = EAGAIN;             /* non-standard, I'm sure. */
-            LIBCLOG_RETURN_INT(-1);
-        }
+    rc = __libc_back_fsResolve(pszName, BACKFS_FLAGS_RESOLVE_FULL, &szNativePath[0], NULL);
+    if (rc)
+    {
+        errno = -rc;
+        return -1;
     }
 
@@ -171,9 +167,9 @@
     pFD->cFiles = sizeof(pFD->achBuffer) / 40;
 #if OFF_MAX > LONG_MAX
-    pFD->fType = __libc_gpfnDosOpenL ? FIL_STANDARDL : FIL_STANDARD;
-    if (pFD->fType == FIL_STANDARDL)  /* the L version is buggy!! Make sure there is enough space. */
-        pFD->cFiles = sizeof(pFD->achBuffer) / sizeof(FILEFINDBUF3L);
+    pFD->fType = __libc_gpfnDosOpenL ? FIL_QUERYEASIZEL : FIL_QUERYEASIZE;
+    if (pFD->fType == FIL_QUERYEASIZEL)  /* the L version is buggy!! Make sure there is enough space. */
+        pFD->cFiles = sizeof(pFD->achBuffer) / sizeof(FILEFINDBUF4L);
 #else
-    pFD->fType = FIL_STANDARD;
+    pFD->fType = FIL_QUERYEASIZE;
 #endif
     FS_SAVE_LOAD();
@@ -234,6 +230,6 @@
     {
         pFD->cFiles = sizeof(pFD->achBuffer) / 40;
-        if (pFD->fType == FIL_STANDARDL)  /* the L version is buggy!! Make sure there is enough space. */
-            pFD->cFiles = sizeof(pFD->achBuffer) / sizeof(FILEFINDBUF3L);
+        if (pFD->fType == FIL_QUERYEASIZEL)  /* the L version is buggy!! Make sure there is enough space. */
+            pFD->cFiles = sizeof(pFD->achBuffer) / sizeof(FILEFINDBUF4L);
         FS_SAVE_LOAD();
         rc = DosFindNext(pFD->hdir, &pFD->achBuffer[0], sizeof(pFD->achBuffer), &pFD->cFiles);
Index: trunk/src/emx/src/lib/sys/fs.c
===================================================================
--- trunk/src/emx/src/lib/sys/fs.c	(revision 1533)
+++ trunk/src/emx/src/lib/sys/fs.c	(revision 1534)
@@ -40,4 +40,5 @@
 #include <errno.h>
 #include <386/builtin.h>
+#include <sys/stat.h>
 #include <sys/fmutex.h>
 #include <emx/startup.h>
@@ -84,8 +85,33 @@
 
 /** Symlink EA name. */
-#define EA_SYMLINK  "LIBC.SYMLINK"
-
-/** Symlink ea name. */
-const char __libc_gszSymlinkEA[] = EA_SYMLINK;
+#define EA_SYMLINK          "LIBC.SYMLINK"
+/** Symlink EA owner. */
+#define EA_UID              "LIBC.UID"
+/** Symlink EA group. */
+#define EA_GID              "LIBC.GID"
+/** Symlink EA mode. */
+#define EA_MODE             "LIBC.MODE"
+/** Symlink EA i-node number. */
+#define EA_INO              "LIBC.INO"
+/** Symlink EA rdev number. */
+#define EA_RDEV             "LIBC.RDEV"
+/** Symlink EA gen number. */
+#define EA_GEN              "LIBC.GEN"
+
+/** Symlink EA name. */
+static const char __libc_gszSymlinkEA[] = EA_SYMLINK;
+/** UID EA name. */
+static const char __libc_gszUidEA[]     = EA_UID;
+/** GID EA name. */
+static const char __libc_gszGidEA[]     = EA_GID;
+/** Mode EA name. */
+static const char __libc_gszModeEA[]    = EA_MODE;
+/** Ino EA name. */
+static const char __libc_gszInoEA[]     = EA_INO;
+/** RDev EA name. */
+static const char __libc_gszRDevEA[]    = EA_RDEV;
+/** Gen(eration) EA name. */
+static const char __libc_gszGenEA[]     = EA_GEN;
+
 /* GEA2LIST Structure, just a bit more conveniently laid out.. */
 static const struct
@@ -95,10 +121,54 @@
     BYTE    cbName;
     CHAR    szName[sizeof(EA_SYMLINK)];
-} gSymlinkGEA2List =
-{
-    sizeof(gSymlinkGEA2List),
+} gGEA2ListSymlink =
+{
+    sizeof(gGEA2ListSymlink),
     0,
     sizeof(EA_SYMLINK) - 1,
     EA_SYMLINK
+};
+
+/* GEA2LIST Structures, just a bit more conveniently laid out.. */
+static const struct GEA2LISTUNIXATTRIBS
+{
+    ULONG   cbList;
+
+    ULONG   offSymlink;
+    BYTE    cbSymlinkName;
+    CHAR    szSymlinkName[sizeof(EA_SYMLINK)];
+
+    ULONG   offUID;
+    BYTE    cbUIDName;
+    CHAR    szUIDName[sizeof(EA_UID)];
+
+    ULONG   offGID;
+    BYTE    cbGIDName;
+    CHAR    szGIDName[sizeof(EA_GID)];
+
+    ULONG   offMode;
+    BYTE    cbModeName;
+    CHAR    szModeName[sizeof(EA_MODE)];
+
+    ULONG   offINO;
+    BYTE    cbINOName;
+    CHAR    szINOName[sizeof(EA_INO)];
+
+    ULONG   offRDev;
+    BYTE    cbRDevName;
+    CHAR    szRDevName[sizeof(EA_RDEV)];
+
+    ULONG   offGen;
+    BYTE    cbGenName;
+    CHAR    szGenName[sizeof(EA_GEN)];
+} gGEA2ListUnixAttribs =
+{
+    sizeof(gGEA2ListUnixAttribs),
+    offsetof(struct GEA2LISTUNIXATTRIBS, offUID)  - offsetof(struct GEA2LISTUNIXATTRIBS, offSymlink), sizeof(EA_SYMLINK) - 1, EA_SYMLINK,
+    offsetof(struct GEA2LISTUNIXATTRIBS, offGID)  - offsetof(struct GEA2LISTUNIXATTRIBS, offUID),     sizeof(EA_UID) - 1,     EA_UID,
+    offsetof(struct GEA2LISTUNIXATTRIBS, offMode) - offsetof(struct GEA2LISTUNIXATTRIBS, offGID),     sizeof(EA_GID) - 1,     EA_GID,
+    offsetof(struct GEA2LISTUNIXATTRIBS, offINO)  - offsetof(struct GEA2LISTUNIXATTRIBS, offMode),    sizeof(EA_MODE) - 1,    EA_MODE,
+    offsetof(struct GEA2LISTUNIXATTRIBS, offRDev) - offsetof(struct GEA2LISTUNIXATTRIBS, offINO),     sizeof(EA_INO) - 1,     EA_INO,
+    offsetof(struct GEA2LISTUNIXATTRIBS, offGen)  - offsetof(struct GEA2LISTUNIXATTRIBS, offRDev),    sizeof(EA_RDEV) - 1,    EA_RDEV,
+    0,                                                                                                sizeof(EA_GEN) - 1,     EA_GEN
 };
 
@@ -316,5 +386,5 @@
     char   *pachBuffer = (char *)((uintptr_t)&_achBuffer[3] & ~3);
     EAOP2   EaOp;
-    EaOp.fpGEA2List = (PGEA2LIST)&gSymlinkGEA2List;
+    EaOp.fpGEA2List = (PGEA2LIST)&gGEA2ListSymlink;
     EaOp.fpFEA2List = (PFEA2LIST)pachBuffer;
     EaOp.oError     = 0;
@@ -749,5 +819,5 @@
          */
         int cchTmp = __libc_PathRewrite(pszUserPath, szTmp, sizeof(szTmp));
-        if (cchTmp)
+        if (cchTmp > 0)
         {
             /*
@@ -968,5 +1038,5 @@
             {
                 EAOP2   EaOp;
-                EaOp.fpGEA2List = (PGEA2LIST)&gSymlinkGEA2List;
+                EaOp.fpGEA2List = (PGEA2LIST)&gGEA2ListSymlink;
                 EaOp.fpFEA2List = (PFEA2LIST)pachBuffer;
                 EaOp.oError     = 0;
@@ -1140,9 +1210,9 @@
  * @param   hFile           File handle to the newly created fs object. If no
  *                          handle handy, set to -1.
- * @param   pszNativePath   Native path of the newly created fs object. If
+ * @param   pszNativePath   Native path to the newly created fs object. If
  *                          handle is give this will be ignored.
  * @param   mode            The specified file permission mode mask.
  */
-int __libc_back_fsSetUnixAttribs(int hFile, const char *pszNativePath, mode_t mode)
+int __libc_back_fsUnixAttribsSet(int hFile, const char *pszNativePath, mode_t mode)
 {
     /* later */
@@ -1150,2 +1220,93 @@
 }
 
+/**
+ * Reads the unix EAs for a file which is being stat'ed.
+ *
+ * @returns 0 on success.
+ * @returns Negative errno on failure.
+ * @param   hFile           File handle to the fs object. If no handle handy, set to -1.
+ * @param   pszNativePath   Native path to the fs object. If handle is give this will be ignored.
+ * @param   pStat           Pointer to the stat buffer.
+ *                          The buffer is only updated if and with the EAs we find,
+ *                          so the caller must fill the fields with defaults before
+ *                          calling this function.
+ */
+int __libc_back_fsUnixAttribsGet(int hFile, const char *pszNativePath, struct stat *pStat)
+{
+    LIBCLOG_ENTER("hFile=%d pszNativePath=%p:{%s} pStat=%p\n", hFile, (void *)pszNativePath, pszNativePath, (void *)pStat);
+
+    /* Try come up with an accurate max estimate of a maximum result. */
+    char    achBuffer[sizeof(gGEA2ListUnixAttribs) + 7 * (sizeof(USHORT) * 2 + sizeof(BYTE)) + CCHMAXPATH + 6 * sizeof(uint32_t) + 0x30];
+    char   *pachBuffer = (char *)((uintptr_t)&achBuffer[3] & ~3);
+    EAOP2   EaOp2;
+    int     rc;
+
+    /*
+     * Issue the query.
+     */
+    EaOp2.fpGEA2List = (PGEA2LIST)&gGEA2ListUnixAttribs;
+    EaOp2.fpFEA2List = (PFEA2LIST)pachBuffer;
+    EaOp2.oError     = 0;
+    EaOp2.fpFEA2List->cbList = sizeof(achBuffer) - 4;
+    if (hFile >= 0)
+        rc = DosQueryFileInfo(hFile, FIL_QUERYEASFROMLIST, &EaOp2, sizeof(EaOp2));
+    else
+        rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASFROMLIST, &EaOp2, sizeof(EaOp2));
+    if (rc)
+    {
+        LIBC_ASSERTM_FAILED("Bogus EAs? rc=%d oError=%ld\n", rc, EaOp2.oError);
+        rc = -__libc_native2errno(rc);
+        LIBCLOG_RETURN_INT(rc);
+    }
+    if (EaOp2.fpFEA2List->cbList < LIBC_UNIX_EA_MIN)
+        LIBCLOG_RETURN_INT(rc);
+
+    /*
+     * Parse the result.
+     */
+    PFEA2   pFea2 = &EaOp2.fpFEA2List->list[0];
+    for (;;)
+    {
+        if (pFea2->cbValue > 0)
+        {
+#define COMPARE_EANAME(name) (pFea2->cbName == sizeof(name) - 1 && !memcmp(name, pFea2->szName, sizeof(name) - 1))
+            if (COMPARE_EANAME(__libc_gszSymlinkEA))
+                pStat->st_mode = (pStat->st_mode & ~S_IFMT) | S_IFLNK;
+            else
+            {
+                PUSHORT pusType = (PUSHORT)((char *)pFea2 + pFea2->cbName);
+                if (pusType[0] == EAT_BINARY && pusType[1] == sizeof(uint32_t))
+                {
+                    uint32_t u32 = *(uint32_t *)&pusType[2];
+                    if (COMPARE_EANAME(__libc_gszUidEA))
+                        pStat->st_uid  = u32;
+                    else if (COMPARE_EANAME(__libc_gszGidEA))
+                        pStat->st_gid  = u32;
+                    else if (COMPARE_EANAME(__libc_gszModeEA))
+                        pStat->st_mode = u32;
+                    else if (COMPARE_EANAME(__libc_gszInoEA))
+                        pStat->st_ino  = u32;
+                    else if (COMPARE_EANAME(__libc_gszRDevEA))
+                        pStat->st_rdev = u32;
+                    else if (COMPARE_EANAME(__libc_gszGenEA))
+                        /* pStat->st_gen  = u32 - not implemented */;
+                    else
+                        LIBC_ASSERTM_FAILED("Huh?!? got an ea named '%s', namelen=%d!\n", pFea2->szName, pFea2->cbName);
+                }
+                else
+                    LIBC_ASSERTM_FAILED("Invalid LIBC EA! %s type=%#x len=%#x, expected type=%#x and len=%#x.\n",
+                                        pFea2->szName, pusType[0], pusType[1], EAT_BINARY, sizeof(uint32_t));
+            }
+#undef COMPARE_EANAME
+        }
+
+        /* next */
+        if (pFea2->oNextEntryOffset <= sizeof(FEA2))
+            break;
+        pFea2 = (PFEA2)((uintptr_t)pFea2 + pFea2->oNextEntryOffset);
+    }
+
+    LIBCLOG_RETURN_INT(0);
+}
+
+
Index: trunk/src/emx/src/lib/sys/fs.h
===================================================================
--- trunk/src/emx/src/lib/sys/fs.h	(revision 1533)
+++ trunk/src/emx/src/lib/sys/fs.h	(revision 1534)
@@ -46,4 +46,8 @@
 /** The current umask of the process. */
 extern mode_t __libc_gfsUMask;
+
+/** The minimum EA size of a file for it to possibly contain any LIBC Unix EAs. */
+#define LIBC_UNIX_EA_MIN    (1 + 1 + 2 + sizeof("LIBC.???") + 2 + 2 + sizeof(uint32_t))
+
 
 #ifdef _OS2EMX_H
@@ -132,5 +136,19 @@
  * @param   mode            The specified file permission mode mask.
  */
-int __libc_back_fsSetUnixAttribs(int hFile, const char *pszNativePath, mode_t mode);
+int __libc_back_fsUnixAttribsSet(int hFile, const char *pszNativePath, mode_t mode);
+
+/**
+ * Reads the unix EAs for a file which is being stat'ed.
+ *
+ * @returns 0 on success.
+ * @returns Negative errno on failure.
+ * @param   hFile           File handle to the fs object. If no handle handy, set to -1.
+ * @param   pszNativePath   Native path to the fs object. If handle is give this will be ignored.
+ * @param   pStat           Pointer to the stat buffer.
+ *                          The buffer is only updated if and with the EAs we find,
+ *                          so the caller must fill the fields with defaults before
+ *                          calling this function.
+ */
+int __libc_back_fsUnixAttribsGet(int hFile, const char *pszNativePath, struct stat *pStat);
 
 
