Index: libc/include/klibc/backend.h
===================================================================
--- libc/include/klibc/backend.h	(revision 3803)
+++ libc/include/klibc/backend.h	(working copy)
@@ -401,6 +401,16 @@
 int __libc_Back_fsSymlinkModeSet(const char *pszPath, mode_t Mode);
 
 /**
+ * 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);
+
+/**
  * Sets the file times of a symlink.
  *
  * @returns 0 on success.
@@ -452,6 +462,17 @@
 int __libc_Back_fsFileModeSetFH(int fh, mode_t fMode);
 
 /**
+ * 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);
+
+/**
  * Sets the file the times of a file.
  *
  * @returns 0 on success.
Index: libc/src/kNIX/b_fsFileModeSetFH.c
===================================================================
--- libc/src/kNIX/b_fsFileModeSetFH.c	(revision 3803)
+++ libc/src/kNIX/b_fsFileModeSetFH.c	(working copy)
@@ -61,3 +61,172 @@
 }
 
 
+/**
+ * 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.
+     */
+    __LIBC_PFH pFH;
+    int rc = __libc_FHGet(fh, &pFH);
+    if (rc)
+    {
+        __libc_FHPut(pFH);
+        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 */
+            __libc_FHPut(pFH);
+            LIBCLOG_ERROR_RETURN_INT(-EINVAL);
+        /* ignore */
+        case F_DEV:
+            __libc_FHPut(pFH);
+            LIBCLOG_RETURN_INT(0);
+
+        /* use the path access. */
+        case F_DIR:
+            if (__predict_false(!pFH->pszNativePath))
+            {
+                __libc_FHPut(pFH);
+                LIBCLOG_ERROR_RETURN_INT(-EINVAL);
+            }
+            rc = __libc_back_fsNativeFileOwnerSet(pFH->pszNativePath, owner, group);
+            __libc_FHPut(pFH);
+            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_back_native2errno(rc);
+		}
+    
+	    if (__predict_false(rc != 0))
+	    {
+		FS_RESTORE();
+                __libc_FHPut(pFH);
+		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_back_native2errno(rc);
+		}
+    
+	    if (__predict_false(rc != 0))
+	    {
+		FS_RESTORE();
+                __libc_FHPut(pFH);
+		LIBCLOG_ERROR_RETURN_INT(rc);
+	    }
+	}
+  
+    FS_RESTORE();
+    }
+
+    __libc_FHPut(pFH);
+    LIBCLOG_RETURN_INT(0);
+}
Index: libc/src/kNIX/b_fsSymlinkModeSet.c
===================================================================
--- libc/src/kNIX/b_fsSymlinkModeSet.c	(revision 3803)
+++ libc/src/kNIX/b_fsSymlinkModeSet.c	(working copy)
@@ -53,3 +53,28 @@
     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: libc/src/kNIX/kNIX.h
===================================================================
--- libc/src/kNIX/kNIX.h	(revision 3803)
+++ libc/src/kNIX/kNIX.h	(working copy)
@@ -230,6 +230,7 @@
 int __libc_back_fsNativeSymlinkRead(const char *pszNativePath, char *pachBuf, size_t cchBuf);
 int __libc_back_fsNativeFileStat(const char *pszNativePath, struct stat *pStat);
 int __libc_back_fsNativeFileModeSet(const char *pszNativePath, mode_t Mode);
+int __libc_back_fsNativeFileOwnerSet(const char *pszNativePath, uid_t owner, gid_t group);
 int __libc_back_fsNativeFileTimesSet(const char *pszNativePath, const struct timeval *paTimes);
 dev_t __libc_back_fsPathCalcInodeAndDev(const char *pszNativePath, ino_t *pInode);
 __LIBC_PFSINFO __libc_back_fsInfoObjByDev(dev_t Dev);
Index: libc/src/kNIX/os2/b_fsNativeFileModeSet.c
===================================================================
--- libc/src/kNIX/os2/b_fsNativeFileModeSet.c	(revision 3803)
+++ libc/src/kNIX/os2/b_fsNativeFileModeSet.c	(working copy)
@@ -209,3 +209,141 @@
     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 */
+
+    /*
+     * 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_back_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_back_native2errno(rc);
+            }
+
+        if (__predict_false(rc != 0))
+        {
+            FS_RESTORE();
+            LIBCLOG_ERROR_RETURN_INT(rc);
+        }
+    }
+
+    FS_RESTORE();
+
+    LIBCLOG_RETURN_INT(0);
+}
Index: libc/src/kNIX/b_fsFileModeSet.c
===================================================================
--- libc/src/kNIX/b_fsFileModeSet.c	(revision 3803)
+++ libc/src/kNIX/b_fsFileModeSet.c	(working copy)
@@ -53,3 +53,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: libc/src/libc/misc/chown.c
===================================================================
--- libc/src/libc/misc/chown.c	(revision 3803)
+++ libc/src/libc/misc/chown.c	(working copy)
@@ -30,6 +30,7 @@
 *   Header Files                                                               *
 *******************************************************************************/
 #include "libc-alias.h"
+#include <errno.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_IO
@@ -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.
@@ -52,9 +51,10 @@
 {
     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: libc/src/libc/libc.def
===================================================================
--- libc/src/libc/libc.def	(revision 3803)
+++ libc/src/libc/libc.def	(working copy)
@@ -2000,3 +2000,7 @@
     "___libc_TermProcess" @1996
     "___libc_Back_fsPathConf" @1997
     "___libc_Back_ioPathConf" @1998
+
+    "___libc_Back_fsFileOwnerSet" @1999
+    "___libc_Back_fsFileOwnerSetFH" @2000
+    "___libc_Back_fsSymlinkOwnerSet" @2001
Index: libc/src/libc/io/lchown.c
===================================================================
--- libc/src/libc/io/lchown.c	(revision 3803)
+++ libc/src/libc/io/lchown.c	(working copy)
@@ -30,6 +30,7 @@
 *   Header Files                                                               *
 *******************************************************************************/
 #include "libc-alias.h"
+#include <errno.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_IO
@@ -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.
@@ -52,9 +51,10 @@
 {
     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);
 }
 
