Index: src/lib/libc.def
===================================================================
--- src/lib/libc.def	(revision 3650)
+++ src/lib/libc.def	(working copy)
@@ -1960,3 +1960,6 @@
     "___libc_Back_signalLostPoke" @1958
 
 
+    "___libc_Back_fsFileOwnerSet" @1959
+    "___libc_Back_fsFileOwnerSetFH" @1960
+    "___libc_Back_fsSymlinkOwnerSet" @1961
Index: src/lib/misc/chown.c
===================================================================
--- src/lib/misc/chown.c	(revision 3650)
+++ src/lib/misc/chown.c	(working copy)
@@ -32,6 +32,7 @@
 #include "libc-alias.h"
 #include <unistd.h>
 #include <sys/stat.h>
+#include <errno.h>
 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_IO
 #include <InnoTekLIBC/logstrict.h>
 
@@ -40,8 +41,6 @@
 /**
  * Change the owner and group over a file.
  *
- * This is stub. It only validates the path and returns without changing anything.
- *
  * @returns 0 on success.
  * @returns -1 and errno on failure.
  * @param   path    Path to the file to change owner/group of.
@@ -51,10 +50,9 @@
 int	 _STD(chown)(const char *path, uid_t owner, gid_t group)
 {
     LIBCLOG_ENTER("path=%p:{%s} owner=%d group=%d\n", (void *)path, path, owner, group);
-    struct stat st;
-    int rc = stat(path, &st);
+    int rc = __libc_Back_fsFileOwnerSet(path, owner, group);
     if (!rc)
-        LIBCLOG_RETURN_INT(rc);
-    LIBCLOG_ERROR_RETURN_INT(rc);
+        LIBCLOG_RETURN_INT(0);
+    errno = -rc;
+    LIBCLOG_ERROR_RETURN_INT(-1);
 }
-
Index: src/lib/io/lchown.c
===================================================================
--- src/lib/io/lchown.c	(revision 3650)
+++ src/lib/io/lchown.c	(working copy)
@@ -32,6 +32,7 @@
 #include "libc-alias.h"
 #include <unistd.h>
 #include <sys/stat.h>
+#include <errno.h>
 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_IO
 #include <InnoTekLIBC/logstrict.h>
 
@@ -40,8 +41,6 @@
 /**
  * Change the owner and group over a symbolic link.
  *
- * This is stub. It only validates the path and returns without changing anything.
- *
  * @returns 0 on success.
  * @returns -1 and errno on failure.
  * @param   path    Path to the link to change owner/group of.
@@ -51,10 +50,9 @@
 int	 _STD(lchown)(const char *path, uid_t owner, gid_t group)
 {
     LIBCLOG_ENTER("path=%p:{%s} owner=%d group=%d\n", (void *)path, path, owner, group);
-    struct stat st;
-    int rc = lstat(path, &st);
+    int rc = __libc_Back_fsSymlinkOwnerSet(path, owner, group);
     if (!rc)
         LIBCLOG_RETURN_INT(0);
+    errno = -rc;
     LIBCLOG_ERROR_RETURN_INT(-1);
 }
-
Index: src/lib/sys/b_fsSymlinkModeSet.c
===================================================================
--- src/lib/sys/b_fsSymlinkModeSet.c	(revision 3650)
+++ src/lib/sys/b_fsSymlinkModeSet.c	(working copy)
@@ -59,3 +59,29 @@
     LIBCLOG_ERROR_RETURN_INT(rc);
 }
 
+
+/**
+ * Sets the file group/owner of a file.
+ *
+ * @returns 0 on success.
+ * @returns Negative error code (errno.h) on failure.
+ * @param   fh      Handle to file.
+ * @param   Mode    The filemode.
+ */
+int __libc_Back_fsSymlinkOwnerSet(const char *pszPath, uid_t owner, gid_t group)
+{
+    LIBCLOG_ENTER("pszPath=%p:{%s} Owner=%#d Group=%#d\n", (void *)pszPath, pszPath, owner, group);
+
+    /*
+     * Resolve the path.
+     */
+    char szNativePath[PATH_MAX];
+    int rc = __libc_back_fsResolve(pszPath, BACKFS_FLAGS_RESOLVE_FULL_SYMLINK | BACKFS_FLAGS_RESOLVE_DIR_MAYBE, szNativePath, NULL);
+    if (!rc)
+        rc = __libc_back_fsNativeFileOwnerSet(szNativePath, owner, group);
+
+    if (!rc)
+        LIBCLOG_RETURN_INT(rc);
+    LIBCLOG_ERROR_RETURN_INT(rc);
+}
+
Index: src/lib/sys/b_fsFileModeSet.c
===================================================================
--- src/lib/sys/b_fsFileModeSet.c	(revision 3650)
+++ src/lib/sys/b_fsFileModeSet.c	(working copy)
@@ -59,3 +59,29 @@
     LIBCLOG_ERROR_RETURN_INT(rc);
 }
 
