path-posix.cpp revision 6dc7df569c3c08b7304fc0905524d35a603507b7
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* $Id$ */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @file
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * innotek Portable Runtime - Path Manipulation, POSIX.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 innotek GmbH
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License as published by the Free Software Foundation,
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync */
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Header Files *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define LOG_GROUP RTLOGGROUP_PATH
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <stdlib.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <limits.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <errno.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <unistd.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <sys/stat.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <sys/time.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <stdio.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <sys/types.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <pwd.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef RT_OS_DARWIN
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# include <mach-o/dyld.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/path.h>
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync#include <iprt/assert.h>
e11fe099decbb0f65cfcc7e2939fa00bacefbb1cvboxsync#include <iprt/string.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/err.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/log.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "internal/path.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "internal/fs.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef RT_OS_L4
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# include <l4/vboxserver/vboxserver.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTPathReal(const char *pszPath, char *pszRealPath, unsigned cchRealPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Convert input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszNativePath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = rtPathToNative(&pszNativePath, pszPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * On POSIX platforms the API doesn't take a length parameter, which makes it
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * a little bit more work.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char szTmpPath[PATH_MAX + 1];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const char *psz = realpath(pszNativePath, szTmpPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (psz)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Convert result and copy it to the return buffer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszUtf8RealPath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = rtPathFromNative(&pszUtf8RealPath, szTmpPath);
cfb3a8ae5e9668de4506cf5c053b8009bcc89dafvboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync size_t cch = strlen(pszUtf8RealPath) + 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cch <= cchRealPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy(pszRealPath, pszUtf8RealPath, cch);
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_BUFFER_OVERFLOW;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync RTStrFree(pszUtf8RealPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync else
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync rc = RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTStrFree(pszNativePath);
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync }
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync LogFlow(("RTPathReal(%p:{%s}, %p:{%s}, %u): returns %Rrc\n", pszPath, pszPath,
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync pszRealPath, RT_SUCCESS(rc) ? pszRealPath : "<failed>", cchRealPath));
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync return rc;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync}
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Cleans up a path specifier a little bit.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This includes removing duplicate slashes, uncessary single dots, and
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * trailing slashes. Also, replaces all RTPATH_SLASH characters with '/'.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns Number of bytes in the clean path.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszPath The path to cleanup.
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync * @remark Borrowed from innotek libc.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int fsCleanPath(char *pszPath)
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync{
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync /*
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * Change to '/' and remove duplicates.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync char *pszSrc = pszPath;
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync char *pszTrg = pszPath;
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync#ifdef HAVE_UNC
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync int fUnc = 0;
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync if ( RTPATH_IS_SLASH(pszPath[0])
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync && RTPATH_IS_SLASH(pszPath[1]))
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync { /* Skip first slash in a unc path. */
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync pszSrc++;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync *pszTrg++ = '/';
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync fUnc = 1;
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync }
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync#endif
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync for (;;)
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync {
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync char ch = *pszSrc++;
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync if (RTPATH_IS_SLASH(ch))
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync {
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync *pszTrg++ = '/';
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync for (;;)
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync {
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync do ch = *pszSrc++;
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync while (RTPATH_IS_SLASH(ch));
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync /* Remove '/./' and '/.'. */
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync if (ch != '.' || (*pszSrc && !RTPATH_IS_SLASH(*pszSrc)))
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync break;
05406988cc320ac1b0971de976b6cf0c986044a9vboxsync }
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync }
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync *pszTrg = ch;
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync if (!ch)
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync break;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync pszTrg++;
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync }
1db6afc370c2fa84144478dffa9c1ed3c28c7158vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * Remove trailing slash if the path may be pointing to a directory.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int cch = pszTrg - pszPath;
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync if ( cch > 1
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync && RTPATH_IS_SLASH(pszTrg[-1])
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef HAVE_DRIVE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && !RTPATH_IS_VOLSEP(pszTrg[-2])
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && !RTPATH_IS_SLASH(pszTrg[-2]))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszPath[--cch] = '\0';
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return cch;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, unsigned cchAbsPath)
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Convert input.
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszNativePath;
23de3d76e5d27015e334e6ff763ab08de5969363vboxsync int rc = rtPathToNative(&pszNativePath, pszPath);
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync if (RT_FAILURE(rc))
23de3d76e5d27015e334e6ff763ab08de5969363vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszPath, pszAbsPath, cchAbsPath, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * On POSIX platforms the API doesn't take a length parameter, which makes it
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * a little bit more work.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char szTmpPath[PATH_MAX + 1];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *psz = realpath(pszNativePath, szTmpPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!psz)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (errno == ENOENT || errno == ENOTDIR
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef RT_OS_OS2
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /// @todo realpath() returns EIO for non-existent UNC paths like
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync // //server/share/subdir (i.e. when a subdir is specified within
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync // a share). We should either fix realpath() in libc or remove
e11fe099decbb0f65cfcc7e2939fa00bacefbb1cvboxsync // this todo.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || errno == EIO
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync )
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (strlen(pszNativePath) <= PATH_MAX)
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * Iterate the path bit by bit an apply realpath to it.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char szTmpSrc[PATH_MAX + 1];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strcpy(szTmpSrc, pszNativePath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fsCleanPath(szTmpSrc);
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync
61e80138f3c5ea5213990bde94a973c8e64d1dadvboxsync size_t cch = 0; // current resolved path length
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszCur = szTmpSrc;
61e80138f3c5ea5213990bde94a973c8e64d1dadvboxsync
61e80138f3c5ea5213990bde94a973c8e64d1dadvboxsync#ifdef HAVE_DRIVE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/')
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz = szTmpPath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cch = 2;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszCur += 3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef HAVE_UNC
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync if (pszCur[0] == '/' && pszCur[1] == '/')
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszCur += 2;
61e80138f3c5ea5213990bde94a973c8e64d1dadvboxsync char *pszSlash = strchr(pszCur, '/');
61e80138f3c5ea5213990bde94a973c8e64d1dadvboxsync size_t cchElement = pszSlash ? pszSlash - pszCur : strlen(pszCur);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cchElement && pszCur[cchElement])
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz = szTmpPath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cch = cchElement + 2;
61e80138f3c5ea5213990bde94a973c8e64d1dadvboxsync pszCur += cchElement + 1;
61e80138f3c5ea5213990bde94a973c8e64d1dadvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* we've got just "//server" or "//" */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /// @todo (r=dmik) not 100% sure we should fail, but the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync // above cases are just invalid (incomplete) paths,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync // no matter that Win32 returns these paths as is.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_INVALID_NAME;
61e80138f3c5ea5213990bde94a973c8e64d1dadvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (*pszCur == '/')
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync psz = szTmpPath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszCur++;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* get the cwd */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz = getcwd(szTmpPath, sizeof(szTmpPath));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsg(psz, ("Couldn't get cwd!\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (psz)
e11fe099decbb0f65cfcc7e2939fa00bacefbb1cvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef HAVE_DRIVE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (*pszCur == '/')
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cch = 2;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszCur++;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cch = strlen(psz);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync
be9bc9b4ba510c4b4159c193f783d024633ef8e9vboxsync if (psz)
be9bc9b4ba510c4b4159c193f783d024633ef8e9vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool fResolveSymlinks = true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char szTmpPath2[PATH_MAX + 1];
be9bc9b4ba510c4b4159c193f783d024633ef8e9vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* make sure strrchr() will work correctly */
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync psz[cch] = '\0';
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while (*pszCur)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszSlash = strchr(pszCur, '/');
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync size_t cchElement = pszSlash ? pszSlash - pszCur : strlen(pszCur);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync if (cch + cchElement + 1 > PATH_MAX)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
090f6abdd6282f48527b83162b8b441425f05e36vboxsync rc = VERR_FILENAME_TOO_LONG;
090f6abdd6282f48527b83162b8b441425f05e36vboxsync break;
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync }
78a205e3fc6719d59e8c561b3d287d3a4f879852vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!strncmp(pszCur, "..", cchElement))
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszLastSlash = strrchr(psz, '/');
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef HAVE_UNC
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pszLastSlash && pszLastSlash > psz &&
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync pszLastSlash[-1] != '/')
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync#else
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync if (pszLastSlash)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif
090f6abdd6282f48527b83162b8b441425f05e36vboxsync {
090f6abdd6282f48527b83162b8b441425f05e36vboxsync cch = pszLastSlash - psz;
090f6abdd6282f48527b83162b8b441425f05e36vboxsync psz[cch] = '\0';
090f6abdd6282f48527b83162b8b441425f05e36vboxsync }
090f6abdd6282f48527b83162b8b441425f05e36vboxsync /* else: We've reached the root and the parent of
090f6abdd6282f48527b83162b8b441425f05e36vboxsync * the root is the root. */
090f6abdd6282f48527b83162b8b441425f05e36vboxsync }
090f6abdd6282f48527b83162b8b441425f05e36vboxsync else
090f6abdd6282f48527b83162b8b441425f05e36vboxsync {
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync psz[cch++] = '/';
090f6abdd6282f48527b83162b8b441425f05e36vboxsync memcpy(psz + cch, pszCur, cchElement);
090f6abdd6282f48527b83162b8b441425f05e36vboxsync cch += cchElement;
090f6abdd6282f48527b83162b8b441425f05e36vboxsync psz[cch] = '\0';
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (fResolveSymlinks)
090f6abdd6282f48527b83162b8b441425f05e36vboxsync {
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync /* resolve possible symlinks */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *psz2 = realpath(psz, psz == szTmpPath
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ? szTmpPath2
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync : szTmpPath);
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync if (psz2)
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz = psz2;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cch = strlen(psz);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (errno != ENOENT && errno != ENOTDIR
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef RT_OS_OS2
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /// @todo see above
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && errno != EIO
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif
e11fe099decbb0f65cfcc7e2939fa00bacefbb1cvboxsync )
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync /* no more need to resolve symlinks */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fResolveSymlinks = false;
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszCur += cchElement;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* skip the slash */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync if (*pszCur)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ++pszCur;
0b65654be767b9fb7677181ddb434d8467f608e3vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef HAVE_DRIVE
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync /* check if we're at the root */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cch == 2 && RTPATH_IS_VOLSEP(psz[1]))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* if the length is zero here, then we're at the root */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!cch)
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync#endif
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync {
0ebb1ef53864eb9cc97580f722288c9b29bc5d03vboxsync psz[cch++] = '/';
0ebb1ef53864eb9cc97580f722288c9b29bc5d03vboxsync psz[cch] = '\0';
0ebb1ef53864eb9cc97580f722288c9b29bc5d03vboxsync }
0ebb1ef53864eb9cc97580f722288c9b29bc5d03vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
f5395a2af3050ddd694b0ad505975f7b717ab4f1vboxsync else
a44cdd0b29504e3de7b8aa87f839ad62b6e66f51vboxsync rc = VERR_FILENAME_TOO_LONG;
a44cdd0b29504e3de7b8aa87f839ad62b6e66f51vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTStrFree(pszNativePath);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (psz && RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Convert result and copy it to the return buffer.
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync */
332ccb6ac6feb4b50ec24d63ff029119164182ffvboxsync char *pszUtf8AbsPath;
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync rc = rtPathFromNative(&pszUtf8AbsPath, psz);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_FAILURE(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath,
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync pszPath, pszAbsPath, cchAbsPath, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync /* replace '/' back with native RTPATH_SLASH */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz = pszUtf8AbsPath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (; *psz; psz++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (*psz == '/')
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *psz = RTPATH_SLASH;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync unsigned cch = strlen(pszUtf8AbsPath) + 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cch <= cchAbsPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy(pszAbsPath, pszUtf8AbsPath, cch);
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_BUFFER_OVERFLOW;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTStrFree(pszUtf8AbsPath);
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("RTPathAbs(%p:{%s}, %p:{%s}, %d): returns %Rrc\n", pszPath,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszPath, pszAbsPath, RT_SUCCESS(rc) ? pszAbsPath : "<failed>",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cchAbsPath, rc));
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync return rc;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync}
a64bf60e92e5cb8a76aa6c8e92193932d88a906fvboxsync
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTPathProgram(char *pszPath, unsigned cchPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d45f7f7fe0c28b500b45b2dc88d7a04f4c0be6b8vboxsync * First time only.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!g_szrtProgramPath[0])
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Linux have no API for obtaining the executable path, but provides a symbolic link
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * in the proc file system. Note that readlink is one of the weirdest Unix apis around.
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * OS/2 have an api for getting the program file name.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @todo use RTProcGetExecutableName() */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_SOLARIS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# ifdef RT_OS_LINUX
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int cchLink = readlink("/proc/self/exe", &g_szrtProgramPath[0], sizeof(g_szrtProgramPath) - 1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# elif defined(RT_OS_SOLARIS)
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync char szFileBuf[PATH_MAX + 1];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync sprintf(szFileBuf, "/proc/%ld/path/a.out", (long)getpid());
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int cchLink = readlink(szFileBuf, &g_szrtProgramPath[0], sizeof(g_szrtProgramPath) - 1);
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync# else /* RT_OS_FREEBSD: */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int cchLink = readlink("/proc/curproc/file", &g_szrtProgramPath[0], sizeof(g_szrtProgramPath) - 1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cchLink < 0 || cchLink == sizeof(g_szrtProgramPath) - 1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = RTErrConvertFromErrno(errno);
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync AssertMsgFailed(("couldn't read /proc/self/exe. errno=%d cchLink=%d\n", errno, cchLink));
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync LogFlow(("RTPathProgram(%p, %u): returns %Rrc\n", pszPath, cchPath, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync g_szrtProgramPath[cchLink] = '\0';
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#elif defined(RT_OS_OS2) || defined(RT_OS_L4)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync _execname(g_szrtProgramPath, sizeof(g_szrtProgramPath));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#elif defined(RT_OS_DARWIN)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const char *pszImageName = _dyld_get_image_name(0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pszImageName, VERR_INTERNAL_ERROR);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync size_t cchImageName = strlen(pszImageName);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cchImageName >= sizeof(g_szrtProgramPath))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pszImageName, VERR_INTERNAL_ERROR);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy(g_szrtProgramPath, pszImageName, cchImageName + 1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# error needs porting.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Convert to UTF-8 and strip of the filename.
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszTmp = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = rtPathFromNative(&pszTmp, &g_szrtProgramPath[0]);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_FAILURE(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync LogFlow(("RTPathProgram(%p, %u): returns %Rrc\n", pszPath, cchPath, rc));
a64bf60e92e5cb8a76aa6c8e92193932d88a906fvboxsync return rc;
a64bf60e92e5cb8a76aa6c8e92193932d88a906fvboxsync }
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync size_t cch = strlen(pszTmp);
04a471b98d492ee51b1f40424c7f90ddf44a90f0vboxsync if (cch >= sizeof(g_szrtProgramPath))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTStrFree(pszTmp);
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync LogFlow(("RTPathProgram(%p, %u): returns %Rrc\n", pszPath, cchPath, VERR_BUFFER_OVERFLOW));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_BUFFER_OVERFLOW;
bee1a7d4b183cab9654f247b3ea8cf680842bed5vboxsync }
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync memcpy(g_szrtProgramPath, pszTmp, cch + 1);
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync RTPathStripFilename(g_szrtProgramPath);
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync RTStrFree(pszTmp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Calc the length and check if there is space before copying.
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync */
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync unsigned cch = strlen(g_szrtProgramPath) + 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cch <= cchPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy(pszPath, g_szrtProgramPath, cch + 1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("RTPathProgram(%p:{%s}, %u): returns %Rrc\n", pszPath, pszPath, cchPath, VINF_SUCCESS));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Buffer too small (%d < %d)\n", cchPath, cch));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("RTPathProgram(%p, %u): returns %Rrc\n", pszPath, cchPath, VERR_BUFFER_OVERFLOW));
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync return VERR_BUFFER_OVERFLOW;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifndef RT_OS_L4
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync * Worker for RTPathUserHome that looks up the home directory
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync * using the getpwuid_r api.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns IPRT status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszPath The path buffer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cchPath The size of the buffer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param uid The User ID to query the home directory of.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int rtPathUserHomeByPasswd(char *pszPath, size_t cchPath, uid_t uid)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d45f7f7fe0c28b500b45b2dc88d7a04f4c0be6b8vboxsync * The getpwuid_r function uses the passed in buffer to "allocate" any
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * extra memory it needs. On some systems we should probably use the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * sysconf function to find the appropriate buffer size, but since it won't
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * work everywhere we'll settle with a 5KB buffer and ASSUME that it'll
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * suffice for even the lengthiest user descriptions...
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char achBuffer[5120];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct passwd Passwd;
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync struct passwd *pPasswd;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memset(&Passwd, 0, sizeof(Passwd));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = getpwuid_r(uid, &Passwd, &achBuffer[0], sizeof(achBuffer), &pPasswd);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc != 0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return RTErrConvertFromErrno(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!pPasswd) /* uid not found in /etc/passwd */
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync return VERR_PATH_NOT_FOUND;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * Check that it isn't empty and that it exists.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct stat st;
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync if ( !pPasswd->pw_dir
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || !*pPasswd->pw_dir
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || stat(pPasswd->pw_dir, &st)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || !S_ISDIR(st.st_mode))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_PATH_NOT_FOUND;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync /*
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync * Convert it to UTF-8 and copy it to the return buffer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszUtf8Path;
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync rc = rtPathFromNative(&pszUtf8Path, pPasswd->pw_dir);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync size_t cchHome = strlen(pszUtf8Path);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cchHome < cchPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy(pszPath, pszUtf8Path, cchHome + 1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_BUFFER_OVERFLOW;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTStrFree(pszUtf8Path);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync#endif
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * Worker for RTPathUserHome that looks up the home directory
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * using the HOME environment variable.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns IPRT status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszPath The path buffer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cchPath The size of the buffer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int rtPathUserHomeByEnv(char *pszPath, size_t cchPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Get HOME env. var it and validate it's existance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = VERR_PATH_NOT_FOUND;
ebe05ec36d1fcd24d62e7066dedcb4eb2e691358vboxsync const char *pszHome = getenv("HOME");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pszHome)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct stat st;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( !stat(pszHome, &st)
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync && S_ISDIR(st.st_mode))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Convert it to UTF-8 and copy it to the return buffer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszUtf8Path;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync rc = rtPathFromNative(&pszUtf8Path, pszHome);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync size_t cchHome = strlen(pszUtf8Path);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cchHome < cchPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy(pszPath, pszUtf8Path, cchHome + 1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_BUFFER_OVERFLOW;
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync RTStrFree(pszUtf8Path);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync }
0ebb1ef53864eb9cc97580f722288c9b29bc5d03vboxsync }
0ebb1ef53864eb9cc97580f722288c9b29bc5d03vboxsync }
0ebb1ef53864eb9cc97580f722288c9b29bc5d03vboxsync return rc;
0ebb1ef53864eb9cc97580f722288c9b29bc5d03vboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
f5395a2af3050ddd694b0ad505975f7b717ab4f1vboxsync
a44cdd0b29504e3de7b8aa87f839ad62b6e66f51vboxsyncRTDECL(int) RTPathUserHome(char *pszPath, unsigned cchPath)
a44cdd0b29504e3de7b8aa87f839ad62b6e66f51vboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifndef RT_OS_L4
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * We make an exception for the root user and use the system call
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * getpwuid_r to determine their initial home path instead of
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * reading it from the $HOME variable. This is because the $HOME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * variable does not get changed by sudo (and possibly su and others)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * which can cause root-owned files to appear in user's home folders.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync uid_t uid = geteuid();
332ccb6ac6feb4b50ec24d63ff029119164182ffvboxsync if (!uid)
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync rc = rtPathUserHomeByPasswd(pszPath, cchPath, uid);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = rtPathUserHomeByEnv(pszPath, cchPath);
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * On failure, retry using the alternative method.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (Should perhaps restrict the retry cases a bit more here...)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( RT_FAILURE(rc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && rc != VERR_BUFFER_OVERFLOW)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync if (!uid)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = rtPathUserHomeByEnv(pszPath, cchPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = rtPathUserHomeByPasswd(pszPath, cchPath, uid);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* RT_OS_L4 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = rtPathUserHomeByEnv(pszPath, cchPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* RT_OS_L4 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync LogFlow(("RTPathUserHome(%p:{%s}, %u): returns %Rrc\n", pszPath,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RT_SUCCESS(rc) ? pszPath : "<failed>", cchPath, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTR3DECL(int) RTPathQueryInfo(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgReturn(VALID_PTR(pszPath), ("%p\n", pszPath), VERR_INVALID_POINTER);
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgReturn(VALID_PTR(pObjInfo), ("%p\n", pszPath), VERR_INVALID_POINTER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgReturn( enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && enmAdditionalAttribs <= RTFSOBJATTRADD_LAST,
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync ("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Convert the filename.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszNativePath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = rtPathToNative(&pszNativePath, pszPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct stat Stat;
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync if (!stat(pszNativePath, &Stat))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rtFsConvertStatToObjInfo(pObjInfo, &Stat, pszPath, 0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync switch (enmAdditionalAttribs)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync case RTFSOBJATTRADD_EASIZE:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo Use SGI extended attribute interface to query EA info. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pObjInfo->Attr.u.EASize.cb = 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break;
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTFSOBJATTRADD_NOTHING:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTFSOBJATTRADD_UNIX:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pObjInfo->Attr.enmAdditional == RTFSOBJATTRADD_UNIX);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync default:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Impossible!\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_INTERNAL_ERROR;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTErrConvertFromErrno(errno);
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync rtPathFreeNative(pszNativePath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("RTPathQueryInfo(%p:{%s}, pObjInfo=%p, %d): returns %Rrc\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszPath, pszPath, pObjInfo, enmAdditionalAttribs, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTR3DECL(int) RTPathSetTimes(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
e11fe099decbb0f65cfcc7e2939fa00bacefbb1cvboxsync AssertMsgReturn(VALID_PTR(pszPath), ("%p\n", pszPath), VERR_INVALID_POINTER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgReturn(*pszPath, ("%p\n", pszPath), VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgReturn(!pAccessTime || VALID_PTR(pAccessTime), ("%p\n", pAccessTime), VERR_INVALID_POINTER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgReturn(!pModificationTime || VALID_PTR(pModificationTime), ("%p\n", pModificationTime), VERR_INVALID_POINTER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgReturn(!pChangeTime || VALID_PTR(pChangeTime), ("%p\n", pChangeTime), VERR_INVALID_POINTER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgReturn(!pBirthTime || VALID_PTR(pBirthTime), ("%p\n", pBirthTime), VERR_INVALID_POINTER);
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * Convert the paths.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszNativePath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = rtPathToNative(&pszNativePath, pszPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * If it's a no-op, we'll only verify the existance of the file.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!pAccessTime && !pModificationTime)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync struct stat Stat;
1df4b0cdc5ec23d817014f9347ef28222b51e3fbvboxsync if (!stat(pszNativePath, &Stat))
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("RTPathSetTimes('%s',,,,): failed with %Rrc and errno=%d\n", pszPath, rc, errno));
1df4b0cdc5ec23d817014f9347ef28222b51e3fbvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
13d75a5db336ccb682d7ab28b397a4f0b8982ea3vboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Convert the input to timeval, getting the missing one if necessary,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * and call the API which does the change.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync struct timeval aTimevals[2];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pAccessTime && pModificationTime)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTimeSpecGetTimeval(pAccessTime, &aTimevals[0]);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTimeSpecGetTimeval(pModificationTime, &aTimevals[1]);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTFSOBJINFO ObjInfo;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = RTPathQueryInfo(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTimeSpecGetTimeval(pAccessTime ? pAccessTime : &ObjInfo.AccessTime, &aTimevals[0]);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTimeSpecGetTimeval(pModificationTime ? pModificationTime : &ObjInfo.ModificationTime, &aTimevals[1]);
e11fe099decbb0f65cfcc7e2939fa00bacefbb1cvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("RTPathSetTimes('%s',%p,%p,,): RTPathQueryInfo failed with %Rrc\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszPath, pAccessTime, pModificationTime, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_SUCCESS(rc))
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (utimes(pszNativePath, aTimevals))
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("RTPathSetTimes('%s',%p,%p,,): failed with %Rrc and errno=%d\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszPath, pAccessTime, pModificationTime, rc, errno));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync }
9f16100a870e25701da9bc9819e15c0f9fb3870evboxsync }
9f16100a870e25701da9bc9819e15c0f9fb3870evboxsync rtPathFreeNative(pszNativePath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("RTPathSetTimes(%p:{%s}, %p:{%RDtimespec}, %p:{%RDtimespec}, %p:{%RDtimespec}, %p:{%RDtimespec}): return %Rrc\n",
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync pszPath, pszPath, pAccessTime, pAccessTime, pModificationTime, pModificationTime,
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync pChangeTime, pChangeTime, pBirthTime, pBirthTime));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Checks if two files are the one and same file.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic bool rtPathSame(const char *pszNativeSrc, const char *pszNativeDst)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct stat SrcStat;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (stat(pszNativeSrc, &SrcStat))
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct stat DstStat;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (stat(pszNativeDst, &DstStat))
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(SrcStat.st_dev && DstStat.st_dev);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(SrcStat.st_ino && DstStat.st_ino);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( SrcStat.st_dev == DstStat.st_dev
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && SrcStat.st_ino == DstStat.st_ino
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && (SrcStat.st_mode & S_IFMT) == (DstStat.st_mode & S_IFMT))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Worker for RTPathRename, RTDirRename, RTFileRename.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns IPRT status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszSrc The source path.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszDst The destintation path.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fRename The rename flags.
e11fe099decbb0f65cfcc7e2939fa00bacefbb1cvboxsync * @param fFileType The filetype. We use the RTFMODE filetypes here. If it's 0,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * anything goes. If it's RTFS_TYPE_DIRECTORY we'll check that the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * source is a directory. If Its RTFS_TYPE_FILE we'll check that it's
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * not a directory (we are NOT checking whether it's a file).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsyncint rtPathPosixRename(const char *pszSrc, const char *pszDst, unsigned fRename, RTFMODE fFileType)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
ab0130d1627b2b214952b929de71b89e4ba41eb1vboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Convert the paths.
9f16100a870e25701da9bc9819e15c0f9fb3870evboxsync */
9f16100a870e25701da9bc9819e15c0f9fb3870evboxsync char *pszNativeSrc;
9f16100a870e25701da9bc9819e15c0f9fb3870evboxsync int rc = rtPathToNative(&pszNativeSrc, pszSrc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync char *pszNativeDst;
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync rc = rtPathToNative(&pszNativeDst, pszDst);
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync if (RT_SUCCESS(rc))
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync {
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync /*
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * Check that the source exists and that any types that's specified matches.
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * We have to check this first to avoid getting errnous VERR_ALREADY_EXISTS
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * errors from the next step.
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync *
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * There are race conditions here (perhaps unlikly ones but still), but I'm
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * afraid there is little with can do to fix that.
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync */
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync struct stat SrcStat;
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync if (stat(pszNativeSrc, &SrcStat))
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync rc = RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else if (!fFileType)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VINF_SUCCESS;
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync else if (RTFS_IS_DIRECTORY(fFileType))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = S_ISDIR(SrcStat.st_mode) ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = S_ISDIR(SrcStat.st_mode) ? VERR_IS_A_DIRECTORY : VINF_SUCCESS;
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool fSameFile = false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync /*
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync * Check if the target exists, rename is rather destructive.
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync * We'll have to make sure we don't overwrite the source!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Another race condition btw.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync struct stat DstStat;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (stat(pszNativeDst, &DstStat))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = errno == ENOENT ? VINF_SUCCESS : RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(SrcStat.st_dev && DstStat.st_dev);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(SrcStat.st_ino && DstStat.st_ino);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( SrcStat.st_dev == DstStat.st_dev
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && SrcStat.st_ino == DstStat.st_ino
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && (SrcStat.st_mode & S_IFMT) == (SrcStat.st_mode & S_IFMT))
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync {
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync /*
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * It's likely that we're talking about the same file here.
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * We should probably check paths or whatever, but for now this'll have to be enough.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fSameFile = true;
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (fSameFile)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else if (S_ISDIR(DstStat.st_mode) || !(fRename & RTPATHRENAME_FLAGS_REPLACE))
61283d6341bac43f73cf33c9ec754a59f674fa19vboxsync rc = VERR_ALREADY_EXISTS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!rename(pszNativeSrc, pszNativeDst))
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else if ( (fRename & RTPATHRENAME_FLAGS_REPLACE)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && (errno == ENOTDIR || errno == EEXIST))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Check that the destination isn't a directory.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Yet another race condition.
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rtPathSame(pszNativeSrc, pszNativeDst))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): appears to be the same file... (errno=%d)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszSrc, pszDst, fRename, fFileType, errno));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (stat(pszNativeDst, &DstStat))
e11fe099decbb0f65cfcc7e2939fa00bacefbb1cvboxsync rc = errno != ENOENT ? RTErrConvertFromErrno(errno) : VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else if (S_ISDIR(DstStat.st_mode))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_ALREADY_EXISTS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_SUCCESS(rc))
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!unlink(pszNativeDst))
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!rename(pszNativeSrc, pszNativeDst))
9f16100a870e25701da9bc9819e15c0f9fb3870evboxsync rc = VINF_SUCCESS;
9f16100a870e25701da9bc9819e15c0f9fb3870evboxsync else
9f16100a870e25701da9bc9819e15c0f9fb3870evboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): rename failed rc=%Rrc errno=%d\n",
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync pszSrc, pszDst, fRename, fFileType, rc, errno));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync rc = RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): failed to unlink dst rc=%Rrc errno=%d\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszSrc, pszDst, fRename, fFileType, rc, errno));
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): dst !dir check failed rc=%Rrc\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszSrc, pszDst, fRename, fFileType, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTErrConvertFromErrno(errno);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (errno == ENOTDIR)
be9bc9b4ba510c4b4159c193f783d024633ef8e9vboxsync rc = VERR_ALREADY_EXISTS; /* unless somebody is racing us, this is the right interpretation */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): rename failed rc=%Rrc errno=%d\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszSrc, pszDst, fRename, fFileType, rc, errno));
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): destination check failed rc=%Rrc errno=%d\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszSrc, pszDst, fRename, fFileType, rc, errno));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync else
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): source type check failed rc=%Rrc errno=%d\n",
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync pszSrc, pszDst, fRename, fFileType, rc, errno));
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync rtPathFreeNative(pszNativeDst);
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync }
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync rtPathFreeNative(pszNativeSrc);
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync }
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync return rc;
e11fe099decbb0f65cfcc7e2939fa00bacefbb1cvboxsync}
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsyncRTR3DECL(int) RTPathRename(const char *pszSrc, const char *pszDst, unsigned fRename)
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync{
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync /*
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * Validate input.
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync */
323b78bf4831666c95416edf3b6e54657a769e5dvboxsync AssertMsgReturn(VALID_PTR(pszSrc), ("%p\n", pszSrc), VERR_INVALID_POINTER);
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync AssertMsgReturn(VALID_PTR(pszDst), ("%p\n", pszDst), VERR_INVALID_POINTER);
9f16100a870e25701da9bc9819e15c0f9fb3870evboxsync AssertMsgReturn(*pszSrc, ("%p\n", pszSrc), VERR_INVALID_PARAMETER);
b880eb99e249b300390f5eeedff304ac30ba548evboxsync AssertMsgReturn(*pszDst, ("%p\n", pszDst), VERR_INVALID_PARAMETER);
9f16100a870e25701da9bc9819e15c0f9fb3870evboxsync AssertMsgReturn(!(fRename & ~RTPATHRENAME_FLAGS_REPLACE), ("%#x\n", fRename), VERR_INVALID_PARAMETER);
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync /*
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * Hand it to the worker.
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync */
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync int rc = rtPathPosixRename(pszSrc, pszDst, fRename, 0);
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync Log(("RTPathRename(%p:{%s}, %p:{%s}, %#x): returns %Rrc\n", pszSrc, pszSrc, pszDst, pszDst, fRename, rc));
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync return rc;
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync}
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsyncRTDECL(bool) RTPathExists(const char *pszPath)
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync{
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync /*
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * Validate input.
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync */
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync AssertPtrReturn(pszPath, false);
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync AssertReturn(*pszPath, false);
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync /*
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync * Convert the path and check if it exists using stat().
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync */
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync char *pszNativePath;
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync int rc = rtPathToNative(&pszNativePath, pszPath);
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync if (RT_SUCCESS(rc))
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync {
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync struct stat Stat;
ebf9e36b6e5548e4db69cebbef120e669a459afevboxsync if (!stat(pszNativePath, &Stat))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_GENERAL_FAILURE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTStrFree(pszNativePath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return RT_SUCCESS(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync