Index: trunk/src/emx/ChangeLog.LIBC
===================================================================
--- trunk/src/emx/ChangeLog.LIBC	(revision 2089)
+++ trunk/src/emx/ChangeLog.LIBC	(revision 2090)
@@ -1,3 +1,28 @@
 /* $Id$ */
+
+2005-06-26: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - libc:
+        o Added [__]isinf[fl] which seems to have been mislaid during the
+          math source import.
+        o Rewrote the libcXXXX.dll install rule to not play with emxload since
+          emxload sticks around when first loaded.
+        o Made unsetenv() cause tzset reload just like putenv() and setenv().
+        o Changed putenv() behaviour for removal (no '=' in input) to be identical
+          to unsetenv(). This solves duplicate variable testcase.
+        o Changed filestreams opened for both reading and writing to switch
+          more willingly between read and write mode.
+        o Made sscan() return EOF on EOF.
+        o Made sscan() skip blanks in input for '%%'.
+        o Implemented the stdio_unlocked stuff with BSD and GLIBC extension.
+          TODO: Require a new locktype which support recursive usage! Currently
+                a hack using 8 free flag bits is used.
+        o Corrected realpath() behaviour to return the path up to the failure
+          point on error. _realrealpath() also does this now.
+          (This also saves us a temp buffer and a copy of the result.)
+        o Fixed a bug in the handling of ".." in the path resolver.
+        o Extended that path resolver to check the directoryness of the input
+          according to flags and any trailing slashes.
+        o Change the path resolver to be very strict about UNC - UNC have exactly
+          two slashes at the start of the path.
 
 2005-06-25: knut st. osmundsen <bird-gccos2-spam@anduin.net>
Index: trunk/src/emx/include/emx/io.h
===================================================================
--- trunk/src/emx/include/emx/io.h	(revision 2089)
+++ trunk/src/emx/include/emx/io.h	(revision 2090)
@@ -8,4 +8,5 @@
 #include <InnoTekLIBC/fork.h>
 #include <alloca.h>
+#include <stdio.h>
 
 __BEGIN_DECLS
@@ -148,4 +149,8 @@
 #define _IONOCLOSEALL   0x00020000
 
+/** This bit is set when the stream is locked by flockfile() or ftrylockfile().
+ * !!TEMPORARY HACK!!
+ * @todo replace the fmutex on the stream with a recursive lock! */
+#define _IOLOCKED       0xff000000
 
 #define _FLUSH_FLUSH  (-1)
@@ -192,5 +197,4 @@
 
 #if defined (_SYS_FMUTEX_H)
-
 /* This semaphore (defined in app/stdio.c) protects _streamv[].  Only
    concurrent access by _newstream(), _setmore(), and freopen() in
@@ -204,21 +208,90 @@
 #define STREAMV_LOCK    _fmutex_checked_request(&_streamv_fmutex, _FMR_IGNINT)
 #define STREAMV_UNLOCK  _fmutex_checked_release(&_streamv_fmutex)
-
-#define STREAM_LOCK(f) \
-  ((f)->__uVersion != _FILE_STDIO_VERSION ? __stream_abort (f, "version error") \
-   : _fmutex_request(&(f)->__u.__fsem, _FMR_IGNINT) != 0 \
-   ? __stream_abort (f, "fmutex request") : 0)
-
-#define STREAM_UNLOCK(f) \
-  (_fmutex_release(&(f)->__u.__fsem) != 0 ? __stream_abort (f, "fmutex release") : (void)0)
-
-#define STREAM_LOCK_NOWAIT(f) \
-  (((f)->__uVersion == _FILE_STDIO_VERSION || __stream_abort (f, "version error")) && _fmutex_request(&(f)->__u.__fsem, _FMR_NOWAIT) == 0)
-
-#define STREAM_UNLOCKED(f) ((f)->__uVersion == _FILE_STDIO_VERSION && _fmutex_available(&(f)->__u.__fsem))
+#endif /* _SYS_FMUTEX_H */
+
+#if defined (__FILE_FSEM_DECLARED)
 
 int __stream_abort(struct _FILE *f, const char *pszMsg);
 
-#endif /* defined (_SYS_FMUTEX_H) */
+static int __inline__ stream_validate(struct _FILE *stream)
+{
+    if (stream->__uVersion != _FILE_STDIO_VERSION)
+    {
+        __stream_abort(stream, "version error");
+        return 0;
+    }
+    return 1;
+}
+
+static int __inline__ stream_lock(struct _FILE *stream)
+{
+    if (!stream_validate(stream))
+        return 0;
+    if (   !(stream->_flags & _IOLOCKED)
+        || !_fmutex_is_owner(&stream->__u.__fsem))
+    {
+        if (_fmutex_request(&stream->__u.__fsem, _FMR_IGNINT) != 0)
+        {
+            __stream_abort(stream, "fmutex_request failed");
+            return 0;
+        }
+        stream->_flags = 0x01000000 | (stream->_flags & ~_IOLOCKED);
+    }
+    else
+        stream->_flags = ((stream->_flags & _IOLOCKED) + 0x01000000) | (stream->_flags & ~_IOLOCKED);
+    return 1;
+}
+
+static int __inline__ stream_trylock(struct _FILE *stream)
+{
+    if (!stream_validate(stream))
+        return 0;
+    if (   !(stream->_flags & _IOLOCKED)
+        || !_fmutex_is_owner(&stream->__u.__fsem))
+    {
+        if (_fmutex_request(&stream->__u.__fsem, _FMR_NOWAIT) != 0)
+        {
+            __stream_abort(stream, "fmutex_request failed");
+            return 0;
+        }
+        stream->_flags = 0x01000000 | (stream->_flags & ~_IOLOCKED);
+    }
+    else
+        stream->_flags = ((stream->_flags & _IOLOCKED) + 0x01000000) | (stream->_flags & ~_IOLOCKED);
+    return 1;
+}
+
+static int __inline__ stream_unlock(struct _FILE *stream)
+{
+    if (!stream_validate(stream))
+        return 0;
+    if (!(stream->_flags & _IOLOCKED))
+    {
+        __stream_abort(stream, "unlock, 0 count");
+        return 0;
+    }
+#ifdef __LIBC_STRICT
+    if (!_fmutex_is_owner(&stream->__u.__fsem))
+    {
+        __stream_abort(stream, "unlock, not owner");
+        return 0;
+    }
+#endif
+    stream->_flags = ((stream->_flags & _IOLOCKED) - 0x01000000) | (stream->_flags & ~_IOLOCKED);
+    if (   !(stream->_flags & _IOLOCKED)
+        && _fmutex_release(&stream->__u.__fsem) != 0)
+    {
+        __stream_abort(stream, "fmutex_release failed");
+        return 0;
+    }
+    return 1;
+}
+
+#define STREAM_LOCK(f)          stream_lock(f)
+#define STREAM_UNLOCK(f)        stream_unlock(f)
+#define STREAM_LOCK_NOWAIT(f)   stream_trylock(f)
+#define STREAM_UNLOCKED(f)      ((f)->__uVersion == _FILE_STDIO_VERSION && _fmutex_available(&(f)->__u.__fsem))
+
+#endif /* __FILE_FSEM_DECLARED */
 
 struct __libc_FileHandle;
@@ -434,8 +507,6 @@
 int _flushstream (struct _FILE *, int);
 void _closestream (struct _FILE *);
-int _fflush_nolock (struct _FILE *);
-int _fseek_nolock (struct _FILE *, off_t, int);
-off_t _ftell_nolock (struct _FILE *);
-size_t _fwrite_nolock (const void *, size_t, size_t, struct _FILE *);
+int _fseek_unlocked (struct _FILE *, off_t, int);
+off_t _ftello_unlocked (struct _FILE *);
 int _input (struct _FILE *, __const__ char *, char *);
 struct _FILE *_newstream (void);
Index: trunk/src/emx/include/stdio.h
===================================================================
--- trunk/src/emx/include/stdio.h	(revision 2089)
+++ trunk/src/emx/include/stdio.h	(revision 2090)
@@ -200,4 +200,6 @@
     {
 #if defined (_SYS_FMUTEX_H)
+#define __FILE_FSEM_DECLARED
+        /** @todo replace this by a nested lock construct, see flockfile(). */
         _fmutex   __fsem;
 #endif
@@ -287,20 +289,10 @@
 long	 ftell(FILE *);
 size_t	 fwrite(const void * __restrict, size_t, size_t, FILE * __restrict);
-#if 0                                   /* bird: emx */
 int	 getc(FILE *);
-#else                                   /* bird: emx */
-/** @todo: Check the standard, if this is correct or not. declaration might be required. */
-#define getc(s)   fgetc(s)              /* bird: emx */
-#endif                                  /* bird: emx */
 int	 getchar(void);
 char	*gets(char *);
 void	 perror(const char *);
 int	 printf(const char * __restrict, ...);
-#if 0                                   /* bird: emx */
 int	 putc(int, FILE *);
-#else                                   /* bird: emx */
-/** @todo: Check the standard, if this is correct or not. declaration might be required. */
-#define putc(c,s) fputc(c,s)            /* bird: emx */
-#endif                                  /* bird: emx */
 int	 putchar(int);
 int	 puts(const char *);
@@ -356,7 +348,7 @@
 
 #if __POSIX_VISIBLE >= 199506
-/** @todo int	 ftrylockfile(FILE *); */
-/** @todo void	 flockfile(FILE *); */
-/** @todo void	 funlockfile(FILE *); */
+int	 ftrylockfile(FILE *);
+void	 flockfile(FILE *);
+void	 funlockfile(FILE *);
 
 /*
@@ -364,14 +356,23 @@
  * requires functions as well.
  */
-/** @todo int	 getc_unlocked(FILE *); */
-/** @todo int	 getchar_unlocked(void); */
-/** @todo int	 putc_unlocked(int, FILE *); */
-/** @todo int	 putchar_unlocked(int); */
+int	 getc_unlocked(FILE *);
+int	 getchar_unlocked(void);
+int	 putc_unlocked(int, FILE *);
+int	 putchar_unlocked(int);
 #endif
 #if __BSD_VISIBLE
-/** @todo void	clearerr_unlocked(FILE *); */
-/** @todo int	feof_unlocked(FILE *); */
-/** @todo int	ferror_unlocked(FILE *); */
-/** @todo int	fileno_unlocked(FILE *); */
+void	clearerr_unlocked(FILE *);
+int	feof_unlocked(FILE *);
+int	ferror_unlocked(FILE *);
+int	fileno_unlocked(FILE *);
+#endif
+#ifdef __USE_MISC
+int     fflush_unlocked(FILE *);
+size_t  fwrite_unlocked(const void * __restrict, size_t, size_t, FILE * __restrict);
+size_t  fread_unlocked(void * __restrict, size_t, size_t, FILE * __restrict);
+int     fgetc_unlocked(FILE *);
+int     fputc_unlocked(int, FILE *);
+int     fputs_unlocked(const char * __restrict, FILE * __restrict);
+int     puts_unlocked(const char *);
 #endif
 
Index: trunk/src/emx/include/sys/fmutex.h
===================================================================
--- trunk/src/emx/include/sys/fmutex.h	(revision 2089)
+++ trunk/src/emx/include/sys/fmutex.h	(revision 2090)
@@ -104,4 +104,10 @@
 }
 
+
+static __inline__ int _fmutex_is_owner (_fmutex *sem)
+{
+    return sem->fs > _FMS_AVAILABLE && sem->Owner == fibGetTidPid();
+}
+
 /**
  * Release a semaphore in the child process after the
Index: trunk/src/emx/src/lib/app/putenv.c
===================================================================
--- trunk/src/emx/src/lib/app/putenv.c	(revision 2089)
+++ trunk/src/emx/src/lib/app/putenv.c	(revision 2090)
@@ -22,10 +22,15 @@
         LIBCLOG_RETURN_INT(-1);
     }
-    _tzset_flag = 0;                    /* Call tzset() */
+
     s = strchr(string, '=');
     if (s == NULL)
-        len = strlen(string);           /* Use complete string */
-    else
-        len = s - string;
+    {
+        /* remove string, let unset do the work */
+        int rc = unsetenv(string);
+        LIBCLOG_RETURN_INT(rc);
+    }
+
+    /* insert/replace */
+    len = s - string;
     p = environ;
     env_size = 0;
@@ -73,8 +78,7 @@
         LIBCLOG_MSG("replacing '%s' with '%s'\n", *p, string);
         *p = (char *)string;
-        /** @todo this doesn't match the unset policy, we should remove the
-                  variable entirely from the environment when no value is
-                  specified! */
     }
+
+    _tzset_flag = 0;                    /* Call tzset() */
     LIBCLOG_RETURN_INT(0);
 }
Index: trunk/src/emx/src/lib/app/unsetenv.c
===================================================================
--- trunk/src/emx/src/lib/app/unsetenv.c	(revision 2089)
+++ trunk/src/emx/src/lib/app/unsetenv.c	(revision 2090)
@@ -17,4 +17,5 @@
 #include <errno.h>
 #include <emx/startup.h>
+#include <emx/time.h>
 #define __LIBC_LOG_GROUP  __LIBC_LOG_GRP_ENV
 #include <InnoTekLIBC/logstrict.h>
@@ -37,5 +38,4 @@
     int     lenname;
     char ** p;
-
 
     /* validate input */
@@ -62,4 +62,5 @@
                     break;
             LIBCLOG_MSG("deleted '%s'\n", s);
+            _tzset_flag = 0;            /* Call tzset() */
         }
         else
Index: trunk/src/emx/src/lib/io/_fill.c
===================================================================
--- trunk/src/emx/src/lib/io/_fill.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/_fill.c	(revision 2090)
@@ -34,11 +34,20 @@
     }
 
-  /* Fail if the stream is in write mode. */
+  /* switch to read mode if necessary. */
 
   if (stream->_flags & _IOWRT)
     {
-      stream->_flags |= _IOERR;
-      errno = EACCES;
-      return EOF;
+      if (stream->_flags & _IORW)
+        {
+          int rc = _fseek_unlocked (stream, 0, SEEK_CUR);
+          if (rc)
+            return EOF;
+        }
+      if (stream->_flags & _IOWRT)
+        {
+          stream->_flags |= _IOERR;
+          errno = EACCES;
+          return EOF;
+        }
     }
 
Index: trunk/src/emx/src/lib/io/_flush.c
===================================================================
--- trunk/src/emx/src/lib/io/_flush.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/_flush.c	(revision 2090)
@@ -28,11 +28,20 @@
     }
 
-  /* Fail if the stream is in read mode. */
+  /* switch to write mode if necessary. */
 
   if (stream->_flags & _IOREAD)
     {
-      stream->_flags |= _IOERR;
-      errno = EACCES;
-      return EOF;
+      if (stream->_flags & _IORW)
+        {
+          int rc = _fseek_unlocked (stream, 0, SEEK_CUR);
+          if (rc)
+            return EOF;
+        }
+      if (stream->_flags & _IOREAD)
+        {
+          stream->_flags |= _IOERR;
+          errno = EACCES;
+          return EOF;
+        }
     }
 
Index: trunk/src/emx/src/lib/io/_input.c
===================================================================
--- trunk/src/emx/src/lib/io/_input.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/_input.c	(revision 2090)
@@ -275,6 +275,11 @@
   if (!ok)
     {
-      make_unread (v, c);
-      v->status = MATCHING_FAILURE;
+      if (c != EOF)
+        {
+          make_unread (v, c);
+          v->status = MATCHING_FAILURE;
+        }
+      else
+          v->status = INPUT_FAILURE;
       return;
     }
@@ -352,6 +357,11 @@
   if (!ok)
     {
-      make_unread (v, c);
-      v->status = MATCHING_FAILURE;
+      if (c != EOF)
+        {
+          make_unread (v, c);
+          v->status = MATCHING_FAILURE;
+        }
+      else
+          v->status = INPUT_FAILURE;
       return;
     }
@@ -489,6 +499,11 @@
       if (!ok)
         {
-          make_unread (v, c);
-          v->status = MATCHING_FAILURE;
+          if (c != EOF)
+            {
+              make_unread (v, c);
+              v->status = MATCHING_FAILURE;
+            }
+          else
+              v->status = INPUT_FAILURE;
           return;
         }
@@ -505,6 +520,11 @@
           if (!isdigit (c))
             {
-              make_unread (v, c);
-              v->status = MATCHING_FAILURE;
+              if (c != EOF)
+                {
+                  make_unread (v, c);
+                  v->status = MATCHING_FAILURE;
+                }
+              else
+                  v->status = INPUT_FAILURE;
               return;
             }
@@ -725,5 +745,5 @@
               if (f == 0)                 /* % at end of string */
                 return v->count;
-              c = get0 (v);
+              c = skip (v);
               if (c != f)
                 return v->count;