+
+/**
+ * Sets the file group/owner of a file.
+ *
+ * @returns 0 on success.
+ * @returns Negative error code (errno.h) on failure.
+ * @param   pszPath The path to the file to set the mode of.
+ * @param   owner    The new owner, if -1 do not change it.
+ * @param   group    The new group, if -1 do not change it.
+ */
+int __libc_Back_fsFileOwnerSet(const char *pszPath, uid_t owner, gid_t group)
+{
+    LIBCLOG_ENTER("pszPath=%p:{%s} Owner=%#d Owner=%#d\n", (void *)pszPath, pszPath, owner, group);
+
+    /*
+     * Resolve the path.
+     */
+    char szNativePath[PATH_MAX];
+    int rc = __libc_back_fsResolve(pszPath, BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_DIR_MAYBE, szNativePath, NULL);
+    if (!rc)
+        rc = __libc_back_fsNativeFileOwnerSet(szNativePath, owner, group);
+
+    if (!rc)
+        LIBCLOG_RETURN_INT(rc);
+    LIBCLOG_ERROR_RETURN_INT(rc);
+}
Index: src/lib/sys/b_fsNativeFileModeSet.c
===================================================================
--- src/lib/sys/b_fsNativeFileModeSet.c	(revision 3650)
+++ src/lib/sys/b_fsNativeFileModeSet.c	(working copy)
@@ -214,3 +227,148 @@
     LIBCLOG_RETURN_INT(0);
 }
 
+/**
+ * Sets the file group/owner of a native file.
+ *
+ * @returns 0 on success.
+ * @returns Negative error code (errno.h) on failure.
+ * @param   pszNativePath   Path to the file to change.
+ * @param   owner    The new owner, if -1 do not change it.
+ * @param   group    The new group, if -1 do not change it.
+ */
+int __libc_back_fsNativeFileOwnerSet(const char *pszNativePath, uid_t owner, gid_t group)
+{
+    LIBCLOG_ENTER("pszNativePath=%p:{%s} Owner=%#d Group=%#d\n", (void *)pszNativePath, pszNativePath, owner, group);
+    FS_VAR();
+
+    /*
+     * Validate input, refusing named pipes.
+     */
+    if (    (pszNativePath[0] == '/' || pszNativePath[0] == '\\')
+        &&  (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] == '\\'))
+        LIBCLOG_ERROR_RETURN_INT(-ENOENT);
+
+    /*
+     * If potential device, then perform real check.
+     * (Devices are subject to mode in POSIX.)
+     */
+    /** @todo copy device check from the path resolver. */
+
+    /** @todo YD add right access check */
+
+    /*
+     * This call isn't available in Non-Unix mode - we don't handle symlinks there.
+     * YD true?
+     */
+    if (__predict_false(__libc_gfNoUnix != 0))
+        LIBCLOG_ERROR_RETURN(-ENOSYS, "ret -ENOSYS - __libc_gfNoUnix=%d\n", __libc_gfNoUnix);
+
+    /*
+     * Do we have UnixEAs on this path?
+     */
+    if (__predict_false(!__libc_back_fsInfoSupportUnixEAs(pszNativePath)))
+        LIBCLOG_ERROR_RETURN(-ENOTSUP, "ret -ENOTSUP - no Unix EAs on '%s'\n", pszNativePath);
+
+    /*
+     * update owner if specified
+     */
+    FS_SAVE_LOAD();
+    int rc;
+    if (owner != -1)
+    {
+            /* construct FEA2 stuff. */
+            #pragma pack(1)
+            struct __LIBC_FSUNIXATTRIBSSETMODE
+            {
+                ULONG   cbList;
+                ULONG   off;
+                BYTE    fEA;
+                BYTE    cbName;
+                USHORT  cbValue;
+                CHAR    szName[sizeof(EA_UID)];
+                USHORT  usType;
+                USHORT  cbData;
+                uint32_t u32Mode;
+            } EAs =
+            {
+                sizeof(EAs), 0, FEA_NEEDEA, sizeof(EA_UID) - 1, sizeof(uint32_t) + 4, EA_UID, EAT_BINARY, sizeof(uint32_t), owner
+            };
+            #pragma pack()
+            EAOP2 EaOp2;
+            EaOp2.fpGEA2List = NULL;
+            EaOp2.fpFEA2List = (PFEA2LIST)&EAs;
+            EaOp2.oError = 0;
+
+            /* finally, try update / add the EA. */
+            rc = DosSetPathInfo((PCSZ)pszNativePath, FIL_QUERYEASIZE, &EaOp2, sizeof(EaOp2), 0);
+            if (__predict_false(rc != NO_ERROR))
+            {
+                LIBCLOG_ERROR("DosSetPathInfo('%s',,,,) -> %d, oError=%#lx\n", pszNativePath, rc, EaOp2.oError);
+                if (rc == ERROR_EAS_NOT_SUPPORTED)
+                    rc = 0;
+                else
+                    rc = -__libc_native2errno(rc);
+            }
+
+        if (__predict_false(rc != 0))
+        {
+            FS_RESTORE();
+            LIBCLOG_ERROR_RETURN_INT(rc);
+        }
+    }
+    
+    /*
+     * update group if specified
+     */
+    if (group != -1)
+    {
+            /* construct FEA2 stuff. */
+            #pragma pack(1)
+            struct __LIBC_FSUNIXATTRIBSSETMODE
+            {
+                ULONG   cbList;
+                ULONG   off;
+                BYTE    fEA;
+                BYTE    cbName;
+                USHORT  cbValue;
+                CHAR    szName[sizeof(EA_GID)];
+                USHORT  usType;
+                USHORT  cbData;
+                uint32_t u32Mode;
+            } EAs =
+            {
+                sizeof(EAs), 0, FEA_NEEDEA, sizeof(EA_GID) - 1, sizeof(uint32_t) + 4, EA_GID, EAT_BINARY, sizeof(uint32_t), group
+            };
+            #pragma pack()
+            EAOP2 EaOp2;
+            EaOp2.fpGEA2List = NULL;
+            EaOp2.fpFEA2List = (PFEA2LIST)&EAs;
+            EaOp2.oError = 0;
+
+            /* finally, try update / add the EA. */
+            rc = DosSetPathInfo((PCSZ)pszNativePath, FIL_QUERYEASIZE, &EaOp2, sizeof(EaOp2), 0);
+            if (__predict_false(rc != NO_ERROR))
+            {
+                LIBCLOG_ERROR("DosSetPathInfo('%s',,,,) -> %d, oError=%#lx\n", pszNativePath, rc, EaOp2.oError);
+                if (rc == ERROR_EAS_NOT_SUPPORTED)
+                    rc = 0;
+                else
+                    rc = -__libc_native2errno(rc);
+            }
+
+        if (__predict_false(rc != 0))
+        {
+            FS_RESTORE();
+            LIBCLOG_ERROR_RETURN_INT(rc);
+        }
+    }
+
+    FS_RESTORE();
+
+    LIBCLOG_RETURN_INT(0);
+}
+
Index: src/lib/sys/b_fs.h
===================================================================
--- src/lib/sys/b_fs.h	(revision 3650)
+++ src/lib/sys/b_fs.h	(working copy)
@@ -388,12 +388,23 @@
  *
  * @returns 0 on success.
  * @returns Negative error code (errno.h) on failure.
