Index: src/emx/include/InnoTekLIBC/backend.h =================================================================== --- src/emx/include/InnoTekLIBC/backend.h (revision 3803) +++ src/emx/include/InnoTekLIBC/backend.h (working copy) @@ -326,6 +326,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. @@ -377,6 +387,17 @@ int __libc_Back_fsFileModeSetFH(int fh, mode_t Mode); /** + * 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: src/emx/src/lib/libc.def =================================================================== --- src/emx/src/lib/libc.def (revision 3803) +++ src/emx/src/lib/libc.def (working copy) @@ -1962,3 +1962,7 @@ "___libc_Back_fsPathConf" @1959 "___libc_Back_ioPathConf" @1960 + + "___libc_Back_fsFileOwnerSet" @1961 + "___libc_Back_fsFileOwnerSetFH" @1962 + "___libc_Back_fsSymlinkOwnerSet" @1963 Index: src/emx/src/lib/misc/chown.c =================================================================== --- src/emx/src/lib/misc/chown.c (revision 3803) +++ src/emx/src/lib/misc/chown.c (working copy) @@ -30,6 +30,7 @@ * Header Files * *******************************************************************************/ #include "libc-alias.h" +#include #include #include #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: src/emx/src/lib/io/lchown.c =================================================================== --- src/emx/src/lib/io/lchown.c (revision 3803) +++ src/emx/src/lib/io/lchown.c (working copy) @@ -30,6 +30,7 @@ * Header Files * *******************************************************************************/ #include "libc-alias.h" +#include #include #include #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); } Index: src/emx/src/lib/sys/b_fsSymlinkModeSet.c =================================================================== --- src/emx/src/lib/sys/b_fsSymlinkModeSet.c (revision 3803) +++ src/emx/src/lib/sys/b_fsSymlinkModeSet.c (working copy) @@ -59,3 +59,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: src/emx/src/lib/sys/b_fsFileModeSet.c =================================================================== --- src/emx/src/lib/sys/b_fsFileModeSet.c (revision 3803) +++ src/emx/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/emx/src/lib/sys/b_fsNativeFileModeSet.c =================================================================== --- src/emx/src/lib/sys/b_fsNativeFileModeSet.c (revision 3803) +++ src/emx/src/lib/sys/b_fsNativeFileModeSet.c (working copy) @@ -227,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/emx/src/lib/sys/b_fs.h =================================================================== --- src/emx/src/lib/sys/b_fs.h (revision 3803) +++ src/emx/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/emx/src/lib/sys/b_fsFileModeSetFH.c =================================================================== --- src/emx/src/lib/sys/b_fsFileModeSetFH.c (revision 3803) +++ src/emx/src/lib/sys/b_fsFileModeSetFH.c (working copy) @@ -213,3 +213,161 @@ 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); +}