path-posix.cpp revision 11e38fb5c81f04067f310efc4cdeb604bb462585
637712559132d2b3617aea0103fb0385978da14evboxsync/* $Id$ */
637712559132d2b3617aea0103fb0385978da14evboxsync/** @file
4efd24e631e5312d1fb78ae7ccaf9de912ff0e9fvboxsync * IPRT - Path Manipulation, POSIX.
637712559132d2b3617aea0103fb0385978da14evboxsync */
637712559132d2b3617aea0103fb0385978da14evboxsync
637712559132d2b3617aea0103fb0385978da14evboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
637712559132d2b3617aea0103fb0385978da14evboxsync *
637712559132d2b3617aea0103fb0385978da14evboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
637712559132d2b3617aea0103fb0385978da14evboxsync * available from http://www.virtualbox.org. This file is free software;
637712559132d2b3617aea0103fb0385978da14evboxsync * you can redistribute it and/or modify it under the terms of the GNU
637712559132d2b3617aea0103fb0385978da14evboxsync * General Public License (GPL) as published by the Free Software
637712559132d2b3617aea0103fb0385978da14evboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
637712559132d2b3617aea0103fb0385978da14evboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
637712559132d2b3617aea0103fb0385978da14evboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
637712559132d2b3617aea0103fb0385978da14evboxsync *
637712559132d2b3617aea0103fb0385978da14evboxsync * The contents of this file may alternatively be used under the terms
637712559132d2b3617aea0103fb0385978da14evboxsync * of the Common Development and Distribution License Version 1.0
637712559132d2b3617aea0103fb0385978da14evboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
637712559132d2b3617aea0103fb0385978da14evboxsync * VirtualBox OSE distribution, in which case the provisions of the
637712559132d2b3617aea0103fb0385978da14evboxsync * CDDL are applicable instead of those of the GPL.
637712559132d2b3617aea0103fb0385978da14evboxsync *
637712559132d2b3617aea0103fb0385978da14evboxsync * You may elect to license modified versions of this file under the
637712559132d2b3617aea0103fb0385978da14evboxsync * terms and conditions of either the GPL or the CDDL or both.
637712559132d2b3617aea0103fb0385978da14evboxsync *
637712559132d2b3617aea0103fb0385978da14evboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
637712559132d2b3617aea0103fb0385978da14evboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
637712559132d2b3617aea0103fb0385978da14evboxsync * additional information or have any questions.
637712559132d2b3617aea0103fb0385978da14evboxsync */
637712559132d2b3617aea0103fb0385978da14evboxsync
637712559132d2b3617aea0103fb0385978da14evboxsync
637712559132d2b3617aea0103fb0385978da14evboxsync/*******************************************************************************
637712559132d2b3617aea0103fb0385978da14evboxsync* Header Files *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync*******************************************************************************/
637712559132d2b3617aea0103fb0385978da14evboxsync#define LOG_GROUP RTLOGGROUP_PATH
637712559132d2b3617aea0103fb0385978da14evboxsync#include <stdlib.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include <limits.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include <errno.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include <unistd.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include <sys/stat.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include <sys/time.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include <stdio.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include <sys/types.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include <pwd.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include <iprt/path.h>
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync#include <iprt/env.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include <iprt/assert.h>
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync#include <iprt/string.h>
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync#include <iprt/err.h>
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync#include <iprt/log.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include "internal/path.h"
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include "internal/process.h"
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include "internal/fs.h"
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#ifdef RT_OS_L4
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync# include <l4/vboxserver/vboxserver.h>
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#endif
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncRTDECL(int) RTPathReal(const char *pszPath, char *pszRealPath, size_t cchRealPath)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Convert input.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync char *pszNativePath;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync int rc = rtPathToNative(&pszNativePath, pszPath);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (RT_SUCCESS(rc))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * On POSIX platforms the API doesn't take a length parameter, which makes it
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * a little bit more work.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync char szTmpPath[PATH_MAX + 1];
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync const char *psz = realpath(pszNativePath, szTmpPath);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (psz)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Convert result and copy it to the return buffer.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync char *pszUtf8RealPath;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = rtPathFromNative(&pszUtf8RealPath, szTmpPath);
637712559132d2b3617aea0103fb0385978da14evboxsync if (RT_SUCCESS(rc))
637712559132d2b3617aea0103fb0385978da14evboxsync {
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync size_t cch = strlen(pszUtf8RealPath) + 1;
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync if (cch <= cchRealPath)
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync memcpy(pszRealPath, pszUtf8RealPath, cch);
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync else
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync rc = VERR_BUFFER_OVERFLOW;
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync RTStrFree(pszUtf8RealPath);
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync }
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync }
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync else
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync rc = RTErrConvertFromErrno(errno);
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync RTStrFree(pszNativePath);
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync }
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync LogFlow(("RTPathReal(%p:{%s}, %p:{%s}, %u): returns %Rrc\n", pszPath, pszPath,
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync pszRealPath, RT_SUCCESS(rc) ? pszRealPath : "<failed>", cchRealPath));
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync return rc;
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync}
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync/**
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync * Cleans up a path specifier a little bit.
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync * This includes removing duplicate slashes, uncessary single dots, and
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync * trailing slashes. Also, replaces all RTPATH_SLASH characters with '/'.
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync *
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync * @returns Number of bytes in the clean path.
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync * @param pszPath The path to cleanup.
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync */
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsyncstatic int fsCleanPath(char *pszPath)
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync{
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync /*
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync * Change to '/' and remove duplicates.
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync */
637712559132d2b3617aea0103fb0385978da14evboxsync char *pszSrc = pszPath;
637712559132d2b3617aea0103fb0385978da14evboxsync char *pszTrg = pszPath;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#ifdef HAVE_UNC
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync int fUnc = 0;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if ( RTPATH_IS_SLASH(pszPath[0])
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync && RTPATH_IS_SLASH(pszPath[1]))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync { /* Skip first slash in a unc path. */
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync pszSrc++;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *pszTrg++ = '/';
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync fUnc = 1;
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync }
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync#endif
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync for (;;)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync char ch = *pszSrc++;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (RTPATH_IS_SLASH(ch))
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync {
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync *pszTrg++ = '/';
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync for (;;)
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync {
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync do ch = *pszSrc++;
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync while (RTPATH_IS_SLASH(ch));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync /* Remove '/./' and '/.'. */
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync if (ch != '.' || (*pszSrc && !RTPATH_IS_SLASH(*pszSrc)))
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync break;
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync }
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync }
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync *pszTrg = ch;
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync if (!ch)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync break;
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync pszTrg++;
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync }
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync /*
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync * Remove trailing slash if the path may be pointing to a directory.
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync */
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync int cch = pszTrg - pszPath;
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync if ( cch > 1
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync && RTPATH_IS_SLASH(pszTrg[-1])
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync#ifdef HAVE_DRIVE
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync && !RTPATH_IS_VOLSEP(pszTrg[-2])
b2e185d7c946ed90402d1dd86b24c6d82d8e591bvboxsync#endif
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync && !RTPATH_IS_SLASH(pszTrg[-2]))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync pszPath[--cch] = '\0';
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return cch;
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync}
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsyncRTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cchAbsPath)
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync{
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync int rc;
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync /*
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync * Validation.
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync */
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync AssertPtr(pszAbsPath);
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync AssertPtr(pszPath);
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync if (RT_UNLIKELY(!*pszPath))
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync return VERR_INVALID_PARAMETER;
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync /*
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync * Make a clean working copy of the input.
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync */
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync size_t cchPath = strlen(pszPath);
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync if (cchPath > PATH_MAX)
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync {
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, cchAbsPath, VERR_FILENAME_TOO_LONG));
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync return VERR_FILENAME_TOO_LONG;
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync }
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync char szTmpPath[PATH_MAX + 1];
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync memcpy(szTmpPath, pszPath, cchPath + 1);
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync size_t cchTmpPath = fsCleanPath(szTmpPath);
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync /*
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync * Handle "." specially (fsCleanPath does).
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync */
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync if (szTmpPath[0] == '.' && !szTmpPath[1])
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return RTPathGetCurrent(pszAbsPath, cchAbsPath);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Do we have a root slash?
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
637712559132d2b3617aea0103fb0385978da14evboxsync char *pszCur = szTmpPath;
637712559132d2b3617aea0103fb0385978da14evboxsync#ifdef HAVE_DRIVE
637712559132d2b3617aea0103fb0385978da14evboxsync if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/')
637712559132d2b3617aea0103fb0385978da14evboxsync pszCur += 3;
637712559132d2b3617aea0103fb0385978da14evboxsync# ifdef HAVE_UNC
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else if (pszCur[0] == '/' && pszCur[1] == '/')
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync pszCur += 2;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync# endif
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#else /* !HAVE_DRIVE */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (pszCur[0] == '/')
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync pszCur += 1;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#endif /* !HAVE_DRIVE */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * No, prepend the current directory to the relative path.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync char szCurDir[RTPATH_MAX];
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = RTPathGetCurrent(szCurDir, sizeof(szCurDir));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertRCReturn(rc, rc);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync size_t cchCurDir = fsCleanPath(szCurDir); /* paranoia */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (cchCurDir + cchTmpPath + 1 > PATH_MAX)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, cchAbsPath, VERR_FILENAME_TOO_LONG));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return VERR_FILENAME_TOO_LONG;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync memmove(szTmpPath + cchCurDir + 1, szTmpPath, cchTmpPath + 1);
637712559132d2b3617aea0103fb0385978da14evboxsync memcpy(szTmpPath, szCurDir, cchCurDir);
637712559132d2b3617aea0103fb0385978da14evboxsync szTmpPath[cchCurDir] = '/';
33698994f509c2b3a92e81a828ee7a0e01b81de0vboxsync
33698994f509c2b3a92e81a828ee7a0e01b81de0vboxsync
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync#ifdef HAVE_DRIVE
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/')
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync pszCur += 3;
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync# ifdef HAVE_UNC
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync else if (pszCur[0] == '/' && pszCur[1] == '/')
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync pszCur += 2;
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync# endif
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync#else
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync if (pszCur[0] == '/')
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync pszCur += 1;
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync#endif
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync else
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync AssertMsgFailedReturn(("pszCur=%s\n", pszCur), VERR_INTERNAL_ERROR);
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync }
21a146e63ee0fdd6658cf0fb9ee378dacd5e416bvboxsync
21a146e63ee0fdd6658cf0fb9ee378dacd5e416bvboxsync char *pszTop = pszCur;
21a146e63ee0fdd6658cf0fb9ee378dacd5e416bvboxsync
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync /*
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync * Get rid of double dot path components by evaluating them.
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync */
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync for (;;)
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync {
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync if ( pszCur[0] == '.'
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync && pszCur[1] == '.'
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync && (!pszCur[2] || pszCur[2] == '/'))
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync {
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync /* rewind to the previous component if any */
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync char *pszPrev = pszCur - 1;
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync if (pszPrev > pszTop)
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync while (*--pszPrev != '/')
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync ;
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync AssertMsg(*pszPrev == '/', ("szTmpPath={%s}, pszPrev=+%u\n", szTmpPath, pszPrev - szTmpPath));
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync memmove(pszPrev, pszCur + 2, strlen(pszCur + 2) + 1);
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync pszCur = pszPrev;
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync }
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync else
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync {
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync /* advance to end of component. */
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync while (*pszCur && *pszCur != '/')
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync pszCur++;
eeee785f36554f67d8737506fb0fadbf683cf9dfvboxsync }
33698994f509c2b3a92e81a828ee7a0e01b81de0vboxsync
33698994f509c2b3a92e81a828ee7a0e01b81de0vboxsync if (!*pszCur)
637712559132d2b3617aea0103fb0385978da14evboxsync break;
637712559132d2b3617aea0103fb0385978da14evboxsync
637712559132d2b3617aea0103fb0385978da14evboxsync /* skip the slash */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync ++pszCur;
33698994f509c2b3a92e81a828ee7a0e01b81de0vboxsync }
33698994f509c2b3a92e81a828ee7a0e01b81de0vboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (pszCur < pszTop)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * We overwrote the root slash with '\0', restore it.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *pszCur++ = '/';
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *pszCur = '\0';
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else if (pszCur > pszTop && pszCur[-1] == '/')
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Extra trailing slash in a non-root path, remove it.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * (A bit questionable...)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *--pszCur = '\0';
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Copy the result to the user buffer.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync cchTmpPath = pszCur - szTmpPath;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (cchTmpPath < cchAbsPath)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync memcpy(pszAbsPath, szTmpPath, cchTmpPath + 1);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = VINF_SUCCESS;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = VERR_BUFFER_OVERFLOW;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync LogFlow(("RTPathAbs(%p:{%s}, %p:{%s}, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath,
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync RT_SUCCESS(rc) ? pszAbsPath : "<failed>", cchAbsPath, rc));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return rc;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#ifndef RT_OS_L4
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Worker for RTPathUserHome that looks up the home directory
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * using the getpwuid_r api.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @returns IPRT status code.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param pszPath The path buffer.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param cchPath The size of the buffer.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param uid The User ID to query the home directory of.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncstatic int rtPathUserHomeByPasswd(char *pszPath, size_t cchPath, uid_t uid)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * The getpwuid_r function uses the passed in buffer to "allocate" any
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * extra memory it needs. On some systems we should probably use the
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * sysconf function to find the appropriate buffer size, but since it won't
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * work everywhere we'll settle with a 5KB buffer and ASSUME that it'll
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * suffice for even the lengthiest user descriptions...
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync char achBuffer[5120];
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync struct passwd Passwd;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync struct passwd *pPasswd;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync memset(&Passwd, 0, sizeof(Passwd));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync int rc = getpwuid_r(uid, &Passwd, &achBuffer[0], sizeof(achBuffer), &pPasswd);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (rc != 0)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return RTErrConvertFromErrno(rc);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (!pPasswd) /* uid not found in /etc/passwd */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return VERR_PATH_NOT_FOUND;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Check that it isn't empty and that it exists.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync struct stat st;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if ( !pPasswd->pw_dir
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync || !*pPasswd->pw_dir
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync || stat(pPasswd->pw_dir, &st)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync || !S_ISDIR(st.st_mode))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return VERR_PATH_NOT_FOUND;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Convert it to UTF-8 and copy it to the return buffer.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync char *pszUtf8Path;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = rtPathFromNative(&pszUtf8Path, pPasswd->pw_dir);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (RT_SUCCESS(rc))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync size_t cchHome = strlen(pszUtf8Path);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (cchHome < cchPath)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync memcpy(pszPath, pszUtf8Path, cchHome + 1);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = VERR_BUFFER_OVERFLOW;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync RTStrFree(pszUtf8Path);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return rc;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#endif
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Worker for RTPathUserHome that looks up the home directory
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * using the HOME environment variable.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @returns IPRT status code.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param pszPath The path buffer.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param cchPath The size of the buffer.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncstatic int rtPathUserHomeByEnv(char *pszPath, size_t cchPath)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Get HOME env. var it and validate it's existance.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync int rc = VERR_PATH_NOT_FOUND;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync const char *pszHome = RTEnvGet("HOME");
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (pszHome)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync struct stat st;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if ( !stat(pszHome, &st)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync && S_ISDIR(st.st_mode))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Convert it to UTF-8 and copy it to the return buffer.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync char *pszUtf8Path;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = rtPathFromNative(&pszUtf8Path, pszHome);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (RT_SUCCESS(rc))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync size_t cchHome = strlen(pszUtf8Path);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (cchHome < cchPath)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync memcpy(pszPath, pszUtf8Path, cchHome + 1);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = VERR_BUFFER_OVERFLOW;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync RTStrFree(pszUtf8Path);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return rc;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncRTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync int rc;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#ifndef RT_OS_L4
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * We make an exception for the root user and use the system call
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * getpwuid_r to determine their initial home path instead of
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * reading it from the $HOME variable. This is because the $HOME
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * variable does not get changed by sudo (and possibly su and others)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * which can cause root-owned files to appear in user's home folders.
637712559132d2b3617aea0103fb0385978da14evboxsync */
637712559132d2b3617aea0103fb0385978da14evboxsync uid_t uid = geteuid();
637712559132d2b3617aea0103fb0385978da14evboxsync if (!uid)
637712559132d2b3617aea0103fb0385978da14evboxsync rc = rtPathUserHomeByPasswd(pszPath, cchPath, uid);
637712559132d2b3617aea0103fb0385978da14evboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = rtPathUserHomeByEnv(pszPath, cchPath);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * On failure, retry using the alternative method.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * (Should perhaps restrict the retry cases a bit more here...)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if ( RT_FAILURE(rc)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync && rc != VERR_BUFFER_OVERFLOW)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (!uid)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = rtPathUserHomeByEnv(pszPath, cchPath);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = rtPathUserHomeByPasswd(pszPath, cchPath, uid);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#else /* RT_OS_L4 */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = rtPathUserHomeByEnv(pszPath, cchPath);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#endif /* RT_OS_L4 */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync LogFlow(("RTPathUserHome(%p:{%s}, %u): returns %Rrc\n", pszPath,
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync RT_SUCCESS(rc) ? pszPath : "<failed>", cchPath, rc));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return rc;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncRTR3DECL(int) RTPathQueryInfo(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return RTPathQueryInfoEx(pszPath, pObjInfo, enmAdditionalAttribs, RTPATH_F_ON_LINK);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
637712559132d2b3617aea0103fb0385978da14evboxsync
637712559132d2b3617aea0103fb0385978da14evboxsyncRTR3DECL(int) RTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
637712559132d2b3617aea0103fb0385978da14evboxsync{
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /*
637712559132d2b3617aea0103fb0385978da14evboxsync * Validate input.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertPtrReturn(pObjInfo, VERR_INVALID_POINTER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertMsgReturn( enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync && enmAdditionalAttribs <= RTFSOBJATTRADD_LAST,
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync ("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs),
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync VERR_INVALID_PARAMETER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
9c901af82dd5443ef16e2412aa6109e1e3476325vboxsync
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Convert the filename.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync char *pszNativePath;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync int rc = rtPathToNative(&pszNativePath, pszPath);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (RT_SUCCESS(rc))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync struct stat Stat;
9c901af82dd5443ef16e2412aa6109e1e3476325vboxsync if (fFlags & RTPATH_F_FOLLOW_LINK)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = stat(pszNativePath, &Stat);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = lstat(pszNativePath, &Stat); /** @todo how doesn't have lstat again? */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (!rc)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rtFsConvertStatToObjInfo(pObjInfo, &Stat, pszPath, 0);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync switch (enmAdditionalAttribs)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync case RTFSOBJATTRADD_EASIZE:
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /** @todo Use SGI extended attribute interface to query EA info. */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync pObjInfo->Attr.u.EASize.cb = 0;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync break;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync case RTFSOBJATTRADD_NOTHING:
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync case RTFSOBJATTRADD_UNIX:
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync Assert(pObjInfo->Attr.enmAdditional == RTFSOBJATTRADD_UNIX);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync break;
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync default:
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertMsgFailed(("Impossible!\n"));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return VERR_INTERNAL_ERROR;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
637712559132d2b3617aea0103fb0385978da14evboxsync }
637712559132d2b3617aea0103fb0385978da14evboxsync else
637712559132d2b3617aea0103fb0385978da14evboxsync rc = RTErrConvertFromErrno(errno);
637712559132d2b3617aea0103fb0385978da14evboxsync rtPathFreeNative(pszNativePath);
637712559132d2b3617aea0103fb0385978da14evboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync LogFlow(("RTPathQueryInfo(%p:{%s}, pObjInfo=%p, %d): returns %Rrc\n",
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync pszPath, pszPath, pObjInfo, enmAdditionalAttribs, rc));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return rc;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncRTR3DECL(int) RTPathSetTimes(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync return RTPathSetTimesEx(pszPath, pAccessTime, pModificationTime, pChangeTime, pBirthTime, RTPATH_F_ON_LINK);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync
45c4c3d2db1a166b7b1e92960adb823960821386vboxsyncRTR3DECL(int) RTPathSetTimesEx(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags)
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync{
d142cd5e90598dd8d14744cb6bb7dd467cec446cvboxsync /*
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync * Validate input.
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync */
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertPtrNullReturn(pAccessTime, VERR_INVALID_POINTER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertPtrNullReturn(pModificationTime, VERR_INVALID_POINTER);
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync AssertPtrNullReturn(pChangeTime, VERR_INVALID_POINTER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertPtrNullReturn(pBirthTime, VERR_INVALID_POINTER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
637712559132d2b3617aea0103fb0385978da14evboxsync * Convert the paths.
637712559132d2b3617aea0103fb0385978da14evboxsync */
637712559132d2b3617aea0103fb0385978da14evboxsync char *pszNativePath;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync int rc = rtPathToNative(&pszNativePath, pszPath);
637712559132d2b3617aea0103fb0385978da14evboxsync if (RT_SUCCESS(rc))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync RTFSOBJINFO ObjInfo;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * If it's a no-op, we'll only verify the existance of the file.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (!pAccessTime && !pModificationTime)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, fFlags);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /*
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * Convert the input to timeval, getting the missing one if necessary,
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * and call the API which does the change.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync struct timeval aTimevals[2];
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (pAccessTime && pModificationTime)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync RTTimeSpecGetTimeval(pAccessTime, &aTimevals[0]);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync RTTimeSpecGetTimeval(pModificationTime, &aTimevals[1]);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, fFlags);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if (RT_SUCCESS(rc))
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTTimeSpecGetTimeval(pAccessTime ? pAccessTime : &ObjInfo.AccessTime, &aTimevals[0]);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTTimeSpecGetTimeval(pModificationTime ? pModificationTime : &ObjInfo.ModificationTime, &aTimevals[1]);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync else
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync Log(("RTPathSetTimes('%s',%p,%p,,): RTPathQueryInfo failed with %Rrc\n",
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync pszPath, pAccessTime, pModificationTime, rc));
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if (RT_SUCCESS(rc))
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (fFlags & RTPATH_F_FOLLOW_LINK)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (utimes(pszNativePath, aTimevals))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = RTErrConvertFromErrno(errno);
637712559132d2b3617aea0103fb0385978da14evboxsync }
637712559132d2b3617aea0103fb0385978da14evboxsync#if (defined(RT_OS_DARWIN) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) \
637712559132d2b3617aea0103fb0385978da14evboxsync || defined(RT_OS_FREEBSD) \
637712559132d2b3617aea0103fb0385978da14evboxsync || defined(RT_OS_LINUX) \
637712559132d2b3617aea0103fb0385978da14evboxsync || defined(RT_OS_OS2) /** @todo who really has lutimes? */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (lutimes(pszNativePath, aTimevals))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = RTErrConvertFromErrno(errno);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#else
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync else
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync {
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync if (pAccessTime && pModificationTime)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, fFlags);
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync if (RT_SUCCESS(rc) && RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = VERR_NS_SYMLINK_SET_TIME;
637712559132d2b3617aea0103fb0385978da14evboxsync else if (RT_SUCCESS(rc))
637712559132d2b3617aea0103fb0385978da14evboxsync {
637712559132d2b3617aea0103fb0385978da14evboxsync if (utimes(pszNativePath, aTimevals))
637712559132d2b3617aea0103fb0385978da14evboxsync rc = RTErrConvertFromErrno(errno);
637712559132d2b3617aea0103fb0385978da14evboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#endif
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (RT_FAILURE(rc))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync Log(("RTPathSetTimes('%s',%p,%p,,): failed with %Rrc and errno=%d\n",
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync pszPath, pAccessTime, pModificationTime, rc, errno));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rtPathFreeNative(pszNativePath);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync LogFlow(("RTPathSetTimes(%p:{%s}, %p:{%RDtimespec}, %p:{%RDtimespec}, %p:{%RDtimespec}, %p:{%RDtimespec}): return %Rrc\n",
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync pszPath, pszPath, pAccessTime, pAccessTime, pModificationTime, pModificationTime,
637712559132d2b3617aea0103fb0385978da14evboxsync pChangeTime, pChangeTime, pBirthTime, pBirthTime));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return rc;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Checks if two files are the one and same file.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncstatic bool rtPathSame(const char *pszNativeSrc, const char *pszNativeDst)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync struct stat SrcStat;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (stat(pszNativeSrc, &SrcStat))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return false;
637712559132d2b3617aea0103fb0385978da14evboxsync struct stat DstStat;
if (stat(pszNativeDst, &DstStat))
return false;
Assert(SrcStat.st_dev && DstStat.st_dev);
Assert(SrcStat.st_ino && DstStat.st_ino);
if ( SrcStat.st_dev == DstStat.st_dev
&& SrcStat.st_ino == DstStat.st_ino
&& (SrcStat.st_mode & S_IFMT) == (DstStat.st_mode & S_IFMT))
return true;
return false;
}
/**
* Worker for RTPathRename, RTDirRename, RTFileRename.
*
* @returns IPRT status code.
* @param pszSrc The source path.
* @param pszDst The destintation path.
* @param fRename The rename flags.
* @param fFileType The filetype. We use the RTFMODE filetypes here. If it's 0,
* anything goes. If it's RTFS_TYPE_DIRECTORY we'll check that the
* source is a directory. If Its RTFS_TYPE_FILE we'll check that it's
* not a directory (we are NOT checking whether it's a file).
*/
int rtPathPosixRename(const char *pszSrc, const char *pszDst, unsigned fRename, RTFMODE fFileType)
{
/*
* Convert the paths.
*/
char *pszNativeSrc;
int rc = rtPathToNative(&pszNativeSrc, pszSrc);
if (RT_SUCCESS(rc))
{
char *pszNativeDst;
rc = rtPathToNative(&pszNativeDst, pszDst);
if (RT_SUCCESS(rc))
{
/*
* Check that the source exists and that any types that's specified matches.
* We have to check this first to avoid getting errnous VERR_ALREADY_EXISTS
* errors from the next step.
*
* There are race conditions here (perhaps unlikly ones but still), but I'm
* afraid there is little with can do to fix that.
*/
struct stat SrcStat;
if (stat(pszNativeSrc, &SrcStat))
rc = RTErrConvertFromErrno(errno);
else if (!fFileType)
rc = VINF_SUCCESS;
else if (RTFS_IS_DIRECTORY(fFileType))
rc = S_ISDIR(SrcStat.st_mode) ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
else
rc = S_ISDIR(SrcStat.st_mode) ? VERR_IS_A_DIRECTORY : VINF_SUCCESS;
if (RT_SUCCESS(rc))
{
bool fSameFile = false;
/*
* Check if the target exists, rename is rather destructive.
* We'll have to make sure we don't overwrite the source!
* Another race condition btw.
*/
struct stat DstStat;
if (stat(pszNativeDst, &DstStat))
rc = errno == ENOENT ? VINF_SUCCESS : RTErrConvertFromErrno(errno);
else
{
Assert(SrcStat.st_dev && DstStat.st_dev);
Assert(SrcStat.st_ino && DstStat.st_ino);
if ( SrcStat.st_dev == DstStat.st_dev
&& SrcStat.st_ino == DstStat.st_ino
&& (SrcStat.st_mode & S_IFMT) == (SrcStat.st_mode & S_IFMT))
{
/*
* It's likely that we're talking about the same file here.
* We should probably check paths or whatever, but for now this'll have to be enough.
*/
fSameFile = true;
}
if (fSameFile)
rc = VINF_SUCCESS;
else if (S_ISDIR(DstStat.st_mode) || !(fRename & RTPATHRENAME_FLAGS_REPLACE))
rc = VERR_ALREADY_EXISTS;
else
rc = VINF_SUCCESS;
}
if (RT_SUCCESS(rc))
{
if (!rename(pszNativeSrc, pszNativeDst))
rc = VINF_SUCCESS;
else if ( (fRename & RTPATHRENAME_FLAGS_REPLACE)
&& (errno == ENOTDIR || errno == EEXIST))
{
/*
* Check that the destination isn't a directory.
* Yet another race condition.
*/
if (rtPathSame(pszNativeSrc, pszNativeDst))
{
rc = VINF_SUCCESS;
Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): appears to be the same file... (errno=%d)\n",
pszSrc, pszDst, fRename, fFileType, errno));
}
else
{
if (stat(pszNativeDst, &DstStat))
rc = errno != ENOENT ? RTErrConvertFromErrno(errno) : VINF_SUCCESS;
else if (S_ISDIR(DstStat.st_mode))
rc = VERR_ALREADY_EXISTS;
else
rc = VINF_SUCCESS;
if (RT_SUCCESS(rc))
{
if (!unlink(pszNativeDst))
{
if (!rename(pszNativeSrc, pszNativeDst))
rc = VINF_SUCCESS;
else
{
rc = RTErrConvertFromErrno(errno);
Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): rename failed rc=%Rrc errno=%d\n",
pszSrc, pszDst, fRename, fFileType, rc, errno));
}
}
else
{
rc = RTErrConvertFromErrno(errno);
Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): failed to unlink dst rc=%Rrc errno=%d\n",
pszSrc, pszDst, fRename, fFileType, rc, errno));
}
}
else
Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): dst !dir check failed rc=%Rrc\n",
pszSrc, pszDst, fRename, fFileType, rc));
}
}
else
{
rc = RTErrConvertFromErrno(errno);
if (errno == ENOTDIR)
rc = VERR_ALREADY_EXISTS; /* unless somebody is racing us, this is the right interpretation */
Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): rename failed rc=%Rrc errno=%d\n",
pszSrc, pszDst, fRename, fFileType, rc, errno));
}
}
else
Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): destination check failed rc=%Rrc errno=%d\n",
pszSrc, pszDst, fRename, fFileType, rc, errno));
}
else
Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): source type check failed rc=%Rrc errno=%d\n",
pszSrc, pszDst, fRename, fFileType, rc, errno));
rtPathFreeNative(pszNativeDst);
}
rtPathFreeNative(pszNativeSrc);
}
return rc;
}
RTR3DECL(int) RTPathRename(const char *pszSrc, const char *pszDst, unsigned fRename)
{
/*
* Validate input.
*/
AssertMsgReturn(VALID_PTR(pszSrc), ("%p\n", pszSrc), VERR_INVALID_POINTER);
AssertMsgReturn(VALID_PTR(pszDst), ("%p\n", pszDst), VERR_INVALID_POINTER);
AssertMsgReturn(*pszSrc, ("%p\n", pszSrc), VERR_INVALID_PARAMETER);
AssertMsgReturn(*pszDst, ("%p\n", pszDst), VERR_INVALID_PARAMETER);
AssertMsgReturn(!(fRename & ~RTPATHRENAME_FLAGS_REPLACE), ("%#x\n", fRename), VERR_INVALID_PARAMETER);
/*
* Hand it to the worker.
*/
int rc = rtPathPosixRename(pszSrc, pszDst, fRename, 0);
Log(("RTPathRename(%p:{%s}, %p:{%s}, %#x): returns %Rrc\n", pszSrc, pszSrc, pszDst, pszDst, fRename, rc));
return rc;
}
RTDECL(bool) RTPathExists(const char *pszPath)
{
return RTPathExistsEx(pszPath, RTPATH_F_FOLLOW_LINK);
}
RTDECL(bool) RTPathExistsEx(const char *pszPath, uint32_t fFlags)
{
/*
* Validate input.
*/
AssertPtrReturn(pszPath, false);
AssertReturn(*pszPath, false);
Assert(RTPATH_F_IS_VALID(fFlags, 0));
/*
* Convert the path and check if it exists using stat().
*/
char *pszNativePath;
int rc = rtPathToNative(&pszNativePath, pszPath);
if (RT_SUCCESS(rc))
{
struct stat Stat;
if (fFlags & RTPATH_F_FOLLOW_LINK)
rc = stat(pszNativePath, &Stat);
else
rc = lstat(pszNativePath, &Stat);
if (!rc)
rc = VINF_SUCCESS;
else
rc = VERR_GENERAL_FAILURE;
RTStrFree(pszNativePath);
}
return RT_SUCCESS(rc);
}
RTDECL(int) RTPathGetCurrent(char *pszPath, size_t cchPath)
{
int rc;
char szNativeCurDir[RTPATH_MAX];
if (getcwd(szNativeCurDir, sizeof(szNativeCurDir)) != NULL)
{
char *pszCurDir;
rc = rtPathFromNative(&pszCurDir, szNativeCurDir);
if (RT_SUCCESS(rc))
{
size_t cchCurDir = strlen(pszCurDir);
if (cchCurDir < cchPath)
{
memcpy(pszPath, pszCurDir, cchCurDir + 1);
RTStrFree(pszCurDir);
return VINF_SUCCESS;
}
rc = VERR_BUFFER_OVERFLOW;
RTStrFree(pszCurDir);
}
}
else
rc = RTErrConvertFromErrno(errno);
return rc;
}
RTDECL(int) RTPathSetCurrent(const char *pszPath)
{
/*
* Validate input.
*/
AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
/*
* Change the directory.
*/
char *pszNativePath;
int rc = rtPathToNative(&pszNativePath, pszPath);
if (RT_SUCCESS(rc))
{
if (chdir(pszNativePath))
rc = RTErrConvertFromErrno(errno);
RTStrFree(pszNativePath);
}
return rc;
}