@@ -733,5 +753,5 @@
             {
             case INPUT_FAILURE:
-              return ((v->count == 0) ? EOF : v->count);
+              return v->count == 0 ? EOF : v->count;
             case MATCHING_FAILURE:
             case OUT_OF_MEMORY:
Index: trunk/src/emx/src/lib/io/_output.c
===================================================================
--- trunk/src/emx/src/lib/io/_output.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/_output.c	(revision 2090)
@@ -74,5 +74,5 @@
   if (n >= 16)
     {
-      if (_fwrite_nolock (s, 1, n, v->stream) != n)
+      if (fwrite_unlocked (s, 1, n, v->stream) != n)
         return -1;
       v->count += n;
Index: trunk/src/emx/src/lib/io/_tmpbuf.c
===================================================================
--- trunk/src/emx/src/lib/io/_tmpbuf.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/_tmpbuf.c	(revision 2090)
@@ -22,5 +22,5 @@
   int result;
 
-  result = _fflush_nolock (stream);
+  result = fflush_unlocked (stream);
   stream->_buf_size = 1;
   stream->_ptr = stream->_buffer = &stream->_char_buf;
Index: trunk/src/emx/src/lib/io/clearerr.c
===================================================================
--- trunk/src/emx/src/lib/io/clearerr.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/clearerr.c	(revision 2090)
@@ -4,6 +4,11 @@
 #include <stdio.h>
 
-void _STD(clearerr) (FILE *stream)
+void _STD(clearerr)(FILE *stream)
 {
-  stream->_flags &= ~(_IOERR|_IOEOF);
+    stream->_flags &= ~(_IOERR|_IOEOF);
 }
+
+void _STD(clearerr_unlocked)(FILE *stream)
+{
+    stream->_flags &= ~(_IOERR|_IOEOF);
+}
Index: trunk/src/emx/src/lib/io/fclose.c
===================================================================
--- trunk/src/emx/src/lib/io/fclose.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/fclose.c	(revision 2090)
@@ -2,5 +2,4 @@
 
 #include "libc-alias.h"
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -9,4 +8,5 @@
 #include <sys/fmutex.h>
 #include <emx/io.h>
+#include <stdio.h>
 
 int _STD(fclose) (FILE *stream)
Index: trunk/src/emx/src/lib/io/feof.c
===================================================================
--- trunk/src/emx/src/lib/io/feof.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/feof.c	(revision 2090)
@@ -4,6 +4,11 @@
 #include <stdio.h>
 
-int _STD(feof) (FILE *s)
+int _STD(feof)(FILE *s)
 {
-  return (s->_flags & _IOEOF ? 1 : 0);
+    return s->_flags & _IOEOF ? 1 : 0;
 }
+
+int _STD(feof_unlocked)(FILE *s)
+{
+    return s->_flags & _IOEOF ? 1 : 0;
+}
Index: trunk/src/emx/src/lib/io/ferror.c
===================================================================
--- trunk/src/emx/src/lib/io/ferror.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/ferror.c	(revision 2090)
@@ -4,6 +4,11 @@
 #include <stdio.h>
 
-int _STD(ferror) (FILE *s)
+int _STD(ferror)(FILE *s)
 {
-  return (s->_flags & _IOERR ? 1 : 0);
+    return s->_flags & _IOERR ? 1 : 0;
 }
+
+int _STD(ferror_unlocked)(FILE *s)
+{
+    return s->_flags & _IOERR ? 1 : 0;
+}
Index: trunk/src/emx/src/lib/io/fflush.c
===================================================================
--- trunk/src/emx/src/lib/io/fflush.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/fflush.c	(revision 2090)
@@ -11,5 +11,5 @@
 #include <emx/io.h>
 
-int _fflush_nolock (FILE *stream)
+int _STD(fflush_unlocked) (FILE *stream)
 {
   int result, n, ft, saved_errno;
@@ -50,5 +50,5 @@
       /* ISO 9899-1990, 7.9.5.2: "The fflush function returns EOF if a
          write error occurs, otherwise zero." */
-      pos = _ftell_nolock (stream);
+      pos = _ftello_unlocked (stream);
       if (pos != -1)
         lseek (stream->_handle, pos, SEEK_SET);
@@ -81,5 +81,5 @@
 
   STREAM_LOCK (stream);
-  result = _fflush_nolock (stream);
+  result = fflush_unlocked (stream);
   STREAM_UNLOCK (stream);
   return result;
Index: trunk/src/emx/src/lib/io/fgetc.c
===================================================================
--- trunk/src/emx/src/lib/io/fgetc.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/fgetc.c	(revision 2090)
@@ -9,11 +9,24 @@
 #include "getputc.h"
 
-int _STD(fgetc) (FILE *stream)
+int _STD(getc)(FILE *stream)
 {
-  int r;
+    return fgetc(stream);
+}
 
-  STREAM_LOCK (stream);
-  r = _getc_inline (stream);
-  STREAM_UNLOCK (stream);
-  return r;
+int _STD(fgetc)(FILE *stream)
+{
+    STREAM_LOCK(stream);
+    int rc = _getc_inline(stream);
+    STREAM_UNLOCK(stream);
+    return rc;
 }
+
+int _STD(getc_unlocked)(FILE *stream)
+{
+    return fgetc_unlocked(stream);
+}
+
+int _STD(fgetc_unlocked)(FILE *stream)
+{
+    return _getc_inline(stream);
+}
Index: trunk/src/emx/src/lib/io/fileno.c
===================================================================
--- trunk/src/emx/src/lib/io/fileno.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/fileno.c	(revision 2090)
@@ -4,6 +4,12 @@
 #include <stdio.h>
 
-int _STD(fileno) (FILE *s)
+int _STD(fileno)(FILE *s)
 {
-  return s->_handle;
+    return s->_handle;
 }
+
+int _STD(fileno_unlocked)(FILE *s)
+{
+    return s->_handle;
+}
+
Index: trunk/src/emx/src/lib/io/flockfile.c
===================================================================
--- trunk/src/emx/src/lib/io/flockfile.c	(revision 2090)
+++ trunk/src/emx/src/lib/io/flockfile.c	(revision 2090)
@@ -0,0 +1,49 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC - flockfile()
+ *
+ * Copyright (c) 2005 knut st. osmundsen <bird@anduin.net>
+ *
+ *
+ * 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 <sys/fmutex.h>
+#include <emx/io.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+/**
+ * Locks a file stream.
+ * Call funlockfile() to release the lock.
+ *
+ * @param   pStream     The file stream to lock.
+ */
+void _STD(flockfile)(FILE *pStream)
+{
+    STREAM_LOCK(pStream);
+}
+
+
Index: trunk/src/emx/src/lib/io/flushall.c
===================================================================
--- trunk/src/emx/src/lib/io/flushall.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/flushall.c	(revision 2090)
@@ -22,5 +22,5 @@
         {
           ++n;
-          _fflush_nolock (&sv->aFiles[i]);
+          fflush_unlocked (&sv->aFiles[i]);
           STREAM_UNLOCK (&sv->aFiles[i]);
         }
Index: trunk/src/emx/src/lib/io/fputc.c
===================================================================
--- trunk/src/emx/src/lib/io/fputc.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/fputc.c	(revision 2090)
@@ -2,5 +2,4 @@
 
 #include "libc-alias.h"
-#include <sys/builtin.h>        /* For <sys/fmutex.h> */
 #include <sys/fmutex.h>
 #include <stdio.h>
@@ -9,11 +8,31 @@
 #include "getputc.h"
 
-int _STD(fputc) (int c, FILE *stream)
+int _STD(putc)(int c, FILE *stream)
 {
-  int r;
+    return fputc(c, stream);
+}
 
-  STREAM_LOCK (stream);
-  r = _putc_inline (c, stream);
-  STREAM_UNLOCK (stream);
-  return r;
+int _STD(fputc)(int c, FILE *stream)
+{
+    int r;
+
+    STREAM_LOCK(stream);
+    r = _putc_inline(c, stream);
+    STREAM_UNLOCK(stream);
+    return r;
 }
+
+int _STD(putc_unlocked)(int c, FILE *stream)
+{
+    return fputc_unlocked(c, stream);
+}
+
+int _STD(fputc_unlocked)(int c, FILE *stream)
+{
+    int r;
+
+    STREAM_LOCK(stream);
+    r = _putc_inline(c, stream);
+    STREAM_UNLOCK(stream);
+    return r;
+}
Index: trunk/src/emx/src/lib/io/fputs.c
===================================================================
--- trunk/src/emx/src/lib/io/fputs.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/fputs.c	(revision 2090)
@@ -5,9 +5,16 @@
 #include <string.h>
 
-int _STD(fputs) (const char *string, FILE *stream)
+int _STD(fputs)(const char *string, FILE *stream)
 {
-  int len;
+    int len = strlen (string);
+    return len == 0 || fwrite(string, len, 1, stream) == 1
+        ? 0 : EOF;
+}
 
-  len = strlen (string);
-  return (len == 0 || fwrite (string, len, 1, stream) == 1 ? 0 : EOF);
+int _STD(fputs_unlocked)(const char *string, FILE *stream)
+{
+    int len = strlen(string);
+    return len == 0 || fwrite_unlocked(string, len, 1, stream) == 1
+        ? 0 : EOF;
 }
+
Index: trunk/src/emx/src/lib/io/fread.c
===================================================================
--- trunk/src/emx/src/lib/io/fread.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/fread.c	(revision 2090)
@@ -12,5 +12,13 @@
 #include <emx/io.h>
 
-size_t _STD(fread) (void *buffer, size_t size, size_t count, FILE *stream)
+size_t _STD(fread)(void *buffer, size_t size, size_t count, FILE *stream)
+{
+    STREAM_LOCK(stream);
+    size_t cb = fread_unlocked(buffer, size, count, stream);
+    STREAM_UNLOCK(stream);
+    return cb;
+}
+
+size_t _STD(fread_unlocked)(void *buffer, size_t size, size_t count, FILE *stream)
 {
   size_t total, left, n;
@@ -28,5 +36,4 @@
     }
 
-  STREAM_LOCK (stream);
   if (nbuf (stream))
     _fbuf (stream);
@@ -120,5 +127,4 @@
         }
     }
-  STREAM_UNLOCK (stream);
   return (total - left) / size;
 }
