예제 #1
0
/** Check that the string is an absolute path to a file or print an error. */
bool checkAbsoluteFilePath(const char *pcszName, const char *pcszValue)
{
    if (RTPathFilename(pcszValue) && RTPathStartsWithRoot(pcszValue))
        return true;
    RTStrmPrintf(g_pStdErr, "%s: %s must be an absolute path of a file.\n", pcszName, pcszValue);
    return false;
}
예제 #2
0
/**
 * Validates a name in an extension pack.
 *
 * We restrict the charset to try make sure the extension pack can be unpacked
 * on all file systems.
 *
 * @returns VBox status code, failures with message.
 * @param   pszName             The name to validate.
 * @param   pszError            Where to store an error message on failure.
 * @param   cbError             The size of the buffer @a pszError points to.
 */
static int vboxExtPackValidateMemberName(const char *pszName, char *pszError, size_t cbError)
{
    if (RTPathStartsWithRoot(pszName))
        return vboxExtPackReturnError(VERR_PATH_IS_NOT_RELATIVE, pszError, cbError, "'%s': starts with root spec", pszName);

    const char *pszErr = NULL;
    const char *psz = pszName;
    int ch;
    while ((ch = *psz) != '\0')
    {
        /* Character set restrictions. */
        if (ch < 0 || ch >= 128)
        {
            pszErr = "Only 7-bit ASCII allowed";
            break;
        }
        if (ch <= 31 || ch == 127)
        {
            pszErr = "No control characters are not allowed";
            break;
        }
        if (ch == '\\')
        {
            pszErr = "Only backward slashes are not allowed";
            break;
        }
        if (strchr("'\":;*?|[]<>(){}", ch))
        {
            pszErr = "The characters ', \", :, ;, *, ?, |, [, ], <, >, (, ), { and } are not allowed";
            break;
        }

        /* Take the simple way out and ban all ".." sequences. */
        if (   ch     == '.'
            && psz[1] == '.')
        {
            pszErr = "Double dot sequence are not allowed";
            break;
        }

        /* Keep the tree shallow or the hardening checks will fail. */
        if (psz - pszName > VBOX_EXTPACK_MAX_MEMBER_NAME_LENGTH)
        {
            pszErr = "Too long";
            break;
        }

        /* advance */
        psz++;
    }

    if (pszErr)
        return vboxExtPackReturnError(VERR_INVALID_NAME, pszError, cbError,
                                      "Bad member name '%s' (pos %zu): %s", pszName, (size_t)(psz - pszName), pszErr);
    return RTEXITCODE_SUCCESS;
}
예제 #3
0
HRESULT SystemProperties::i_setDefaultAdditionsISO(const com::Utf8Str &aPath)
{
    com::Utf8Str path(aPath);
    if (path.isEmpty())
    {
        char strTemp[RTPATH_MAX];
        int vrc = RTPathAppPrivateNoArch(strTemp, sizeof(strTemp));
        AssertRC(vrc);
        Utf8Str strSrc1 = Utf8Str(strTemp).append("/VBoxGuestAdditions.iso");

        vrc = RTPathExecDir(strTemp, sizeof(strTemp));
        AssertRC(vrc);
        Utf8Str strSrc2 = Utf8Str(strTemp).append("/additions/VBoxGuestAdditions.iso");

        vrc = RTPathUserHome(strTemp, sizeof(strTemp));
        AssertRC(vrc);
        Utf8Str strSrc3 = Utf8StrFmt("%s/VBoxGuestAdditions_%s.iso", strTemp, VirtualBox::i_getVersionNormalized().c_str());

        /* Check the standard image locations */
        if (RTFileExists(strSrc1.c_str()))
            path = strSrc1;
        else if (RTFileExists(strSrc2.c_str()))
            path = strSrc2;
        else if (RTFileExists(strSrc3.c_str()))
            path = strSrc3;
        else
            return setError(E_FAIL,
                            tr("Cannot determine default Guest Additions ISO location. Most likely they are not available"));
    }

    if (!RTPathStartsWithRoot(path.c_str()))
        return setError(E_INVALIDARG,
                        tr("Given default machine Guest Additions ISO file '%s' is not fully qualified"),
                        path.c_str());

    if (!RTFileExists(path.c_str()))
        return setError(E_INVALIDARG,
                        tr("Given default machine Guest Additions ISO file '%s' does not exist"),
                        path.c_str());

    m->strDefaultAdditionsISO = path;

    return S_OK;
}
/**
 * Internal implementation to set the default machine folder. Gets called
 * from the public attribute setter as well as loadSettings(). With 4.0,
 * the "default default" machine folder has changed, and we now require
 * a full path always.
 * @param aPath
 * @return
 */