- * @param   fh      Handle to file.
+ * @param   pszNativePath   Path to the file to change.
  * @param   Mode    The filemode.
  */
 int __libc_back_fsNativeFileModeSet(const char *pszNativePath, mode_t Mode);
 
 /**
+ * Sets the file group/owner of a native file.
+ *
+ * @returns 0 on success.
+ * @returns Negative error code (errno.h) on failure.
+ * @param   pszNativePath   Path to the file to change.
+ * @param   owner    The new owner, if -1 do not change it.
+ * @param   group    The new group, if -1 do not change it.
+ */
+int __libc_back_fsNativeFileOwnerSet(const char *pszNativePath, uid_t owner, gid_t group);
+
+/**
  * Sets the file times of a native file.
  *
  * @returns 0 on success.
Index: src/lib/sys/b_fsFileModeSetFH.c
===================================================================
--- src/lib/sys/b_fsFileModeSetFH.c	(revision 3650)
+++ src/lib/sys/b_fsFileModeSetFH.c	(working copy)
@@ -209,3 +209,163 @@
     LIBCLOG_RETURN_INT(0);
 }
 
+
+
+/**
+ * Sets the owner/group of a file by filehandle.
+ *
+ * @returns 0 on success.
+ * @returns Negative error code (errno.h) on failure.
+ * @param   fh      Handle to file.
+ * @param   owner    The new owner, if -1 do not change it.
+ * @param   group    The new group, if -1 do not change it.
+ */
+int __libc_Back_fsFileOwnerSetFH(int fh, uid_t owner, gid_t group)
+{
+    LIBCLOG_ENTER("fh=%d Owner=%#d Group=%#d\n", fh, owner, group);
+
+    /*
+     * Get filehandle.
+     */
+    PLIBCFH pFH;
+    int rc = __libc_FHEx(fh, &pFH);
+    if (rc)
+        LIBCLOG_ERROR_RETURN_INT(rc);
+
+    /*
+     * Check the type.
+     */
+    switch (pFH->fFlags & __LIBC_FH_TYPEMASK)
+    {
+        /* fail */
+        case F_SOCKET:
+        case F_PIPE: /* treat as socket for now */
+            LIBCLOG_ERROR_RETURN_INT(-EINVAL);
+        /* ignore */
+        case F_DEV:
+            LIBCLOG_RETURN_INT(0);
+
+        /* use the path access. */
+        case F_DIR:
+            if (__predict_false(!pFH->pszNativePath))
+                LIBCLOG_ERROR_RETURN_INT(-EINVAL);
+            rc = __libc_back_fsNativeFileOwnerSet(pFH->pszNativePath, owner, group);
+            if (rc)
+                LIBCLOG_ERROR_RETURN_INT(rc);
+            LIBCLOG_RETURN_INT(rc);
+
+        /* treat */
+        default:
+        case F_FILE:
+            break;
+    }
+
+    /** @todo YD add right access check */
+
+    if (!pFH->pOps)
+    {
+        /*
+         * Standard OS/2 file handle.
+         */
+        FS_VAR();
+        FS_SAVE_LOAD();
+	/*
+	 * update owner if specified
+	 */
+	FS_SAVE_LOAD();
+	int rc;
+	if (owner != -1)
+	{
+		/* construct FEA2 stuff. */
+		#pragma pack(1)
+		struct __LIBC_FSUNIXATTRIBSSETMODE
+		{
+		    ULONG   cbList;
+		    ULONG   off;
+		    BYTE    fEA;
+		    BYTE    cbName;
+		    USHORT  cbValue;
+		    CHAR    szName[sizeof(EA_UID)];
+		    USHORT  usType;
+		    USHORT  cbData;
+		    uint32_t u32Mode;
+		} EAs =
+		{
+		    sizeof(EAs), 0, FEA_NEEDEA, sizeof(EA_UID) - 1, sizeof(uint32_t) + 4, EA_UID, EAT_BINARY, sizeof(uint32_t), owner
+		};
+		#pragma pack()
+		EAOP2 EaOp2;
+		EaOp2.fpGEA2List = NULL;
+		EaOp2.fpFEA2List = (PFEA2LIST)&EAs;
+		EaOp2.oError = 0;
+    
+		/* finally, try update / add the EA. */
+		rc = DosSetFileInfo(fh, FIL_QUERYEASIZE, &EaOp2, sizeof(EaOp2));
+		if (__predict_false(rc != NO_ERROR))
+		{
+		    LIBCLOG_ERROR("DosSetFileInfo('%d',,,,) -> %d, oError=%#lx\n", fh, rc, EaOp2.oError);
+		    if (rc == ERROR_EAS_NOT_SUPPORTED)
+			rc = 0;
+		    else
+			rc = -__libc_native2errno(rc);
+		}
+    
+	    if (__predict_false(rc != 0))
+	    {
+		FS_RESTORE();
+		LIBCLOG_ERROR_RETURN_INT(rc);
+	    }
+	}
+	
+	/*
+	 * update group if specified
+	 */
+	if (group != -1)
+	{
+		/* construct FEA2 stuff. */
+		#pragma pack(1)
+		struct __LIBC_FSUNIXATTRIBSSETMODE
+		{
+		    ULONG   cbList;
+		    ULONG   off;
+		    BYTE    fEA;
+		    BYTE    cbName;
+		    USHORT  cbValue;
+		    CHAR    szName[sizeof(EA_GID)];
+		    USHORT  usType;
+		    USHORT  cbData;
+		    uint32_t u32Mode;
+		} EAs =
+		{
+		    sizeof(EAs), 0, FEA_NEEDEA, sizeof(EA_GID) - 1, sizeof(uint32_t) + 4, EA_GID, EAT_BINARY, sizeof(uint32_t), group
+		};
+		#pragma pack()
+		EAOP2 EaOp2;
+		EaOp2.fpGEA2List = NULL;
+		EaOp2.fpFEA2List = (PFEA2LIST)&EAs;
+		EaOp2.oError = 0;
+    
+		/* finally, try update / add the EA. */
+		rc = DosSetFileInfo(fh, FIL_QUERYEASIZE, &EaOp2, sizeof(EaOp2));
+		if (__predict_false(rc != NO_ERROR))
+		{
+		    LIBCLOG_ERROR("DosSetFileInfo('%d',,,,) -> %d, oError=%#lx\n", fh, rc, EaOp2.oError);
+		    if (rc == ERROR_EAS_NOT_SUPPORTED)
+			rc = 0;
+		    else
+			rc = -__libc_native2errno(rc);
+		}
+    
+	    if (__predict_false(rc != 0))
+	    {
+		FS_RESTORE();
+		LIBCLOG_ERROR_RETURN_INT(rc);
+	    }
+	}
+  
+    FS_RESTORE();
+    }
+
+    LIBCLOG_RETURN_INT(0);
+}
+
