/**
 * Changes the file mode of one file system object.
 *
 * @returns exit code
 * @param   pOpts               The chmod options.
 * @param   pszPath             The path to the file system object to change the
 *                              file mode of.
 */
static RTEXITCODE rtCmdChModOne(RTCMDCHMODOPTS const *pOpts, const char *pszPath)
{
    int         rc;
    RTFSOBJINFO ObjInfo;
    bool        fChanges = false;
    if (!pOpts->fAlwaysUseChainApi && !RTVfsChainIsSpec(pszPath) )
    {
        rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK);
        if (RT_SUCCESS(rc))
        {
            RTFMODE fNewMode = rtCmdMkModCalcNewMode(pOpts, ObjInfo.Attr.fMode);
            fChanges = fNewMode != ObjInfo.Attr.fMode;
            if (fChanges)
            {
                rc = RTPathSetMode(pszPath, fNewMode);
                if (RT_FAILURE(rc))
                    RTMsgError("RTPathSetMode failed on '%s' with fNewMode=%#x: %Rrc", pszPath, fNewMode, rc);
            }
        }
        else
            RTMsgError("RTPathQueryInfoEx failed on '%s': %Rrc", pszPath, rc);
    }
    else
    {
        RTVFSOBJ        hVfsObj;
        uint32_t        offError;
        RTERRINFOSTATIC ErrInfo;
        rc = RTVfsChainOpenObj(pszPath, RTFILE_O_ACCESS_ATTR_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
                               RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_CREATE_NOTHING | RTPATH_F_FOLLOW_LINK,
                               &hVfsObj, &offError, RTErrInfoInitStatic(&ErrInfo));
        if (RT_SUCCESS(rc))
        {
            rc = RTVfsObjQueryInfo(hVfsObj, &ObjInfo, RTFSOBJATTRADD_NOTHING);
            if (RT_SUCCESS(rc))
            {
                RTFMODE fNewMode = rtCmdMkModCalcNewMode(pOpts, ObjInfo.Attr.fMode);
                fChanges = fNewMode != ObjInfo.Attr.fMode;
                if (fChanges)
                {
                    rc = RTVfsObjSetMode(hVfsObj, fNewMode, RTCHMOD_SET_ALL_MASK);
                    if (RT_FAILURE(rc))
                        RTMsgError("RTVfsObjSetMode failed on '%s' with fNewMode=%#x: %Rrc", pszPath, fNewMode, rc);
                }
            }
            else
                RTVfsChainMsgError("RTVfsObjQueryInfo", pszPath, rc, offError, &ErrInfo.Core);
            RTVfsObjRelease(hVfsObj);
        }
        else
            RTVfsChainMsgError("RTVfsChainOpenObject", pszPath, rc, offError, &ErrInfo.Core);
    }

    if (RT_SUCCESS(rc))
    {
        if (pOpts->enmNoiseLevel >= (fChanges ? kRTCmdChModNoise_Changes : kRTCmdChModNoise_Verbose))
            RTPrintf("%s\n", pszPath);
        return RTEXITCODE_SUCCESS;
    }
    return RTEXITCODE_FAILURE;
}
static int VBoxServiceAutoMountPrepareMountPoint(const char *pszMountPoint, const char *pszShareName,
                                                 vbsf_mount_opts *pOpts)
{
    AssertPtrReturn(pOpts, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszMountPoint, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszShareName, VERR_INVALID_PARAMETER);

    RTFMODE fMode = RTFS_UNIX_IRWXU | RTFS_UNIX_IRWXG; /* Owner (=root) and the group (=vboxsf) have full access. */
    int rc = RTDirCreateFullPath(pszMountPoint, fMode);
    if (RT_SUCCESS(rc))
    {
        rc = RTPathSetOwnerEx(pszMountPoint, NIL_RTUID /* Owner, unchanged */, pOpts->gid, RTPATH_F_ON_LINK);
        if (RT_SUCCESS(rc))
        {
            rc = RTPathSetMode(pszMountPoint, fMode);
            if (RT_FAILURE(rc))
            {
                if (rc == VERR_WRITE_PROTECT)
                {
                    VBoxServiceVerbose(3, "VBoxServiceAutoMountPrepareMountPoint: Mount directory \"%s\" already is used/mounted\n", pszMountPoint);
                    rc = VINF_SUCCESS;
                }
                else
                    VBoxServiceError("VBoxServiceAutoMountPrepareMountPoint: Could not set mode %RTfmode for mount directory \"%s\", rc = %Rrc\n",
                                     fMode, pszMountPoint, rc);
            }
        }
        else
            VBoxServiceError("VBoxServiceAutoMountPrepareMountPoint: Could not set permissions for mount directory \"%s\", rc = %Rrc\n",
                             pszMountPoint, rc);
    }
    else
        VBoxServiceError("VBoxServiceAutoMountPrepareMountPoint: Could not create mount directory \"%s\" with mode %RTfmode, rc = %Rrc\n",
                         pszMountPoint, fMode, rc);
    return rc;
}