HRESULT SystemProperties::setDefaultMachineFolder(const Utf8Str &strPath)
{
    Utf8Str path(strPath);      // make modifiable
    if (    path.isEmpty()          // used by API calls to reset the default
         || path == "Machines"      // this value (exactly like this, without path) is stored
                                    // in VirtualBox.xml if user upgrades from before 4.0 and
                                    // has not changed the default machine folder
       )
    {
        // new default with VirtualBox 4.0: "$HOME/VirtualBox VMs"
        HRESULT rc = getUserHomeDirectory(path);
        if (FAILED(rc)) return rc;
        path += RTPATH_SLASH_STR "VirtualBox VMs";
    }

    if (!RTPathStartsWithRoot(path.c_str()))
        return setError(E_INVALIDARG,
                        tr("Given default machine folder '%s' is not fully qualified"),
                        path.c_str());

    m->strDefaultMachineFolder = path;

    return S_OK;
}
RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst,
                               const char *pszPathFrom,
                               const char *pszPathTo)
{
    int rc = VINF_SUCCESS;

    AssertPtrReturn(pszPathDst, VERR_INVALID_POINTER);
    AssertReturn(cbPathDst, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszPathFrom, VERR_INVALID_POINTER);
    AssertPtrReturn(pszPathTo, VERR_INVALID_POINTER);
    AssertReturn(RTPathStartsWithRoot(pszPathFrom), VERR_INVALID_PARAMETER);
    AssertReturn(RTPathStartsWithRoot(pszPathTo), VERR_INVALID_PARAMETER);
    AssertReturn(RTStrCmp(pszPathFrom, pszPathTo), VERR_INVALID_PARAMETER);

    /*
     * Check for different root specifiers (drive letters), creating a relative path doesn't work here.
     * @todo: How to handle case insensitive root specifiers correctly?
     */
    size_t offRootFrom = rtPathRootSpecLen(pszPathFrom);
    size_t offRootTo   = rtPathRootSpecLen(pszPathTo);

    if (   offRootFrom != offRootTo
        || RTStrNCmp(pszPathFrom, pszPathTo, offRootFrom))
        return VERR_NOT_SUPPORTED;

    /* Filter out the parent path which is equal to both paths. */
    while (   *pszPathFrom == *pszPathTo
           && *pszPathFrom != '\0'
           && *pszPathTo != '\0')
    {
        pszPathFrom++;
        pszPathTo++;
    }

    /*
     * Because path components can start with an equal string but differ afterwards we
     * need to go back to the beginning of the current component.
     */
    while (!RTPATH_IS_SEP(*pszPathFrom))
        pszPathFrom--;

    pszPathFrom++; /* Skip path separator. */

    while (!RTPATH_IS_SEP(*pszPathTo))
        pszPathTo--;

    pszPathTo++; /* Skip path separator. */

    /* Paths point to the first non equal component now. */
    char aszPathTmp[RTPATH_MAX + 1];
    unsigned offPathTmp = 0;

    /* Create the part to go up from pszPathFrom. */
    while (*pszPathFrom != '\0')
    {
        while (   !RTPATH_IS_SEP(*pszPathFrom)
               && *pszPathFrom != '\0')
            pszPathFrom++;

        if (RTPATH_IS_SEP(*pszPathFrom))
        {
            if (offPathTmp + 3 >= sizeof(aszPathTmp) - 1)
                return VERR_FILENAME_TOO_LONG;
            aszPathTmp[offPathTmp++] = '.';
            aszPathTmp[offPathTmp++] = '.';
            aszPathTmp[offPathTmp++] = RTPATH_SLASH;
            pszPathFrom++;
        }
    }

    aszPathTmp[offPathTmp] = '\0';

    /* Now append the rest of pszPathTo to the final path. */
    char *pszPathTmp = &aszPathTmp[offPathTmp];
    size_t cbPathTmp = sizeof(aszPathTmp) - offPathTmp - 1;
    rc = RTStrCatP(&pszPathTmp, &cbPathTmp, pszPathTo);
    if (RT_SUCCESS(rc))
    {
        *pszPathTmp = '\0';

        size_t cchPathTmp = strlen(aszPathTmp);
        if (cchPathTmp >= cbPathDst)
           return VERR_BUFFER_OVERFLOW;
        memcpy(pszPathDst, aszPathTmp, cchPathTmp + 1);
    }
    else
        rc = VERR_FILENAME_TOO_LONG;

    return rc;
}
int rtldrNativeLoad(const char *pszFilename, uintptr_t *phHandle, uint32_t fFlags, PRTERRINFO pErrInfo)
{
    Assert(sizeof(*phHandle) >= sizeof(HMODULE));
    AssertReturn(!(fFlags & RTLDRLOAD_FLAGS_GLOBAL), VERR_INVALID_FLAGS);
    AssertLogRelMsgReturn(RTPathStartsWithRoot(pszFilename),  /* Relative names will still be applied to the search path. */
                          ("pszFilename='%s'\n", pszFilename),
                          VERR_INTERNAL_ERROR_2);

    /*
     * Convert to UTF-16 and make sure it got a .DLL suffix.
     */
    int rc;
    RTUTF16 *pwszNative = NULL;
    if (RTPathHasSuffix(pszFilename))
        rc = RTStrToUtf16(pszFilename, &pwszNative);
    else
    {
        size_t cwcAlloc;
        rc = RTStrCalcUtf16LenEx(pszFilename, RTSTR_MAX, &cwcAlloc);
        if (RT_SUCCESS(rc))
        {
            cwcAlloc += sizeof(".DLL");
            pwszNative = RTUtf16Alloc(cwcAlloc * sizeof(RTUTF16));
            if (pwszNative)
            {
                size_t cwcNative;
                rc = RTStrToUtf16Ex(pszFilename, RTSTR_MAX, &pwszNative, cwcAlloc, &cwcNative);
                if (RT_SUCCESS(rc))
                    rc = RTUtf16CopyAscii(&pwszNative[cwcNative], cwcAlloc - cwcNative, ".DLL");
            }
            else
                rc = VERR_NO_UTF16_MEMORY;
        }
    }
    if (RT_SUCCESS(rc))
    {
        /*
         * Attempt load.
         */
        HMODULE     hmod;
        static int  s_iSearchDllLoadDirSupported = 0;
        if (   !(fFlags & RTLDRLOAD_FLAGS_NT_SEARCH_DLL_LOAD_DIR)
            || s_iSearchDllLoadDirSupported < 0)
            hmod = LoadLibraryExW(pwszNative, NULL, 0);
        else
        {
            hmod = LoadLibraryExW(pwszNative, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32
                                  | LOAD_LIBRARY_SEARCH_APPLICATION_DIR);
            if (s_iSearchDllLoadDirSupported == 0)
            {
                if (hmod != NULL || GetLastError() != ERROR_INVALID_PARAMETER)
                    s_iSearchDllLoadDirSupported = 1;
                else
                {
                    s_iSearchDllLoadDirSupported = -1;
                    hmod = LoadLibraryExW(pwszNative, NULL, 0);
                }
            }
        }
        if (hmod)
        {
            *phHandle = (uintptr_t)hmod;
            RTUtf16Free(pwszNative);
            return VINF_SUCCESS;
        }

        /*
         * Try figure why it failed to load.
         */
        DWORD dwErr = GetLastError();
        rc = RTErrConvertFromWin32(dwErr);
        rc = RTErrInfoSetF(pErrInfo, rc, "GetLastError=%u", dwErr);
    }
    else
        rc = RTErrInfoSetF(pErrInfo, rc, "Error converting UTF-8 to UTF-16 string.");
    RTUtf16Free(pwszNative);
    return rc;
}
/**
 * Create one directory and any missing parent directories.
 *
 * @returns exit code
 * @param   pOpts               The mkdir option.
 * @param   pszDir              The path to the new directory.
 */