Index: trunk/src/emx/src/lib/io/fseek.c
===================================================================
--- trunk/src/emx/src/lib/io/fseek.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/fseek.c	(revision 2090)
@@ -10,5 +10,5 @@
 #include <emx/io.h>
 
-int _fseek_nolock (FILE *stream, off_t offset, int origin)
+int _fseek_unlocked (FILE *stream, off_t offset, int origin)
 {
   off_t     cur_pos;
@@ -40,5 +40,5 @@
       file_pos = tell (stream->_handle);
       if (file_pos == -1) return EOF;
-      cur_pos = _ftell_nolock (stream);
+      cur_pos = _ftello_unlocked (stream);
       if (origin == SEEK_CUR)
         {
@@ -146,8 +146,8 @@
 
   if (origin == SEEK_CUR && cur_pos == -1)
-    cur_pos = _ftell_nolock (stream);
+    cur_pos = _ftello_unlocked (stream);
 #endif
 
-  fflush_result = _fflush_nolock (stream);
+  fflush_result = fflush_unlocked (stream);
   stream->_flags &= ~_IOEOF;
   if (stream->_flags & _IORW)
@@ -157,5 +157,5 @@
     {
       if (cur_pos == -1)
-        cur_pos = _ftell_nolock (stream);
+        cur_pos = _ftello_unlocked (stream);
       if (cur_pos == -1)
         {
@@ -184,5 +184,5 @@
 
     STREAM_LOCK (stream);
-    result = _fseek_nolock (stream, offset, origin);
+    result = _fseek_unlocked (stream, offset, origin);
     STREAM_UNLOCK (stream);
     return result;
Index: trunk/src/emx/src/lib/io/ftell.c
===================================================================
--- trunk/src/emx/src/lib/io/ftell.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/ftell.c	(revision 2090)
@@ -12,5 +12,5 @@
 #include <emx/io.h>
 
-off_t _ftell_nolock (FILE *stream)
+off_t _ftello_unlocked (FILE *stream)
 {
   off_t     pos;
@@ -104,5 +104,5 @@
 
   STREAM_LOCK (stream);
-  off = _ftell_nolock (stream);
+  off = _ftello_unlocked (stream);
   STREAM_UNLOCK (stream);
   return off;
Index: trunk/src/emx/src/lib/io/ftrylockfile.c
===================================================================
--- trunk/src/emx/src/lib/io/ftrylockfile.c	(revision 2090)
+++ trunk/src/emx/src/lib/io/ftrylockfile.c	(revision 2090)
@@ -0,0 +1,52 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC - ftrylockfile()
+ *
+ * Copyright (c) 2005 knut st. osmundsen <bird@anduin.net>
+ *
+ *
+ * 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 <sys/fmutex.h>
+#include <emx/io.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+/**
+ * Tries to locks a file stream.
+ * Call funlockfile() to release the lock.
+ *
+ * @returns 0 if the lock was aquired.
+ * @returns -1 if the lock was not aquired.
+ * @param   pStream     The file stream to attempt locking.
+ */
+int _STD(ftrylockfile)(FILE *pStream)
+{
+    if (STREAM_LOCK_NOWAIT(pStream))
+        return 0;
+    return -1;
+}
+
Index: trunk/src/emx/src/lib/io/funlockfile.c
===================================================================
--- trunk/src/emx/src/lib/io/funlockfile.c	(revision 2090)
+++ trunk/src/emx/src/lib/io/funlockfile.c	(revision 2090)
@@ -0,0 +1,50 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC - funlockfile()
+ *
+ * Copyright (c) 2005 knut st. osmundsen <bird@anduin.net>
+ *
+ *
+ * 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 <sys/fmutex.h>
+#include <emx/io.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+/**
+ * Unlocks a file stream.
+ * The stream must previously have been locked by calling flockfile().
+ *
+ * @param   pStream     The file stream to unlock.
+ */
+void _STD(funlockfile)(FILE *pStream)
+{
+    STREAM_UNLOCK(pStream);
+}
+
+
+
Index: trunk/src/emx/src/lib/io/fwrite.c
===================================================================
--- trunk/src/emx/src/lib/io/fwrite.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/fwrite.c	(revision 2090)
@@ -102,21 +102,27 @@
 }
 
-
-size_t _fwrite_nolock (const void *buffer, size_t size, size_t count,
-                       FILE *stream)
+size_t _STD(fwrite_unlocked) (const void *buffer, size_t size, size_t count, FILE *stream)
 {
   size_t total, left, n;
   const char *src, *newline;
 
-  if (stream->_flags & _IOREAD)    /* File in read mode? */
+  /* switch to write mode if necessary. */
+  if (stream->_flags & _IOREAD)
     {
-      stream->_flags |= _IOERR;
-      errno = EACCES;
-      return 0;
+      if (stream->_flags & _IORW)
+        {
+          int rc = _fseek_unlocked (stream, 0, SEEK_CUR);
+          if (rc)
+            return EOF;
+        }
+      if (stream->_flags & _IOREAD)
+        {
+          stream->_flags |= _IOERR;
+          errno = EACCES;
+          return EOF;
+        }
     }
-  if (count == 0)
+  if (size == 0 || count == 0)
     return 0;
-  if (size == 0)
-    return count;
   total = size * count;
   if (total / count != size)
@@ -143,8 +149,8 @@
             {
               /* Note that the return value will be inaccurate if
-                 _fflush_nolock() fails, but that's also true for
+                 fflush_unlocked() fails, but that's also true for
                  _IOFBF. */
 
-              if (_fflush_nolock (stream) != 0)
+              if (fflush_unlocked (stream) != 0)
                 left = total;
               else if (left != 0)
@@ -164,5 +170,5 @@
 
   STREAM_LOCK (stream);
-  r = _fwrite_nolock (buffer, size, count, stream);
+  r = fwrite_unlocked (buffer, size, count, stream);
   STREAM_UNLOCK (stream);
   return r;
Index: trunk/src/emx/src/lib/io/getchar.c
===================================================================
--- trunk/src/emx/src/lib/io/getchar.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/getchar.c	(revision 2090)
@@ -4,6 +4,11 @@
 #include <stdio.h>
 
-int _STD(getchar) (void)
+int _STD(getchar)(void)
 {
-  return getc (stdin);
+    return getc(stdin);
 }
+
+int _STD(getchar_unlocked)(void)
+{
+    return getc_unlocked(stdin);
+}
Index: trunk/src/emx/src/lib/io/putchar.c
===================================================================
--- trunk/src/emx/src/lib/io/putchar.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/putchar.c	(revision 2090)
@@ -4,6 +4,11 @@
 #include <stdio.h>
 
-int _STD(putchar) (int c)
+int _STD(putchar)(int c)
 {
-  return putc (c, stdout);
+    return putc(c, stdout);
 }
+
+int _STD(putchar_unlocked)(int c)
+{
+    return putc_unlocked(c, stdout);
+}
Index: trunk/src/emx/src/lib/io/puts.c
===================================================================
--- trunk/src/emx/src/lib/io/puts.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/puts.c	(revision 2090)
@@ -12,19 +12,26 @@
 int _STD(puts) (const char *string)
 {
-  int result, len;
-  void *tb;
+    STREAM_LOCK(stdout);
+    int rc = puts_unlocked(string);
+    STREAM_UNLOCK(stdout);
+    return rc;
+}
 
-  len = strlen (string);
-  STREAM_LOCK (stdout);
-  if (nbuf (stdout))
-    _fbuf (stdout);
-  _tmpbuf (stdout, tb);
-  if (len == 0 || _fwrite_nolock (string, len, 1, stdout) == 1)
-    result = _putc_inline ('\n', stdout);
-  else
-    result = EOF;
-  if (_endbuf (stdout) != 0)
-    result = EOF;
-  STREAM_UNLOCK (stdout);
-  return result;
+int _STD(puts_unlocked) (const char *string)
+{
+    int result;
+
+    int len = strlen(string);
+    if (nbuf(stdout))
+        _fbuf (stdout);
+    void *tb;
+    _tmpbuf(stdout, tb);
+    if (    len == 0
+        ||  fwrite_unlocked(string, len, 1, stdout) == 1)
+        result = _putc_inline('\n', stdout);
+    else
+        result = EOF;
+    if (_endbuf(stdout) != 0)
+        result = EOF;
+    return result;
 }
Index: trunk/src/emx/src/lib/io/rewind.c
===================================================================
--- trunk/src/emx/src/lib/io/rewind.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/rewind.c	(revision 2090)
@@ -11,6 +11,6 @@
 {
   STREAM_LOCK (stream);
-  _fflush_nolock (stream);
-  _fseek_nolock (stream, 0, SEEK_SET);
+  fflush_unlocked (stream);
+  _fseek_unlocked (stream, 0, SEEK_SET);
   stream->_flags &= ~_IOERR;
   STREAM_UNLOCK (stream);
Index: trunk/src/emx/src/lib/io/setvbuf.c
===================================================================
--- trunk/src/emx/src/lib/io/setvbuf.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/setvbuf.c	(revision 2090)
@@ -15,5 +15,5 @@
 
   STREAM_LOCK (stream);
-  _fflush_nolock (stream);
+  fflush_unlocked (stream);
   if ((stream->_flags & _IOBUFMASK) == _IOBUFLIB)
     free (stream->_buffer);
Index: trunk/src/emx/src/lib/io/ungetc.c
===================================================================
--- trunk/src/emx/src/lib/io/ungetc.c	(revision 2089)
+++ trunk/src/emx/src/lib/io/ungetc.c	(revision 2090)
@@ -112,5 +112,5 @@
           || ft != HT_FILE)
         return EOF;
-      
+
       /* OK, we can flush the stream buffer.  We flush the buffer
          completely and don't attempt to keep some data (that would be
@@ -119,5 +119,5 @@
 
       uc = stream->_ungetc_count;
-      if (_fflush_nolock (stream) != 0)
+      if (fflush_unlocked (stream) != 0)
         return EOF;
       stream->_ungetc_count = uc;
Index: trunk/src/emx/src/lib/libc.def
===================================================================
--- trunk/src/emx/src/lib/libc.def	(revision 2089)
+++ trunk/src/emx/src/lib/libc.def	(revision 2090)
@@ -533,5 +533,5 @@
     "__fbuf" @546
     "__fcloseall" @547
-    "__fflush_nolock" @548
+    "__std_fflush_unlocked" @548
     "__filesys" @549
     "__fill" @550
@@ -558,10 +558,10 @@
     "__fpreset" @571
     "__fseek_hdr" @572
-    "__fseek_nolock" @573
+    "__fseek_unlocked" @573
     "__fsetmode" @574
     "__fsopen" @575
-    "__ftell_nolock" @576
+    "__ftello_unlocked" @576
     "__fullpath" @577
-    "__fwrite_nolock" @578
+    "__std_fwrite_unlocked" @578
     "__fxam" @579
     "__fxaml" @580
@@ -1719,2 +1719,24 @@
     "__std_mkdtemp" @1722
     "__std_mkstemps" @1723
+    ; unlocked file stream stuff.
+    "__std_clearerr_unlocked" @1724
+    "__std_feof_unlocked" @1725
+    "__std_ferror_unlocked" @1726
+    "__std_fgetc_unlocked" @1727
+    "__std_fileno_unlocked" @1728
+    "__std_flockfile" @1729
+    "__std_ftrylockfile" @1730
+    "__std_funlockfile" @1731
+    "__std_getc" @1732
+    "__std_getchar_unlocked" @1733
+    "__std_getc_unlocked" @1734
+    "__std_putchar_unlocked" @1735
+    "__std_fputc_unlocked" @1736
+    "__std_putc" @1737
+    "__std_putc_unlocked" @1738
+    "__std_fputs_unlocked" @1739
+    "__std_puts_unlocked" @1740
+    "__std_fread_unlocked" @1741
+    "___isinff" @1742
+    "___isinfl" @1743
+    "__std_isinf" @1744
Index: trunk/src/emx/src/lib/libc.smak
===================================================================
--- trunk/src/emx/src/lib/libc.smak	(revision 2089)
+++ trunk/src/emx/src/lib/libc.smak	(revision 2090)
@@ -364,5 +364,6 @@
 
 $(INS)lib/$(notdir $(LIBC.DLL)): $(LIBC.DLL)
-	if test -f $@; then emxload emxomfld && unlock $(subst /,\\,$@) && cp $< $@ && emxload -u emxomfld; else cp $< $@; fi
+	if test -f $@; then rm -f $@ || (unlock $(subst /,\\,$@) && rm -f $@); fi
+	cp $< $@
 	
 $(INS)lib/$(notdir $(LIBC.DLL:.dll=.map)): $(LIBC.DLL:.dll=.map)
Index: trunk/src/emx/src/lib/libc06b4.def
===================================================================
--- trunk/src/emx/src/lib/libc06b4.def	(revision 2089)
+++ trunk/src/emx/src/lib/libc06b4.def	(revision 2090)
@@ -531,5 +531,5 @@
     "__fbuf" @546
     "__fcloseall" @547
-    "__fflush_nolock" @548
+    "__std_fflush_unlocked" @548
     "__filesys" @549
     "__fill" @550
@@ -556,10 +556,10 @@
     "__fpreset" @571
     "__fseek_hdr" @572
-    "__fseek_nolock" @573
+    "__fseek_unlocked" @573
     "__fsetmode" @574
     "__fsopen" @575
-    "__ftell_nolock" @576
+    "__ftello_unlocked" @576
     "__fullpath" @577
-    "__fwrite_nolock" @578
+    "__std_fwrite_unlocked" @578
     "__fxam" @579
     "__fxaml" @580
Index: trunk/src/emx/src/lib/misc/_realrealpath.c
===================================================================
--- trunk/src/emx/src/lib/misc/_realrealpath.c	(revision 2089)
+++ trunk/src/emx/src/lib/misc/_realrealpath.c	(revision 2090)
@@ -53,4 +53,11 @@
     LIBCLOG_ENTER("pszPath=%p:{%s} pszResolved=%p cchResolved=%d\n", (void *)pszPath, pszPath, pszResolved, cchResolved);
 
+    if (!pszPath)
+    {
+        errno = EINVAL;
+        LIBC_ASSERTM_FAILED("pszPath is NULL!\n");
+        LIBCLOG_RETURN_INT(NULL);
+    }
+
     int rc;
     if (!pszResolved)
@@ -75,14 +82,16 @@
         else
             rc = -ENOMEM;
-    }
-    else
-    {
-        rc = __libc_Back_fsPathResolve(pszPath, pszResolved, cchResolved, __LIBC_BACKFS_FLAGS_RESOLVE_NATIVE);
-        if (!rc)
-            LIBCLOG_RETURN_MSG(pszResolved, "ret %p:{%s}\n", pszResolved, pszResolved);
+        errno = -rc;
+        LIBCLOG_RETURN_P(NULL);
     }
 
-    errno = -rc;
-    LIBCLOG_RETURN_P(NULL);
+    char *pszRet = pszResolved;
+    rc = __libc_Back_fsPathResolve(pszPath, pszResolved, cchResolved, __LIBC_BACKFS_FLAGS_RESOLVE_NATIVE);
+    if (rc)
+    {
+        errno = -rc;
+        pszRet = NULL;
+    }
+    LIBCLOG_RETURN_MSG(pszRet, "ret %p pszResolved=%p:{%s}\n", pszRet, pszResolved, pszResolved);
 }
 
Index: trunk/src/emx/src/lib/misc/realpath.c
===================================================================
--- trunk/src/emx/src/lib/misc/realpath.c	(revision 2089)
+++ trunk/src/emx/src/lib/misc/realpath.c	(revision 2090)
@@ -53,4 +53,11 @@
     LIBCLOG_ENTER("path=%p:{%s} resolved_path=%p\n", (void *)path, path, resolved_path);
 
+    if (!path)
+    {
+        errno = EINVAL;
+        LIBC_ASSERTM_FAILED("path is NULL!\n");
+        LIBCLOG_RETURN_P(NULL);
+    }
+
     int rc;
     if (!resolved_path)
@@ -73,14 +80,16 @@
         else
             rc = -ENOMEM;
-    }
-    else
-    {
-        rc = __libc_Back_fsPathResolve(path, resolved_path, PATH_MAX, 0);
-        if (!rc)
-            LIBCLOG_RETURN_MSG(resolved_path, "ret %p:{%s}\n", resolved_path, resolved_path);
+        errno = -rc;
+        LIBCLOG_RETURN_P(NULL);
     }
 
-    errno = -rc;
-    LIBCLOG_RETURN_P(NULL);
+    char *pszRet = resolved_path;
+    rc = __libc_Back_fsPathResolve(path, resolved_path, PATH_MAX, 0);
+    if (rc)
+    {
+        errno = -rc;
+        pszRet = NULL;
+    }
+    LIBCLOG_RETURN_MSG(pszRet, "ret %p resolved_path=%p:{%s}\n", pszRet, resolved_path, resolved_path);
 }
 
Index: trunk/src/emx/src/lib/msun/std-math.c
===================================================================
--- trunk/src/emx/src/lib/msun/std-math.c	(revision 2089)
+++ trunk/src/emx/src/lib/msun/std-math.c	(revision 2090)
@@ -284,5 +284,5 @@
 double	drem(double, double);
 int	finite(double) __pure2;
-int	isnanf(float) __pure2;
+int	_STD(isnanf)(float) __pure2;
 
 /*
Index: trunk/src/emx/src/lib/sys/b_fs.h
===================================================================
--- trunk/src/emx/src/lib/sys/b_fs.h	(revision 2089)
+++ trunk/src/emx/src/lib/sys/b_fs.h	(revision 2090)
@@ -106,5 +106,5 @@
  *
  * @returns 0 on success.
- * @returns -1 and errno on failure.
+ * @returns Negative error code (errno.h) on failiure.
  * @param   pszUserPath     The user path.
  * @parm    fFlags          Flags controlling the operation of the function.
Index: trunk/src/emx/src/lib/sys/b_fsPathResolve.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_fsPathResolve.c	(revision 2089)
+++ trunk/src/emx/src/lib/sys/b_fsPathResolve.c	(revision 2090)
@@ -66,27 +66,25 @@
     int     fInUnixTree;
     char    szNativePath[PATH_MAX];
+    szNativePath[0] = '\0';
     rc = __libc_back_fsResolve(pszPath, BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_DIR_MAYBE, szNativePath, &fInUnixTree);
-    if (!rc)
+
+    /*
+     * Copy the (half) result back to the caller.
+     */
+    char *pszSrc = &szNativePath[0];
+    if (!(fFlags & __LIBC_BACKFS_FLAGS_RESOLVE_NATIVE) && fInUnixTree)
     {
-        char *pszSrc = &szNativePath[0];
-        if (!(fFlags & __LIBC_BACKFS_FLAGS_RESOLVE_NATIVE) && fInUnixTree)
-        {
-            pszSrc += __libc_gcchUnixRoot;
-            LIBC_ASSERTM(*pszSrc == '/', "bogus fInUnixTree flag! pszSrc='%s' whole think '%s'\n", pszSrc, szNativePath);
-        }
-        __libc_back_fsMutexRelease();
+        pszSrc += __libc_gcchUnixRoot;
+        LIBC_ASSERTM(*pszSrc == '/', "bogus fInUnixTree flag! pszSrc='%s' whole thing is '%s'\n", pszSrc, szNativePath);
+    }
+    __libc_back_fsMutexRelease();
 
-        int cch = strlen(pszSrc) + 1;
-        if (cch < cchBuf)
-        {
-            memcpy(pszBuf, pszSrc, cchBuf);
-            LIBCLOG_RETURN_MSG(0, "ret 0 pszPath=%p:{%s}\n", (void *)pszPath, pszPath);
-        }
-        else
-            rc = -ERANGE;
-    }
-    else
-        __libc_back_fsMutexRelease();
-    LIBCLOG_RETURN_INT(rc);
+    int cch = strlen(pszSrc) + 1;
+    if (cch < cchBuf)
+        memcpy(pszBuf, pszSrc, cchBuf);
+    else if (!rc)
+        rc = -ERANGE;
+
+    LIBCLOG_RETURN_MSG(rc, "ret %d pszPath=%p:{%s}\n", rc, (void *)pszPath, pszPath);
 }
 
Index: trunk/src/emx/src/lib/sys/fs.c
===================================================================
--- trunk/src/emx/src/lib/sys/fs.c	(revision 2089)
+++ trunk/src/emx/src/lib/sys/fs.c	(revision 2090)
@@ -604,8 +604,10 @@
  * @returns Number of bytes in the clean path.
  * @param   pszPath     The path to cleanup.
- * @parm    fFlags          Flags controlling the operation of the function.
- *                          See the BACKFS_FLAGS_* defines.
- */
-static int fsCleanPath(char *pszPath, int fFlags)
+ * @param   fFlags      Flags controlling the operation of the function.
+ *                      See the BACKFS_FLAGS_* defines.
+ * @param   pfFlags     Where to clear the BACKFS_FLAGS_RESOLVE_DIR_MAYBE_ flag if a
+ *                      trailing slash was found.
+ */
+static int fsCleanPath(char *pszPath, unsigned fFlags, unsigned *pfFlags)
 {
     /*
@@ -616,5 +618,6 @@
     char   *pszTrg = pszPath;
     if (    (pszPath[0] == '\\' || pszPath[0] == '/')
-        &&  (pszPath[1] == '\\' || pszPath[1] == '/'))
+        &&  (pszPath[1] == '\\' || pszPath[1] == '/')
+        &&   pszPath[2] != '\\' && pszPath[2] != '/')
     {   /* Skip first slash in a unc path. */
         pszSrc++;
@@ -654,5 +657,9 @@
         &&  pszTrg[-2] != ':'
         &&  pszTrg[-2] != '/')
+    {
         pszPath[--cch] = '\0';
+        if (pfFlags)
+            *pfFlags &= ~BACKFS_FLAGS_RESOLVE_DIR_MAYBE_;
+    }
 
     return cch;
@@ -664,5 +671,5 @@
  *
  * @returns 0 on success.
- * @returns -1 and errno on failure.
+ * @returns Negative error code (errno.h) on failiure.
  * @param   pszUserPath     The user path.
  * @parm    fFlags          Flags controlling the operation of the function.
@@ -674,8 +681,21 @@
 int __libc_back_fsResolve(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree)
 {
-    if (!__libc_gfNoUnix)
-        return fsResolveUnix(pszUserPath, fFlags, pszNativePath, pfInUnixTree);
-    else
-        return fsResolveOS2(pszUserPath, fFlags, pszNativePath, pfInUnixTree);
+    if (pszUserPath && *pszUserPath)
+    {
+        if (!__libc_gfNoUnix)
+            return fsResolveUnix(pszUserPath, fFlags, pszNativePath, pfInUnixTree);
+        else
+            return fsResolveOS2(pszUserPath, fFlags, pszNativePath, pfInUnixTree);
+    }
+
+    /* failure */
+    *pszNativePath = '\0';
+    if (pfInUnixTree)
+        *pfInUnixTree = 0;
+
+    LIBC_ASSERT(pszUserPath);
+    if (!pszUserPath)
+        return -EINVAL;
+    return -ENOENT;
 }
 
@@ -685,5 +705,5 @@
  *
  * @returns 0 on success.
- * @returns -1 and errno on failure.
+ * @returns Negative error code (errno.h) on failiure.
  * @param   pszUserPath     The user path.
  * @parm    fFlags          Flags controlling the operation of the function.
@@ -698,5 +718,4 @@
                   (void *)pszUserPath, pszUserPath, (void *)pszNativePath, (void *)pfInUnixTree);
     const char *pszUserPathIn = pszUserPath;
-    char        szTmp[PATH_MAX];
     char        _achBuffer[SIZEOF_ACHBUFFER + 4];
     char       *pachBuffer = (char *)((uintptr_t)&_achBuffer[3] & ~3);
@@ -739,8 +758,8 @@
                 ULONG ulDisk;
                 rc = DosQueryCurrentDisk(&ulDisk, &ul);
-                szTmp[0] = ulDisk + 'A' - 1;
-                ul = sizeof(szTmp) - 2;
+                pszNativePath[0] = ulDisk + 'A' - 1;
+                ul = PATH_MAX - 2;
                 if (!rc)
-                    rc = DosQueryCurrentDir(0, (PSZ)&szTmp[3], &ul);
+                    rc = DosQueryCurrentDir(0, (PSZ)&pszNativePath[3], &ul);
                 iRoot = __libc_gfInUnixTree ? __libc_gcchUnixRoot : 2;
                 /* fInUnixTree remains whatever it is */
@@ -751,7 +770,7 @@
                  * Drive letter but no root slash.
                  */
-                szTmp[0] = pszUserPath[0];
-                ul = sizeof(szTmp) - 2;
-                rc = DosQueryCurrentDir(pszUserPath[0] - (pszUserPath[0] >= 'A' && pszUserPath[0] <= 'Z' ? 'A' : 'a') + 1, (PSZ)&szTmp[3], &ul);
+                pszNativePath[0] = pszUserPath[0];
+                ul = PATH_MAX - 2;
+                rc = DosQueryCurrentDir(pszUserPath[0] - (pszUserPath[0] >= 'A' && pszUserPath[0] <= 'Z' ? 'A' : 'a') + 1, (PSZ)&pszNativePath[3], &ul);
                 pszUserPath += 2;
                 iRoot = 2;
@@ -768,8 +787,8 @@
              * Add the path stuff from the user.
              */
-            szTmp[1] = ':';
-            szTmp[2] = '/';
-            int cch = strlen(szTmp);
-            szTmp[cch++] = '/';
+            pszNativePath[1] = ':';
+            pszNativePath[2] = '/';
+            int cch = strlen(pszNativePath);
+            pszNativePath[cch++] = '/';
             int cchUserPath = strlen(pszUserPath) + 1;
             if (cch + cchUserPath > PATH_MAX)
@@ -778,6 +797,6 @@
                 break;
             }
-            memcpy(&szTmp[cch], pszUserPath, cchUserPath);
-            pszUserPath = memcpy(pachBuffer, szTmp, cch + cchUserPath);
+            memcpy(&pszNativePath[cch], pszUserPath, cchUserPath);
+            pszUserPath = memcpy(pachBuffer, pszNativePath, cch + cchUserPath);
         }
 
@@ -802,23 +821,23 @@
         /*
          * Apply rewrite rules.
-         * Path now goes to szTmp buffer.
+         * Path now goes to pszNativePath buffer.
          */
-        int cchTmp = __libc_PathRewrite(pszUserPath, szTmp, sizeof(szTmp));
-        if (cchTmp > 0)
+        int cchNativePath = __libc_PathRewrite(pszUserPath, pszNativePath, PATH_MAX);
+        if (cchNativePath > 0)
         {
             /*
              * Redetermin root because of rewrite.
              */
-            iRoot = szTmp[1] == ':' ? 2 : 0;
+            iRoot = pszNativePath[1] == ':' ? 2 : 0;
         }
-        else if (!cchTmp)
-        {
-            cchTmp = strlen(pszUserPath);
-            if (cchTmp + 2 > sizeof(szTmp))
+        else if (!cchNativePath)
+        {
+            cchNativePath = strlen(pszUserPath);
+            if (cchNativePath + 2 > PATH_MAX)
             {
                 rcRet = -ENAMETOOLONG;
                 break;
             }
-            memcpy(szTmp, pszUserPath, cchTmp + 1);
+            memcpy(pszNativePath, pszUserPath, cchNativePath + 1);
         }
         else
@@ -831,31 +850,31 @@
          * Check if special OS/2 name.
          */
-        if (szTmp[0] == '/' || szTmp[0] == '\\')
+        if (pszNativePath[0] == '/' || pszNativePath[0] == '\\')
         {
             int fDone = 0;
-            if (    (szTmp[1] == 'p' || szTmp[1] == 'P')
-                &&  (szTmp[2] == 'i' || szTmp[2] == 'I')
-                &&  (szTmp[3] == 'p' || szTmp[3] == 'P')
-                &&  (szTmp[4] == 'e' || szTmp[4] == 'E')
-                &&  (szTmp[5] == '/' || szTmp[5] == '\\'))
+            if (    (pszNativePath[1] == 'p' || pszNativePath[1] == 'P')
+                &&  (pszNativePath[2] == 'i' || pszNativePath[2] == 'I')
+                &&  (pszNativePath[3] == 'p' || pszNativePath[3] == 'P')
+                &&  (pszNativePath[4] == 'e' || pszNativePath[4] == 'E')
+                &&  (pszNativePath[5] == '/' || pszNativePath[5] == '\\'))
                 fDone = 1;
-            else if ((szTmp[1]== 'd' || szTmp[1] == 'D')
-                &&  (szTmp[2] == 'e' || szTmp[2] == 'E')
-                &&  (szTmp[3] == 'v' || szTmp[3] == 'V')
-                &&  (szTmp[4] == '/' || szTmp[4] == '\\')
+            else if ((pszNativePath[1]== 'd' || pszNativePath[1] == 'D')
+                &&  (pszNativePath[2] == 'e' || pszNativePath[2] == 'E')
+                &&  (pszNativePath[3] == 'v' || pszNativePath[3] == 'V')
+                &&  (pszNativePath[4] == '/' || pszNativePath[4] == '\\')
                 )
             {
                 PFSQBUFFER2 pfsqb = (PFSQBUFFER2)pachBuffer;
                 ULONG       cb = SIZEOF_ACHBUFFER;
-                fDone = !DosQueryFSAttach((PCSZ)szTmp, 0, FSAIL_QUERYNAME, pfsqb, &cb);
-            }
-
-            /* If it was, copy path to szTmp and go to exit code. */
+                fDone = !DosQueryFSAttach((PCSZ)pszNativePath, 0, FSAIL_QUERYNAME, pfsqb, &cb);
+            }
+
+            /* If it was, copy path to pszNativePath and go to exit code. */
             if (fDone)
             {
-                int cch = strlen(szTmp) + 1;
+                int cch = strlen(pszNativePath) + 1;
                 if (cch <= PATH_MAX)
                 {
-                    fsCleanPath(&szTmp[0], fFlags);
+                    fsCleanPath(pszNativePath, fFlags, NULL);
                     rcRet = 0;
                 }
@@ -869,21 +888,21 @@
          * Remove excessive slashing and convert all slashes to '/'.
          */
-        cchTmp = fsCleanPath(&szTmp[0], fFlags);
+        cchNativePath = fsCleanPath(pszNativePath, fFlags, &fFlags);
 
         /*
          * Expand unix root or add missing drive letter.
          */
-        if (szTmp[0] == '/' && szTmp[1] != '/')
-        {
-            memcpy(pachBuffer, szTmp, cchTmp + 1);
+        if (pszNativePath[0] == '/' && pszNativePath[1] != '/')
+        {
+            memcpy(pachBuffer, pszNativePath, cchNativePath + 1);
             if (__libc_gcchUnixRoot)
             {
                 iRoot = __libc_gcchUnixRoot;
-                if (cchTmp + iRoot >= PATH_MAX)
+                if (cchNativePath + iRoot >= PATH_MAX)
                 {
                     rcRet = -ENAMETOOLONG;
                     break;
                 }
-                memcpy(szTmp, __libc_gszUnixRoot, iRoot);
+                memcpy(pszNativePath, __libc_gszUnixRoot, iRoot);
                 fInUnixTree = 1;
             }
@@ -894,17 +913,17 @@
                 ULONG   ul;
                 DosQueryCurrentDisk(&ulDisk, &ul);
-                if (cchTmp + iRoot >= PATH_MAX)
+                if (cchNativePath + iRoot >= PATH_MAX)
                 {
                     rcRet = -ENAMETOOLONG;
                     break;
                 }
-                szTmp[0] = ulDisk + 'A' - 1;
-                szTmp[1] = ':';
-            }
-            if (cchTmp != 1 || iRoot <= 2)
-                memcpy(&szTmp[iRoot], pachBuffer, cchTmp + 1);
+                pszNativePath[0] = ulDisk + 'A' - 1;
+                pszNativePath[1] = ':';
+            }
+            if (cchNativePath != 1 || iRoot <= 2)
+                memcpy(&pszNativePath[iRoot], pachBuffer, cchNativePath + 1);
             else
-                szTmp[iRoot] = szTmp[iRoot + 1] = '\0'; /* The +1 fixes '/' access in an compartement (pszPrev below). */
-            cchTmp += iRoot;
+                pszNativePath[iRoot] = pszNativePath[iRoot + 1] = '\0'; /* The +1 fixes '/' access in an compartement (pszPrev below). */
+            cchNativePath += iRoot;
         }
 
@@ -920,4 +939,5 @@
          * up with an optimal path in the end.
          */
+        /** @todo If we've retreived the current directory, we can safely save of the effort of validating it! */
 
         /*
@@ -926,8 +946,8 @@
         char *pszPrev;
         char *psz;
-        if (szTmp[0] == '/' && szTmp[1] == '/')
+        if (pszNativePath[0] == '/' && pszNativePath[1] == '/' && pszNativePath[2] != '/')
         {
             /* UNC - skip past the share name. */
-            psz = strchr(&szTmp[2], '/');
+            psz = strchr(&pszNativePath[2], '/');
             if (!psz)
             {
@@ -938,14 +958,14 @@
             if (!psz)
             {
-                strupr(szTmp);          /* The server + share is uppercased for consistant ino_t calculations. */
+                strupr(pszNativePath);  /* The server + share is uppercased for consistant ino_t calculations. */
                 rcRet = 0;
                 break;
             }
             *psz = '\0';                /* The server + share is uppercased for consistant ino_t calculations. */
-            strupr(szTmp);
+            strupr(pszNativePath);
             *psz = '/';
             pszPrev = ++psz;
             fInUnixTree = 0;            /* Unix root cannot be UNC. */
-            iRoot = psz - &szTmp[0];
+            iRoot = psz - pszNativePath;
             psz = strchr(psz, '/');
         }
@@ -953,16 +973,16 @@
         {
             /* drive letters are always uppercase! (inode dev number req) */
-            LIBC_ASSERT(szTmp[1] == ':');
-            if (szTmp[0] >= 'a' && szTmp[0] <= 'z')
-                szTmp[0] -= 'a' - 'A';
-            pszPrev = &szTmp[iRoot + 1];
+            LIBC_ASSERT(pszNativePath[1] == ':');
+            if (pszNativePath[0] >= 'a' && pszNativePath[0] <= 'z')
+                pszNativePath[0] -= 'a' - 'A';
+            pszPrev = &pszNativePath[iRoot + 1];
             psz = strchr(pszPrev, '/');
         }
-        LIBC_ASSERTM(pszPrev - &szTmp[0] >= iRoot, "iRoot=%d  pszPrev offset %d  szTmp=%s\n", iRoot, pszPrev - &szTmp[0], szTmp);
+        LIBC_ASSERTM(pszPrev - pszNativePath >= iRoot, "iRoot=%d  pszPrev offset %d  pszNativePath=%s\n", iRoot, pszPrev - pszNativePath, pszNativePath);
         /* If only one component, we'll check if the fVerifyLast was requested. */
         if (    !psz
             &&  (fFlags & (BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK))
             &&  *pszPrev)
-            psz = strchr(szTmp, '\0');
+            psz = strchr(pszNativePath, '\0');
 
         /*
@@ -983,5 +1003,5 @@
             {
                 if (    pszPrev[1] != '\0'
-                    &&  (uintptr_t)(pszPrev - &szTmp[0]) != iRoot + 1)
+                    &&  (uintptr_t)(pszPrev - pszNativePath) != iRoot + 1)
                 {
                     for (pszPrev -= 2; *pszPrev != '/'; pszPrev--)
@@ -990,6 +1010,6 @@
                 }
                 *psz = chSlash;
-                memmove(pszPrev - 1, psz, cchTmp - (psz - &szTmp[0]) + 1);
-                cchTmp -= psz - pszPrev - 1;
+                memmove(pszPrev - 1, psz, cchNativePath - (psz - pszNativePath) + 1);
+                cchNativePath -= psz - (pszPrev - 1);
 
                 /*
@@ -1036,5 +1056,5 @@
              * getting the caseing resolved.)
              */
-            LIBC_ASSERT(psz - szTmp == cchTmp);
+            LIBC_ASSERT(psz - pszNativePath == cchNativePath);
             PFILEFINDBUF4 pFindBuf = (PFILEFINDBUF4)pachBuffer;
             ULONG cFiles = 1;
@@ -1042,5 +1062,5 @@
             psz[0] = '?';
             psz[1] = '\0';
-            int rc = DosFindFirst((PCSZ)&szTmp[0], &hDir, FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED,
+            int rc = DosFindFirst((PCSZ)pszNativePath, &hDir, FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED,
                                   pFindBuf, SIZEOF_ACHBUFFER, &cFiles, FIL_QUERYEASIZE);
             psz[0] = '\0';
@@ -1054,5 +1074,5 @@
             if (rc || cFiles == 0)
             {
-                LIBCLOG_MSG("DosFindFirst/Next('%s',,,,,) -> %d resolving '%s'\n", szTmp, rc, pszUserPathIn);
+                LIBCLOG_MSG("DosFindFirst/Next('%s',,,,,) -> %d resolving '%s'\n", pszNativePath, rc, pszUserPathIn);
                 if ((fFlags & BACKFS_FLAGS_RESOLVE_FULL_MAYBE_) && !chSlash)
                 {
@@ -1085,8 +1105,8 @@
                 EaOp.oError     = 0;
                 EaOp.fpFEA2List->cbList = SIZEOF_ACHBUFFER;
-                rc = DosQueryPathInfo((PCSZ)&szTmp[0], FIL_QUERYEASFROMLIST, &EaOp, sizeof(EaOp));
+                rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASFROMLIST, &EaOp, sizeof(EaOp));
                 if (rc)
                 {
-                    LIBCLOG_MSG("DosQueryPathInfo('%s',,,) -> %d resolving '%s'\n", szTmp, rc, pszUserPathIn);
+                    LIBCLOG_MSG("DosQueryPathInfo('%s',,,) -> %d resolving '%s'\n", pszNativePath, rc, pszUserPathIn);
                     if ((fFlags & BACKFS_FLAGS_RESOLVE_FULL_MAYBE_) && !chSlash)
                         rcRet = 0;
@@ -1125,8 +1145,8 @@
                     /* Cleanup the symlink and find it's length. */
                     pszSymlink[pusType[1]] = '\0';
-                    int cchSymlink = fsCleanPath(pszSymlink, fFlags);
+                    int cchSymlink = fsCleanPath(pszSymlink, fFlags, NULL);
 
                     /* Merge symlink with the path. */
-                    int cchLeft = cchTmp - (psz - &szTmp[0]);
+                    int cchLeft = cchNativePath - (psz - pszNativePath);
                     if (*pszSymlink == '/' || *pszSymlink == '\\' || pszSymlink[1] == ':')
                     {
@@ -1156,5 +1176,5 @@
                          * Squeeze the symlink in instead of the current path component.
                          */
-                        if (cchSymlink + cchTmp + 2 >= PATH_MAX)
+                        if (cchSymlink + cchNativePath + 2 >= PATH_MAX)
                         {
                             rcRet = -ENAMETOOLONG;
@@ -1190,10 +1210,10 @@
 
             /*
-             * If we get here it was not a symlink and we should check if the directoryness
+             * If we get here it was not a symlink and we should check how the directoryness
              * of it fit's into the big picture...
              */
             if (!fIsDirectory && chSlash)
             {
-                LIBCLOG_MSG("'%s' is not a directory (resolving '%s')\n", szTmp, pszUserPathIn);
+                LIBCLOG_MSG("'%s' is not a directory (resolving '%s')\n", pszNativePath, pszUserPathIn);
                 rcRet = -ENOTDIR;
                 break;
@@ -1207,4 +1227,7 @@
             {
                 rcRet = 0;
+                if (    (fFlags & (BACKFS_FLAGS_RESOLVE_DIR | BACKFS_FLAGS_RESOLVE_DIR_MAYBE_)) == BACKFS_FLAGS_RESOLVE_DIR
+                    &&  !fIsDirectory)
+                    rcRet = -ENOTDIR;
                 break;
             }
@@ -1241,11 +1264,10 @@
     if (!rcRet)
     {
-        int cch = strlen(szTmp) + 1;
-        if (cch == 1 || (cch == 3 && szTmp[1] == ':'))
-        {
-            szTmp[cch - 1] = '/';
-            szTmp[cch++] = '\0';
+        int cch = strlen(pszNativePath) + 1;
+        if (cch == 1 || (cch == 3 && pszNativePath[1] == ':'))
+        {
+            pszNativePath[cch - 1] = '/';
+            pszNativePath[cch] = '\0';
         }
-        memcpy(pszNativePath, szTmp, cch);
         if (pfInUnixTree)
             *pfInUnixTree = fInUnixTree;
@@ -1263,5 +1285,5 @@
  *
  * @returns 0 on success.
- * @returns -1 and errno on failure.
+ * @returns Negative error code (errno.h) on failiure.
  * @param   pszUserPath     The user path.
  * @parm    fFlags          Flags controlling the operation of the function.
@@ -1279,5 +1301,5 @@
      * Apply rewrite rule.
      */
-    int cch = __libc_PathRewrite(pszUserPath, pszNativePath, sizeof(pszNativePath));
+    int cch = __libc_PathRewrite(pszUserPath, pszNativePath, PATH_MAX);
     if (cch < 0)
         LIBCLOG_RETURN_INT(-EINVAL);