static int rtCmdRmDirOneWithParents(RTCMDRMDIROPTS const *pOpts, const char *pszDir)
{
    /* We need a copy we can work with here. */
    char *pszCopy = RTStrDup(pszDir);
    if (!pszCopy)
        return RTMsgErrorExitFailure("Out of string memory!");

    int rc;
    if (!pOpts->fAlwaysUseChainApi && !RTVfsChainIsSpec(pszDir) )
    {
        size_t cchCopy = strlen(pszCopy);
        do
        {
            rc = RTDirRemove(pszCopy);
            if (RT_SUCCESS(rc))
            {
                if (pOpts->fVerbose)
                    RTPrintf("%s\n", pszCopy);
            }
            else if ((rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND) && pOpts->fIgnoreNonExisting)
                rc = VINF_SUCCESS;
            else
            {
                if ((rc == VERR_DIR_NOT_EMPTY || rc == VERR_SHARING_VIOLATION) && pOpts->fIgnoreNotEmpty)
                    rc = VINF_SUCCESS;
                else
                    RTMsgError("Failed to remove directory '%s': %Rrc", pszCopy, rc);
                break;
            }

            /* Strip off a component. */
            while (cchCopy > 0 && RTPATH_IS_SLASH(pszCopy[cchCopy - 1]))
                cchCopy--;
            while (cchCopy > 0 && !RTPATH_IS_SLASH(pszCopy[cchCopy - 1]))
                cchCopy--;
            while (cchCopy > 0 && RTPATH_IS_SLASH(pszCopy[cchCopy - 1]))
                cchCopy--;
            pszCopy[cchCopy] = '\0';
        } while (cchCopy > 0);
    }
    else
    {
        /*
         * Strip the final path element from the pszDir spec.
         */
        char       *pszFinalPath;
        char       *pszSpec;
        uint32_t    offError;
        rc = RTVfsChainSplitOffFinalPath(pszCopy, &pszSpec, &pszFinalPath, &offError);
        if (RT_SUCCESS(rc))
        {
            /*
             * Open the root director/whatever.
             */
            RTERRINFOSTATIC ErrInfo;
            RTVFSDIR hVfsBaseDir;
            if (pszSpec)
            {
                rc = RTVfsChainOpenDir(pszSpec, 0 /*fOpen*/, &hVfsBaseDir, &offError, RTErrInfoInitStatic(&ErrInfo));
                if (RT_FAILURE(rc))
                    RTVfsChainMsgError("RTVfsChainOpenDir", pszSpec, rc, offError, &ErrInfo.Core);
                else if (!pszFinalPath)
                    pszFinalPath = RTStrEnd(pszSpec, RTSTR_MAX);
            }
            else if (!RTPathStartsWithRoot(pszFinalPath))
            {
                rc = RTVfsDirOpenNormal(".", 0 /*fOpen*/, &hVfsBaseDir);
                if (RT_FAILURE(rc))
                    RTMsgError("Failed to open '.' (for %s): %Rrc", rc, pszFinalPath);
            }
            else
            {
                char *pszRoot = pszFinalPath;
                pszFinalPath = RTPathSkipRootSpec(pszFinalPath);
                char const chSaved = *pszFinalPath;
                *pszFinalPath = '\0';
                rc = RTVfsDirOpenNormal(pszRoot, 0 /*fOpen*/, &hVfsBaseDir);
                *pszFinalPath = chSaved;
                if (RT_FAILURE(rc))
                    RTMsgError("Failed to open root dir for '%s': %Rrc", rc, pszRoot);
            }

            /*
             * Walk the path component by component, starting at the end.
             */
            if (RT_SUCCESS(rc))
            {
                size_t cchFinalPath = strlen(pszFinalPath);
                while (RT_SUCCESS(rc) && cchFinalPath > 0)
                {
                    rc = RTVfsDirRemoveDir(hVfsBaseDir, pszFinalPath, 0 /*fFlags*/);
                    if (RT_SUCCESS(rc))
                    {
                        if (pOpts->fVerbose)
                            RTPrintf("%s\n", pszCopy);
                    }
                    else if ((rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND) && pOpts->fIgnoreNonExisting)
                        rc = VINF_SUCCESS;
                    else
                    {
                        if ((rc == VERR_DIR_NOT_EMPTY || rc == VERR_SHARING_VIOLATION) && pOpts->fIgnoreNotEmpty)
                            rc = VINF_SUCCESS;
                        else if (pszSpec)
                            RTMsgError("Failed to remove directory '%s:%s': %Rrc", pszSpec, pszFinalPath, rc);
                        else
                            RTMsgError("Failed to remove directory '%s': %Rrc", pszFinalPath, rc);
                        break;
                    }

                    /* Strip off a component. */
                    while (cchFinalPath > 0 && RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1]))
                        cchFinalPath--;
                    while (cchFinalPath > 0 && !RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1]))
                        cchFinalPath--;
                    while (cchFinalPath > 0 && RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1]))
                        cchFinalPath--;
                    pszFinalPath[cchFinalPath] = '\0';
                }

                RTVfsDirRelease(hVfsBaseDir);
            }
        }
        else
            RTVfsChainMsgError("RTVfsChainOpenParentDir", pszCopy, rc, offError, NULL);
    }
    RTStrFree(pszCopy);
    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
}