VirtualBox

Changeset 33806 in vbox


Ignore:
Timestamp:
Nov 5, 2010 5:20:15 PM (14 years ago)
Author:
vboxsync
Message:

ExtPack changes, related IPRT changes.

Location:
trunk
Files:
30 edited

Legend:

Unmodified
Added
Removed
  • trunk/Config.kmk

    r33677 r33806  
    30083008
    30093009#
     3010# Template for building set-uid-to-root helper programs.
     3011# These shall have not extra runpaths, esp. not origin ones.
     3012#
     3013TEMPLATE_VBoxR3SetUidToRoot = Set-uid-to-root helper program.
     3014TEMPLATE_VBoxR3SetUidToRoot_EXTENDS = VBOXR3HARDENEDEXE
     3015TEMPLATE_VBoxR3SetUidToRoot_LIBS = $(NO_SUCH_VARIABLE)
     3016
     3017
     3018#
    30103019# Template for building R3 shared objects / DLLs with the 10.5 Mac OS X SDK.
    30113020# Identical to VBOXR3EXE, except for the DYLIB, the classic_linker and SDK bits.
  • trunk/include/VBox/err.h

    r33739 r33806  
    13901390/** The file or directory is world writable (hardening). */
    13911391#define VERR_SUPLIB_WORLD_WRITABLE                  (-3767)
     1392/** The argv[0] of an internal application does not match the executable image
     1393 * path (hardening). */
     1394#define VERR_SUPLIB_INVALID_ARGV0_INTERNAL          (-3768)
     1395/** The internal application does not reside in the correct place (hardening). */
     1396#define VERR_SUPLIB_INVALID_INTERNAL_APP_DIR        (-3769)
    13921397/** @} */
    13931398
  • trunk/include/VBox/sup.h

    r33739 r33806  
    971971 * @param   phFile          Where to store the handle to the opened file. This is optional, pass NULL
    972972 *                          if the file should not be opened.
     973 * @deprecated Write a new one.
    973974 */
    974975SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszWhat, PRTFILE phFile);
     976
     977/**
     978 * Verifies the integrity of a the current process, including the image
     979 * location and that the invocation was absolute.
     980 *
     981 * This must currently be called after initializing the runtime.  The intended
     982 * audience is set-uid-to-root applications, root services and similar.
     983 *
     984 * @returns VBox status code.  On failure
     985 *          message.
     986 * @param   pszArgv0        The first argument to main().
     987 * @param   fInternal       Set this to @c true if this is an internal
     988 *                          VirtualBox application.  Otherwise pass @c false.
     989 * @param   pszErr          Where to return error message on failure.
     990 * @param   cbErr           The size of the error buffer.
     991 */
     992SUPR3DECL(int) SUPR3HardenedVerifySelf(const char *pszArgv0, bool fInternal, char *pszErr, size_t cbErr);
    975993
    976994/**
  • trunk/include/iprt/process.h

    r33044 r33806  
    282282
    283283/**
    284  * Gets the executable image name (full path) of the current process.
    285  *
    286  * @returns pszExecName on success. NULL on buffer overflow or other errors.
    287  *
    288  * @param   pszExecName     Where to store the name.
    289  * @param   cchExecName     The size of the buffer.
    290  */
    291 RTR3DECL(char *) RTProcGetExecutableName(char *pszExecName, size_t cchExecName);
     284 * Gets the short process name.
     285 *
     286 * @returns Pointer to read-only name string.
     287 */
     288RTR3DECL(const char *) RTProcShortName(void);
     289
     290/**
     291 * Gets the path to the executable image of the current process.
     292 *
     293 * @returns pszExecPath on success. NULL on buffer overflow or other errors.
     294 *
     295 * @param   pszExecPath     Where to store the path.
     296 * @param   cbExecPath      The size of the buffer.
     297 */
     298RTR3DECL(char *) RTProcGetExecutablePath(char *pszExecPath, size_t cbExecPath);
    292299
    293300/**
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp

    r33762 r33806  
    10491049    /* Search the path of our executable. */
    10501050    char szVBoxService[RTPATH_MAX];
    1051     if (RTProcGetExecutableName(szVBoxService, sizeof(szVBoxService)))
     1051    if (RTProcGetExecutablePath(szVBoxService, sizeof(szVBoxService)))
    10521052    {
    10531053        char *pszExecResolved = NULL;
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServicePageSharing.cpp

    r32772 r33806  
    690690        {
    691691            char szExeName[256];
    692             char *pszExeName = RTProcGetExecutableName(szExeName, sizeof(szExeName));
     692            char *pszExeName = RTProcGetExecutablePath(szExeName, sizeof(szExeName));
    693693            if (pszExeName)
    694694            {
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r33740 r33806  
    14381438
    14391439
     1440SUPR3DECL(int) SUPR3HardenedVerifySelf(const char *pszArgv0, bool fInternal, char *pszErr, size_t cbErr)
     1441{
     1442    /*
     1443     * Quick input validation.
     1444     */
     1445    AssertPtr(pszArgv0);
     1446    AssertPtr(pszErr);
     1447    Assert(cbErr > 32);
     1448
     1449    /*
     1450     * Get the executable image path as we need it for all the tests here.
     1451     */
     1452    char szExecPath[RTPATH_MAX];
     1453    if (!RTProcGetExecutablePath(szExecPath, sizeof(szExecPath)))
     1454    {
     1455        RTStrPrintf(pszErr, cbErr, "RTProcGetExecutablePath failed");
     1456        return VERR_INTERNAL_ERROR_2;
     1457    }
     1458
     1459    int rc;
     1460    if (fInternal)
     1461    {
     1462        /*
     1463         * Internal applications must be launched directly without any PATH
     1464         * searching involved.
     1465         */
     1466        if (RTPathCompare(pszArgv0, szExecPath) != 0)
     1467        {
     1468            RTStrPrintf(pszErr, cbErr, "argv[0] does not match the executable image path: '%s' != '%s'", pszArgv0, szExecPath);
     1469            return VERR_SUPLIB_INVALID_ARGV0_INTERNAL;
     1470        }
     1471
     1472        /*
     1473         * Internal applications must reside in or under the
     1474         * RTPathAppPrivateArch directory.
     1475         */
     1476        char szAppPrivateArch[RTPATH_MAX];
     1477        rc = RTPathAppPrivateArch(szAppPrivateArch, sizeof(szAppPrivateArch));
     1478        if (RT_FAILURE(rc))
     1479        {
     1480            RTStrPrintf(pszErr, cbErr, "RTPathAppPrivateArch failed with rc=%Rrc", rc);
     1481            return VERR_SUPLIB_INVALID_ARGV0_INTERNAL;
     1482        }
     1483        size_t cchAppPrivateArch = strlen(szAppPrivateArch);
     1484        if (   cchAppPrivateArch >= strlen(szExecPath)
     1485            || !RTPATH_IS_SLASH(szExecPath[cchAppPrivateArch]))
     1486        {
     1487            RTStrPrintf(pszErr, cbErr, "Internal executable does reside under RTPathAppPrivateArch");
     1488            return VERR_SUPLIB_INVALID_INTERNAL_APP_DIR;
     1489        }
     1490        szExecPath[cchAppPrivateArch] = '\0';
     1491        if (RTPathCompare(szExecPath, szAppPrivateArch) != 0)
     1492        {
     1493            RTStrPrintf(pszErr, cbErr, "Internal executable does reside under RTPathAppPrivateArch");
     1494            return VERR_SUPLIB_INVALID_INTERNAL_APP_DIR;
     1495        }
     1496        szExecPath[cchAppPrivateArch] = RTPATH_SLASH;
     1497    }
     1498
     1499#ifdef VBOX_WITH_HARDENING
     1500    /*
     1501     * Verify that the image file and parent directories are sane.
     1502     */
     1503    rc = supR3HardenedVerifyFile(szPath, NULL, pszErr, cbErr);
     1504    if (RT_FAILURE(rc))
     1505        return rc;
     1506#endif
     1507
     1508    return VINF_SUCCESS;
     1509}
     1510
     1511
    14401512SUPR3DECL(int) SUPR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, char *pszErr, size_t cbErr)
    14411513{
  • trunk/src/VBox/HostServices/GuestControl/testcase/tstGuestControlSvc.cpp

    r31847 r33806  
    11271127
    11281128    /* Save image name for later use. */
    1129     if (!RTProcGetExecutableName(g_szImageName, sizeof(g_szImageName)))
    1130         return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTProcGetExecutableName failed\n");
     1129    if (!RTProcGetExecutablePath(g_szImageName, sizeof(g_szImageName)))
     1130        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTProcGetExecutablePath failed\n");
    11311131
    11321132    VBOXHGCMSVCFNTABLE svcTable;
  • trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa.c

    r33540 r33806  
    6868    /* VirtualBox is the only frontend which support 3D right now. */
    6969    char pszName[256];
    70     if (RTProcGetExecutableName(pszName, sizeof(pszName)))
     70    if (RTProcGetExecutablePath(pszName, sizeof(pszName)))
    7171        /* Check for VirtualBox and VirtualBoxVM */
    7272        if (RTStrNICmp(RTPathFilename(pszName), "VirtualBox", 10) != 0)
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r33784 r33806  
    50665066        /* the package type is interesting for Linux distributions */
    50675067        char szExecName[RTPATH_MAX];
    5068         char *pszExecName = RTProcGetExecutableName(szExecName, sizeof(szExecName));
     5068        char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
    50695069        RTLogRelLogger(loggerRelease, 0, ~0U,
    50705070                       "Executable: %s\n"
  • trunk/src/VBox/Main/DHCPServerRunner.cpp

    r31539 r33806  
    8383    /* get the path to the executable */
    8484    char exePathBuf[RTPATH_MAX];
    85     const char *exePath = RTProcGetExecutableName(exePathBuf, RTPATH_MAX);
     85    const char *exePath = RTProcGetExecutablePath(exePathBuf, RTPATH_MAX);
    8686    char *substrSl = strrchr(exePathBuf, '/');
    8787    char *substrBs = strrchr(exePathBuf, '\\');
  • trunk/src/VBox/Main/ExtPackManagerImpl.cpp

    r33765 r33806  
    445445    if (RT_FAILURE(vrc))
    446446    {
    447         m->strWhyUnusable.printf(tr("%s"), szErr);
     447        m->strWhyUnusable.printf(tr("%s (rc=%Rrc)"), szErr, vrc);
    448448        return;
    449449    }
     
    842842    int rc = RTPathAppPrivateArch(szBaseDir, sizeof(szBaseDir));
    843843    AssertLogRelRCReturn(rc, E_FAIL);
    844     rc = RTPathAppend(szBaseDir, sizeof(szBaseDir), "ExtensionPacks");
     844    rc = RTPathAppend(szBaseDir, sizeof(szBaseDir), VBOX_EXTPACK_INSTALL_DIR);
    845845    AssertLogRelRCReturn(rc, E_FAIL);
    846846
    847847    char szCertificatDir[RTPATH_MAX];
    848     rc = RTPathAppPrivateArch(szCertificatDir, sizeof(szCertificatDir));
     848    rc = RTPathAppPrivateNoArch(szCertificatDir, sizeof(szCertificatDir));
    849849    AssertLogRelRCReturn(rc, E_FAIL);
    850     rc = RTPathAppend(szBaseDir, sizeof(szCertificatDir), "Certificates");
     850    rc = RTPathAppend(szBaseDir, sizeof(szCertificatDir), VBOX_EXTPACK_CERT_DIR);
    851851    AssertLogRelRCReturn(rc, E_FAIL);
    852852
     
    882882            if (   RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode)
    883883                && strcmp(Entry.szName, ".")  != 0
    884                 && strcmp(Entry.szName, "..") != 0 )
     884                && strcmp(Entry.szName, "..") != 0
     885                && VBoxExtPackIsValidName(Entry.szName) )
    885886            {
    886887                /*
     
    10031004                    /*
    10041005                     * Derive the name of the extension pack from the file
    1005                      * name.
    1006                      *
    1007                      * RESTRICTION: The name can only contain english alphabet
    1008                      *              charactes, decimal digits and space.
    1009                      *              Impose a max length of 64 chars.
     1006                     * name.  Certain restrictions are here placed on the
     1007                     * tarball name.
    10101008                     */
    1011                     char *pszName = RTStrDup(RTPathFilename(strTarball.c_str()));
    1012                     if (pszName)
     1009                    iprt::MiniString *pStrName = VBoxExtPackExtractNameFromTarballPath(strTarball.c_str());
     1010                    if (pStrName)
    10131011                    {
    1014                         char *pszEnd = pszName;
    1015                         while (RT_C_IS_ALNUM(*pszEnd) || *pszEnd == ' ')
    1016                             pszEnd++;
    1017                         if (   pszEnd == pszName
    1018                             || pszEnd - pszName <= 64)
     1012                        /*
     1013                         * Refresh the data we have on the extension pack as it
     1014                         * may be made stale by direct meddling or some other user.
     1015                         */
     1016                        ExtPack *pExtPack;
     1017                        hrc = refreshExtPack(pStrName->c_str(), false /*a_fUnsuableIsError*/, &pExtPack);
     1018                        if (SUCCEEDED(hrc) && !pExtPack)
    10191019                        {
    1020                             *pszEnd = '\0';
    1021 
    10221020                            /*
    1023                              * Refresh the data we have on the extension pack
    1024                              * as it may be made stale by direct meddling or
    1025                              * some other user.
     1021                             * Run the set-uid-to-root binary that performs the actual
     1022                             * installation.  Then create an object for the packet (we
     1023                             * do this even on failure, to be on the safe side).
    10261024                             */
    1027                             ExtPack *pExtPack;
    1028                             hrc = refreshExtPack(pszName, false /*a_fUnsuableIsError*/, &pExtPack);
    1029                             if (SUCCEEDED(hrc) && !pExtPack)
     1025                            char szTarballFd[64];
     1026                            RTStrPrintf(szTarballFd, sizeof(szTarballFd), "0x%RX64",
     1027                                        (uint64_t)RTFileToNative(hFile));
     1028
     1029                            hrc = runSetUidToRootHelper("install",
     1030                                                        "--base-dir",        m->strBaseDir.c_str(),
     1031                                                        "--certificate-dir", m->strCertificatDirPath.c_str(),
     1032                                                        "--name",            pStrName->c_str(),
     1033                                                        "--tarball",         strTarball.c_str(),
     1034                                                        "--tarball-fd",      &szTarballFd[0],
     1035                                                        NULL);
     1036                            if (SUCCEEDED(hrc))
    10301037                            {
    1031                                 /*
    1032                                  * Run the set-uid-to-root binary that performs the actual
    1033                                  * installation.  Then create an object for the packet (we
    1034                                  * do this even on failure, to be on the safe side).
    1035                                  */
    1036                                 char szTarballFd[64];
    1037                                 RTStrPrintf(szTarballFd, sizeof(szTarballFd), "0x%RX64",
    1038                                             (uint64_t)RTFileToNative(hFile));
    1039 
    1040                                 hrc = runSetUidToRootHelper("install",
    1041                                                             "--base-dir",        m->strBaseDir.c_str(),
    1042                                                             "--name",            pszName,
    1043                                                             "--certificate-dir", m->strCertificatDirPath.c_str(),
    1044                                                             "--tarball",         strTarball.c_str(),
    1045                                                             "--tarball-fd",      &szTarballFd[0],
    1046                                                             NULL);
     1038                                hrc = refreshExtPack(pStrName->c_str(), true /*a_fUnsuableIsError*/, &pExtPack);
    10471039                                if (SUCCEEDED(hrc))
    10481040                                {
    1049                                     hrc = refreshExtPack(pszName, true /*a_fUnsuableIsError*/, &pExtPack);
    1050                                     if (SUCCEEDED(hrc))
    1051                                     {
    1052                                         LogRel(("ExtPackManager: Successfully installed extension pack '%s'.\n", pszName));
    1053                                         pExtPack->callInstalledHook();
    1054                                     }
    1055                                 }
    1056                                 else
    1057                                 {
    1058                                     ErrorInfoKeeper Eik;
    1059                                     refreshExtPack(pszName, false /*a_fUnsuableIsError*/, NULL);
     1041                                    LogRel(("ExtPackManager: Successfully installed extension pack '%s'.\n", pStrName->c_str()));
     1042                                    pExtPack->callInstalledHook();
    10601043                                }
    10611044                            }
    1062                             else if (SUCCEEDED(hrc))
    1063                                 hrc = setError(E_FAIL,
    1064                                                tr("Extension pack '%s' is already installed."
    1065                                                   " In case of a reinstallation, please uninstall it first"),
    1066                                                pszName);
     1045                            else
     1046                            {
     1047                                ErrorInfoKeeper Eik;
     1048                                refreshExtPack(pStrName->c_str(), false /*a_fUnsuableIsError*/, NULL);
     1049                            }
    10671050                        }
    1068                         else
    1069                             hrc = setError(E_FAIL, tr("Malformed '%s' file name"), strTarball.c_str());
     1051                        else if (SUCCEEDED(hrc))
     1052                            hrc = setError(E_FAIL,
     1053                                           tr("Extension pack '%s' is already installed."
     1054                                              " In case of a reinstallation, please uninstall it first"),
     1055                                           pStrName->c_str());
     1056                        delete pStrName;
    10701057                    }
    10711058                    else
    1072                         hrc = E_OUTOFMEMORY;
     1059                        hrc = setError(E_FAIL, tr("Malformed '%s' file name"), strTarball.c_str());
    10731060                }
    10741061                else if (RT_SUCCESS(vrc))
  • trunk/src/VBox/Main/ExtPackUtil.cpp

    r33656 r33806  
    1515*   Header Files                                                               *
    1616*******************************************************************************/
    17 #include "ExtPackUtil.h"
     17#include "include/ExtPackUtil.h"
    1818
    1919#include <iprt/ctype.h>
     
    150150
    151151/**
     152 * Extract the extension pack name from the tarball path.
     153 *
     154 * @returns String containing the name on success, the caller must delete it.
     155 *          NULL if no valid name was found or if we ran out of memory.
     156 * @param   pszTarball          The path to the tarball.
     157 */
     158iprt::MiniString *VBoxExtPackExtractNameFromTarballPath(const char *pszTarball)
     159{
     160    /*
     161     * Skip ahead to the filename part and count the number of characters
     162     * that matches the criteria for a extension pack name.
     163     */
     164    const char *pszSrc = RTPathFilename(pszTarball);
     165    if (!pszSrc)
     166        return NULL;
     167
     168    size_t off = 0;
     169    while (RT_C_IS_ALNUM(pszSrc[off]) || pszSrc[off] == ' ')
     170        off++;
     171
     172    /*
     173     * Check min and max name limits.
     174     */
     175    if (   off > VBOX_EXTPACK_NAME_MIN_LEN
     176        || off < VBOX_EXTPACK_NAME_MIN_LEN)
     177        return NULL;
     178
     179    /*
     180     * Make a duplicate of the name and return it.
     181     */
     182    iprt::MiniString *pStrRet = new iprt::MiniString(off, pszSrc);
     183    Assert(VBoxExtPackIsValidName(pStrRet->c_str()));
     184    return pStrRet;
     185}
     186
     187
     188/**
    152189 * Validates the extension pack name.
    153190 *
    154191 * @returns true if valid, false if not.
    155192 * @param   pszName             The name to validate.
     193 * @sa      VBoxExtPackExtractNameFromTarballPath
    156194 */
    157195bool VBoxExtPackIsValidName(const char *pszName)
    158196{
    159     /* This must match the code in the extension manager. */
    160     if (!pszName || *pszName == '\0')
    161         return false;
    162     while (RT_C_IS_ALNUM(*pszName) || *pszName == ' ')
    163         pszName++;
    164     return *pszName == '\0';
     197    if (!pszName)
     198        return false;
     199
     200    /*
     201     * Check the characters making up the name, only english alphabet
     202     * characters, decimal digits and spaces are allowed.
     203     */
     204    size_t off = 0;
     205    while (pszName[off])
     206    {
     207        if (!RT_C_IS_ALNUM(pszName[off]) && !pszName[off] == ' ')
     208            return false;
     209        off++;
     210    }
     211
     212    /*
     213     * Check min and max name limits.
     214     */
     215    if (   off > VBOX_EXTPACK_NAME_MIN_LEN
     216        || off < VBOX_EXTPACK_NAME_MIN_LEN)
     217        return false;
     218
     219    return true;
    165220}
    166221
  • trunk/src/VBox/Main/Makefile.kmk

    r33784 r33806  
    730730ifeq ($(LOGNAME),bird) # def VBOX_WITH_EXTPACK
    731731 PROGRAMS += VBoxExtPackHelperApp
    732  VBoxExtPackHelperApp_TEMPLATE = VBoxR3Static
    733  VBoxExtPackHelperApp_SOURCES = VBoxExtPackHelperApp.cpp
    734  VBoxExtPackHelperApp_DEFS = IN_RT_R3
     732 VBoxExtPackHelperApp_TEMPLATE = VBoxR3SetUidToRoot
     733 VBoxExtPackHelperApp_SOURCES = \
     734        VBoxExtPackHelperApp.cpp \
     735        ExtPackUtil.cpp
    735736 VBoxExtPackHelperApp_LIBS = \
    736         $(VBOX_LIB_RUNTIME_STATIC)
     737        $(LIB_RUNTIME)
     738
    737739endif # VBOX_WITH_EXTPACK
    738740
  • trunk/src/VBox/Main/VBoxExtPackHelperApp.cpp

    r33784 r33806  
    1919#include <iprt/buildconfig.h>
    2020//#include <iprt/ctype.h>
    21 //#include <iprt/dir.h>
     21#include <iprt/dir.h>
    2222//#include <iprt/env.h>
    23 //#include <iprt/file.h>
     23#include <iprt/file.h>
     24#include <iprt/fs.h>
    2425#include <iprt/getopt.h>
    2526#include <iprt/initterm.h>
    2627#include <iprt/message.h>
    27 //#include <iprt/param.h>
     28#include <iprt/param.h>
    2829#include <iprt/path.h>
    2930//#include <iprt/pipe.h>
     31#include <iprt/process.h>
    3032#include <iprt/string.h>
    3133#include <iprt/stream.h>
     
    3335#include <VBox/log.h>
    3436#include <VBox/err.h>
     37#include <VBox/sup.h>
    3538#include <VBox/version.h>
    3639
     
    4043{
    4144    return true;
     45}
     46
     47
     48/**
     49 * Handle the special standard options when these are specified after the
     50 * command.
     51 *
     52 * @param   ch          The option character.
     53 */
     54static RTEXITCODE DoStandardOption(int ch)
     55{
     56    switch (ch)
     57    {
     58        case 'h':
     59        {
     60            RTMsgInfo(VBOX_PRODUCT " Extension Pack Helper App\n"
     61                      "(C) " VBOX_C_YEAR " " VBOX_VENDOR "\n"
     62                      "All rights reserved.\n"
     63                      "\n"
     64                      "This NOT intended for general use, please use VBoxManage instead\n"
     65                      "or call the IExtPackManager API directly.\n"
     66                      "\n"
     67                      "Usage: %s <command> [options]\n"
     68                      "Commands:\n"
     69                      "    install --base-dir <dir> --certificate-dir <dir> --name <name> \\\n"
     70                      "        --tarball <tarball> --tarball-fd <fd>\n"
     71                      "    uninstall --base-dir <dir> --name <name>\n"
     72                      , RTProcShortName());
     73            return RTEXITCODE_SUCCESS;
     74        }
     75
     76        case 'V':
     77            RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision());
     78            return RTEXITCODE_SUCCESS;
     79
     80        default:
     81            AssertFailedReturn(RTEXITCODE_FAILURE);
     82    }
     83}
     84
     85
     86/**
     87 * Checks if the cerficiate directory is valid.
     88 *
     89 * @returns true if it is valid, false if it isn't.
     90 * @param   pszCertDir          The certificate directory to validate.
     91 */
     92static bool IsValidCertificateDir(const char *pszCertDir)
     93{
     94    /*
     95     * Just be darn strict for now.
     96     */
     97    char szCorrect[RTPATH_MAX];
     98    int rc = RTPathAppPrivateNoArch(szCorrect, sizeof(szCorrect));
     99    if (RT_FAILURE(rc))
     100        return false;
     101    rc = RTPathAppend(szCorrect, sizeof(szCorrect), VBOX_EXTPACK_CERT_DIR);
     102    if (RT_FAILURE(rc))
     103        return false;
     104
     105    return RTPathCompare(szCorrect, pszCertDir) == 0;
     106}
     107
     108
     109/**
     110 * Checks if the base directory is valid.
     111 *
     112 * @returns true if it is valid, false if it isn't.
     113 * @param   pszBaesDir          The base directory to validate.
     114 */
     115static bool IsValidBaseDir(const char *pszBaseDir)
     116{
     117    /*
     118     * Just be darn strict for now.
     119     */
     120    char szCorrect[RTPATH_MAX];
     121    int rc = RTPathAppPrivateArch(szCorrect, sizeof(szCorrect));
     122    if (RT_FAILURE(rc))
     123        return false;
     124    rc = RTPathAppend(szCorrect, sizeof(szCorrect), VBOX_EXTPACK_INSTALL_DIR);
     125    if (RT_FAILURE(rc))
     126        return false;
     127
     128    return RTPathCompare(szCorrect, pszBaseDir) == 0;
     129}
     130
     131/**
     132 * Cleans up a temporary extension pack directory.
     133 *
     134 * This is used by 'uninstall', 'cleanup' and in the failure path of 'install'.
     135 *
     136 * @returns The program exit code.
     137 * @param   pszDir          The directory to clean up.  The caller is
     138 *                          responsible for making sure this is valid.
     139 * @param   fTemporary      Whether this is a temporary install directory or
     140 *                          not.
     141 */
     142static RTEXITCODE RemoveExtPackDir(const char *pszDir, bool fTemporary)
     143{
     144    /** @todo May have to undo 555 modes here later.  */
     145    int rc = RTDirRemoveRecursive(pszDir, RTDIRRMREC_F_CONTENT_AND_DIR);
     146    if (RT_FAILURE(rc))
     147        return RTMsgErrorExit(RTEXITCODE_FAILURE,
     148                              "Failed to delete the %sextension pack directory: %Rrc ('%s')",
     149                              fTemporary ? "temporary " : "", rc, pszDir);
     150    return RTEXITCODE_SUCCESS;
     151}
     152
     153
     154/**
     155 * Sets the permissions of the temporary extension pack directory just before
     156 * renaming it.
     157 *
     158 * By default the temporary directory is only accessible by root, this function
     159 * will make it world readable and browseable.
     160 *
     161 * @returns The program exit code.
     162 * @param   pszDir              The temporary extension pack directory.
     163 */
     164static RTEXITCODE SetExtPackPermissions(const char *pszDir)
     165{
     166#if !defined(RT_OS_WINDOWS)
     167     int rc = RTPathSetMode(pszDir, 0755);
     168     if (RT_FAILURE(rc))
     169         return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to set directory permissions: %Rrc ('%s')", rc, pszDir);
     170#else
     171        /** @todo  */
     172#endif
     173
     174    return RTEXITCODE_SUCCESS;
     175}
     176
     177/**
     178 * Validates the extension pack.
     179 *
     180 * Operations performed:
     181 *      - Manifest seal check.
     182 *      - Manifest check.
     183 *      - Recursive hardening check.
     184 *      - XML validity check.
     185 *      - Name check (against XML).
     186 *
     187 * @returns The program exit code.
     188 * @param   pszDir              The directory where the extension pack has been
     189 *                              unpacked.
     190 * @param   pszName             The expected extension pack name.
     191 * @param   pszTarball          The name of the tarball in case we have to
     192 *                              complain about something.
     193 */
     194static RTEXITCODE ValidateExtPack(const char *pszDir, const char *pszTarball, const char *pszName)
     195{
     196    /** @todo  */
     197    return RTEXITCODE_SUCCESS;
     198}
     199
     200
     201/**
     202 * Unpacks the extension pack into the specified directory.
     203 *
     204 * This will apply ownership and permission changes to all the content, the
     205 * exception is @a pszDirDst which will be handled by SetExtPackPermissions.
     206 *
     207 * @returns The program exit code.
     208 * @param   hTarballFile        The tarball to unpack.
     209 * @param   pszDirDst           Where to unpack it.
     210 * @param   pszTarball          The name of the tarball in case we have to
     211 *                              complain about something.
     212 */
     213static RTEXITCODE UnpackExtPack(RTFILE hTarballFile, const char *pszDirDst, const char *pszTarball)
     214{
     215    /** @todo  */
     216    return RTEXITCODE_SUCCESS;
     217}
     218
     219
     220/**
     221 * The 2nd part of the installation process.
     222 *
     223 * @returns The program exit code.
     224 * @param   pszBaseDir          The base directory.
     225 * @param   pszCertDir          The certificat directory.
     226 * @param   pszTarball          The tarball name.
     227 * @param   hTarballFile        The handle to open the @a pszTarball file.
     228 * @param   hTarballFileOpt     The tarball file handle (optional).
     229 * @param   pszName             The extension pack name.
     230 */
     231static RTEXITCODE DoInstall2(const char *pszBaseDir, const char *pszCertDir, const char *pszTarball,
     232                             RTFILE hTarballFile, RTFILE hTarballFileOpt, const char *pszName)
     233{
     234    /*
     235     * Do some basic validation of the tarball file.
     236     */
     237    RTFSOBJINFO ObjInfo;
     238    int rc = RTFileQueryInfo(hTarballFile, &ObjInfo, RTFSOBJATTRADD_UNIX);
     239    if (RT_FAILURE(rc))
     240        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTFileQueryInfo failed with %Rrc on '%s'", rc, pszTarball);
     241    if (!RTFS_IS_FILE(ObjInfo.Attr.fMode))
     242        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Not a regular file: %s", pszTarball);
     243
     244    if (hTarballFileOpt != NIL_RTFILE)
     245    {
     246        RTFSOBJINFO ObjInfo2;
     247        rc = RTFileQueryInfo(hTarballFileOpt, &ObjInfo2, RTFSOBJATTRADD_UNIX);
     248        if (RT_FAILURE(rc))
     249            return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTFileQueryInfo failed with %Rrc on --tarball-fd", rc);
     250        if (   ObjInfo.Attr.u.Unix.INodeIdDevice != ObjInfo2.Attr.u.Unix.INodeIdDevice
     251            || ObjInfo.Attr.u.Unix.INodeId       != ObjInfo2.Attr.u.Unix.INodeId)
     252            return RTMsgErrorExit(RTEXITCODE_FAILURE, "--tarball and --tarball-fd does not match");
     253    }
     254
     255    /*
     256     * Construct the paths to the two directories we'll be using.
     257     */
     258    char szFinalPath[RTPATH_MAX];
     259    rc = RTPathJoin(szFinalPath, sizeof(szFinalPath), pszBaseDir, pszName);
     260    if (RT_FAILURE(rc))
     261        return RTMsgErrorExit(RTEXITCODE_FAILURE,
     262                              "Failed to construct the path to the final extension pack directory: %Rrc", rc);
     263
     264    char szTmpPath[RTPATH_MAX];
     265    rc = RTPathJoin(szTmpPath, sizeof(szTmpPath) - 64, pszBaseDir, pszName);
     266    if (RT_SUCCESS(rc))
     267    {
     268        size_t cchTmpPath = strlen(szTmpPath);
     269        RTStrPrintf(&szTmpPath[cchTmpPath], sizeof(szTmpPath) - cchTmpPath, "-_-inst-%u", (uint32_t)RTProcSelf());
     270    }
     271    if (RT_FAILURE(rc))
     272        return RTMsgErrorExit(RTEXITCODE_FAILURE,
     273                              "Failed to construct the path to the temporary extension pack directory: %Rrc", rc);
     274
     275    /*
     276     * Check that they don't exist at this point in time.
     277     */
     278    rc = RTPathQueryInfoEx(szFinalPath, &ObjInfo, RTFSOBJATTRADD_NOTHING,  RTPATH_F_ON_LINK);
     279    if (RT_SUCCESS(rc) && RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
     280        return RTMsgErrorExit(RTEXITCODE_FAILURE, "The extension pack is already installed. You must uninstall the old one first.");
     281    if (RT_SUCCESS(rc))
     282        return RTMsgErrorExit(RTEXITCODE_FAILURE,
     283                              "Found non-directory file system object where the extension pack would be installed ('%s')",
     284                              szFinalPath);
     285    if (rc != VERR_FILE_NOT_FOUND && rc != VERR_PATH_NOT_FOUND)
     286        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Unexpected RTPathQueryInfoEx status code %Rrc for '%s'", rc, szFinalPath);
     287
     288    rc = RTPathQueryInfoEx(szTmpPath, &ObjInfo, RTFSOBJATTRADD_NOTHING,  RTPATH_F_ON_LINK);
     289    if (rc != VERR_FILE_NOT_FOUND && rc != VERR_PATH_NOT_FOUND)
     290        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Unexpected RTPathQueryInfoEx status code %Rrc for '%s'", rc, szFinalPath);
     291
     292    /*
     293     * Create the temporary directory and prepare the extension pack within it.
     294     * If all checks out correctly, rename it to the final directory.
     295     */
     296    rc = RTDirCreate(szTmpPath, 0700);
     297    if (RT_FAILURE(rc))
     298        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to create temporary directory: %Rrc ('%s')", rc, szTmpPath);
     299
     300    RTEXITCODE rcExit = UnpackExtPack(hTarballFile, szTmpPath, pszTarball);
     301    if (rcExit == RTEXITCODE_SUCCESS)
     302        rcExit = ValidateExtPack(szTmpPath, pszTarball, pszName);
     303    if (rcExit == RTEXITCODE_SUCCESS)
     304        rcExit = SetExtPackPermissions(szTmpPath);
     305    if (rcExit == RTEXITCODE_SUCCESS)
     306    {
     307        rc = RTDirRename(szTmpPath, szFinalPath, RTPATHRENAME_FLAGS_NO_REPLACE);
     308        if (RT_SUCCESS(rc))
     309            RTMsgInfo("Successfully installed '%s' (%s)", pszName, pszTarball);
     310        else
     311            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE,
     312                                    "Failed to rename the temporary directory to the final one: %Rrc ('%s' -> '%s')",
     313                                    rc, szTmpPath, szFinalPath);
     314    }
     315
     316    /*
     317     * Clean up the temporary directory on failure.
     318     */
     319    if (rcExit != RTEXITCODE_SUCCESS)
     320        RemoveExtPackDir(szTmpPath, true /*fTemporary*/);
     321
     322    return rcExit;
    42323}
    43324
     
    52333static RTEXITCODE DoInstall(int argc, char **argv)
    53334{
    54     return RTEXITCODE_FAILURE;
    55 }
     335    /*
     336     * Parse the parameters.
     337     *
     338     * Note! The --base-dir and --cert-dir are only for checking that the
     339     *       caller and this help applications have the same idea of where
     340     *       things are.  Likewise, the --name is for verifying assumptions
     341     *       the caller made about the name.  The optional --tarball-fd option
     342     *       is just for easing the paranoia on the user side.
     343     */
     344    static const RTGETOPTDEF s_aOptions[] =
     345    {
     346        { "--base-dir",     'b',   RTGETOPT_REQ_STRING },
     347        { "--cert-dir",     'c',   RTGETOPT_REQ_STRING },
     348        { "--name",         'n',   RTGETOPT_REQ_STRING },
     349        { "--tarball",      't',   RTGETOPT_REQ_STRING },
     350        { "--tarball-fd",   'f',   RTGETOPT_REQ_UINT64 }
     351    };
     352    RTGETOPTSTATE   GetState;
     353    int rc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
     354    if (RT_FAILURE(rc))
     355        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOptInit failed: %Rrc\n", rc);
     356
     357    const char     *pszBaseDir      = NULL;
     358    const char     *pszCertDir      = NULL;
     359    const char     *pszName         = NULL;
     360    const char     *pszTarball      = NULL;
     361    RTFILE          hTarballFileOpt = NIL_RTFILE;
     362    RTGETOPTUNION   ValueUnion;
     363    int             ch;
     364    while ((ch = RTGetOpt(&GetState, &ValueUnion)))
     365    {
     366        switch (ch)
     367        {
     368            case 'b':
     369                if (pszBaseDir)
     370                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many --base-dir options");
     371                pszBaseDir = ValueUnion.psz;
     372                if (!IsValidBaseDir(pszBaseDir))
     373                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "Invalid base directory: '%s'", pszBaseDir);
     374                break;
     375
     376            case 'c':
     377                if (pszCertDir)
     378                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many --cert-dir options");
     379                pszCertDir = ValueUnion.psz;
     380                if (!IsValidCertificateDir(pszCertDir))
     381                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "Invalid certificate directory: '%s'", pszCertDir);
     382                break;
     383
     384            case 'n':
     385                if (pszName)
     386                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many --name options");
     387                pszName = ValueUnion.psz;
     388                if (!VBoxExtPackIsValidName(pszName))
     389                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "Invalid extension pack name: '%s'", pszName);
     390                break;
     391
     392            case 't':
     393                if (pszTarball)
     394                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many --tarball options");
     395                pszTarball = ValueUnion.psz;
     396                break;
     397
     398            case 'd':
     399            {
     400                if (hTarballFileOpt != NIL_RTFILE)
     401                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many --tarball-fd options");
     402                RTHCUINTPTR hNative = (RTHCUINTPTR)ValueUnion.u64;
     403                if (hNative != ValueUnion.u64)
     404                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "The --tarball-fd value is out of range: %#RX64", ValueUnion.u64);
     405                rc = RTFileFromNative(&hTarballFileOpt, hNative);
     406                if (RT_FAILURE(rc))
     407                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "RTFileFromNative failed on --target-fd value: %Rrc", rc);
     408                break;
     409            }
     410
     411            case 'h':
     412            case 'V':
     413                return DoStandardOption(ch);
     414
     415            default:
     416                return RTGetOptPrintError(ch, &ValueUnion);
     417        }
     418        break;
     419    }
     420    if (!pszName)
     421        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Missing --name option");
     422    if (!pszBaseDir)
     423        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Missing --base-dir option");
     424    if (!pszCertDir)
     425        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Missing --cert-dir option");
     426    if (!pszTarball)
     427        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Missing --tarball option");
     428
     429    /*
     430     * Ok, down to business.
     431     */
     432    RTFILE hTarballFile;
     433    rc = RTFileOpen(&hTarballFile, pszTarball, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     434    if (RT_FAILURE(rc))
     435        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to open the extension pack tarball: %Rrc ('%s')", rc, pszTarball);
     436
     437    RTEXITCODE rcExit = DoInstall2(pszBaseDir, pszCertDir, pszTarball, hTarballFile, hTarballFileOpt, pszName);
     438    RTFileClose(hTarballFile);
     439    return rcExit;
     440}
     441
    56442
    57443/**
     
    64450static RTEXITCODE DoUninstall(int argc, char **argv)
    65451{
    66     return RTEXITCODE_FAILURE;
    67 }
    68 
    69 
    70 int main(int argc, char **argv)
    71 {
    72     int rc = RTR3Init();
    73     if (RT_FAILURE(rc))
    74         return RTMsgInitFailure(rc);
    75 
    76     RTEXITCODE rcExit = RTEXITCODE_FAILURE;
    77     if (argc > 1)
    78     {
    79         /*
    80          * Command string switch.
    81          */
    82         if (!strcmp(argv[1], "install"))
    83             rcExit = DoInstall(argc, argv);
    84         else if (!strcmp(argv[1], "uninstall"))
    85             rcExit = DoUninstall(argc, argv);
    86         else
     452    /*
     453     * Parse the parameters.
     454     *
     455     * Note! The --base-dir is only for checking that the caller and this help
     456     *       applications have the same idea of where things are.
     457     */
     458    static const RTGETOPTDEF s_aOptions[] =
     459    {
     460        { "--base-dir",     'b',   RTGETOPT_REQ_STRING },
     461        { "--name",         'n',   RTGETOPT_REQ_STRING }
     462    };
     463    RTGETOPTSTATE   GetState;
     464    int rc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
     465    if (RT_FAILURE(rc))
     466        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOptInit failed: %Rrc\n", rc);
     467
     468    const char     *pszBaseDir = NULL;
     469    const char     *pszName    = NULL;
     470    RTGETOPTUNION   ValueUnion;
     471    int             ch;
     472    while ((ch = RTGetOpt(&GetState, &ValueUnion)))
     473    {
     474        switch (ch)
    87475        {
    88             /*
    89              * Didn't match a command, check for standard options.
    90              */
    91             RTGETOPTSTATE State;
    92             rc = RTGetOptInit(&State, argc, argv, NULL, 0, 1, 0 /*fFlags*/);
     476            case 'b':
     477                if (pszBaseDir)
     478                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many --base-dir options");
     479                pszBaseDir = ValueUnion.psz;
     480                if (!IsValidBaseDir(pszBaseDir))
     481                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "Invalid base directory: '%s'", pszBaseDir);
     482                break;
     483
     484            case 'n':
     485                if (pszName)
     486                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many --name options");
     487                pszName = ValueUnion.psz;
     488                if (!VBoxExtPackIsValidName(pszName))
     489                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "Invalid extension pack name: '%s'", pszName);
     490                break;
     491
     492            case 'h':
     493            case 'V':
     494                return DoStandardOption(ch);
     495
     496            default:
     497                return RTGetOptPrintError(ch, &ValueUnion);
     498        }
     499        break;
     500    }
     501    if (!pszName)
     502        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Missing --name option");
     503    if (!pszBaseDir)
     504        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Missing --base-dir option");
     505
     506    /*
     507     * Ok, down to business.
     508     */
     509    /* Check that it exists. */
     510    char szExtPackDir[RTPATH_MAX];
     511    rc = RTPathJoin(szExtPackDir, sizeof(szExtPackDir), pszBaseDir, pszName);
     512    if (RT_FAILURE(rc))
     513        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to construct extension pack path: %Rrc", rc);
     514
     515    if (!RTDirExists(szExtPackDir))
     516    {
     517        RTMsgInfo("Extension pack not installed. Nothing to do.");
     518        return RTEXITCODE_SUCCESS;
     519    }
     520
     521    /* Rename the extension pack directory before deleting it to prevent new
     522       VM processes from picking it up. */
     523    char szExtPackUnInstDir[RTPATH_MAX];
     524    rc = RTPathJoin(szExtPackUnInstDir, sizeof(szExtPackUnInstDir), pszBaseDir, pszName);
     525    if (RT_SUCCESS(rc))
     526        rc = RTStrCat(szExtPackUnInstDir, sizeof(szExtPackUnInstDir), "-_-uninst");
     527    if (RT_FAILURE(rc))
     528        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to construct temporary extension pack path: %Rrc", rc);
     529
     530    rc = RTDirRename(szExtPackDir, szExtPackUnInstDir, RTPATHRENAME_FLAGS_NO_REPLACE);
     531    if (RT_FAILURE(rc))
     532        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to rename the extension pack directory: %Rrc", rc);
     533
     534    /* Recursively delete the directory content. */
     535    RTEXITCODE rcExit = RemoveExtPackDir(szExtPackUnInstDir, false /*fTemporary*/);
     536    if (rcExit == RTEXITCODE_SUCCESS)
     537        RTMsgInfo("Successfully removed extension pack '%s'\n", pszName);
     538
     539    return rcExit;
     540}
     541
     542/**
     543 * Implements the 'cleanup' command.
     544 *
     545 * @returns The program exit code.
     546 * @param   argc            The number of program arguments.
     547 * @param   argv            The program arguments.
     548 */
     549static RTEXITCODE DoCleanup(int argc, char **argv)
     550{
     551    /*
     552     * Parse the parameters.
     553     *
     554     * Note! The --base-dir is only for checking that the caller and this help
     555     *       applications have the same idea of where things are.
     556     */
     557    static const RTGETOPTDEF s_aOptions[] =
     558    {
     559        { "--base-dir",     'b',   RTGETOPT_REQ_STRING },
     560    };
     561    RTGETOPTSTATE   GetState;
     562    int rc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
     563    if (RT_FAILURE(rc))
     564        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOptInit failed: %Rrc\n", rc);
     565
     566    const char     *pszBaseDir = NULL;
     567    RTGETOPTUNION   ValueUnion;
     568    int             ch;
     569    while ((ch = RTGetOpt(&GetState, &ValueUnion)))
     570    {
     571        switch (ch)
     572        {
     573            case 'b':
     574                if (pszBaseDir)
     575                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Too many --base-dir options");
     576                pszBaseDir = ValueUnion.psz;
     577                if (!IsValidBaseDir(pszBaseDir))
     578                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "Invalid base directory: '%s'", pszBaseDir);
     579                break;
     580
     581            case 'h':
     582            case 'V':
     583                return DoStandardOption(ch);
     584
     585            default:
     586                return RTGetOptPrintError(ch, &ValueUnion);
     587        }
     588        break;
     589    }
     590    if (!pszBaseDir)
     591        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Missing --base-dir option");
     592
     593    /*
     594     * Ok, down to business.
     595     */
     596    PRTDIR pDir;
     597    rc = RTDirOpen(&pDir, pszBaseDir);
     598    if (RT_FAILURE(rc))
     599        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed open the base directory: %Rrc ('%s')", rc, pszBaseDir);
     600
     601    uint32_t    cCleaned = 0;
     602    RTEXITCODE  rcExit = RTEXITCODE_SUCCESS;
     603    for (;;)
     604    {
     605        RTDIRENTRYEX Entry;
     606        rc = RTDirReadEx(pDir, &Entry, NULL /*pcbDirEntry*/, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
     607        if (RT_FAILURE(rc))
     608        {
     609            if (rc != VERR_NO_MORE_FILES)
     610                rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTDirReadEx returns %Rrc", rc);
     611            break;
     612        }
     613        if (   RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode)
     614            && strcmp(Entry.szName, ".")  != 0
     615            && strcmp(Entry.szName, "..") != 0
     616            && !VBoxExtPackIsValidName(Entry.szName) )
     617        {
     618            char szPath[RTPATH_MAX];
     619            rc = RTPathJoin(szPath, sizeof(szPath), pszBaseDir, Entry.szName);
    93620            if (RT_SUCCESS(rc))
    94621            {
    95                 for (;;)
    96                 {
    97                     RTGETOPTUNION ValueUnion;
    98                     int ch = RTGetOpt(&State, &ValueUnion);
    99                     switch (ch)
    100                     {
    101                         case 'h':
    102                             RTMsgInfo(VBOX_PRODUCT " Extension Pack Helper App\n"
    103                                       "(C) " VBOX_C_YEAR " " VBOX_VENDOR "\n"
    104                                       "All rights reserved.\n"
    105                                       "\n"
    106                                       "This NOT intended for general use, please use VBoxManage instead\n"
    107                                       "or call the IExtPackManager API directly.\n"
    108                                       "\n"
    109                                       "Usage: %s <command> [options]\n"
    110                                       "Commands:\n"
    111                                       "    install --base-dir <dir> --name <name> --tarball <tarball> --tarball-fd <fd>\n"
    112                                       "    uninstall --base-dir <dir> --name <name>\n"
    113                                       , RTPathFilename(argv[0]));
    114                             rcExit = RTEXITCODE_SUCCESS;
    115                             break;
    116 
    117                         case 'V':
    118                             RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision());
    119                             rcExit = RTEXITCODE_SUCCESS;
    120                             break;
    121 
    122                         default:
    123                             rcExit = RTGetOptPrintError(ch, &ValueUnion);
    124                             break;
    125                     }
    126                 }
     622                RTEXITCODE rcExit2 = RemoveExtPackDir(szPath, true /*fTemporary*/);
     623                if (rcExit2 == RTEXITCODE_SUCCESS)
     624                    RTMsgInfo("Successfully removed '%s'.", Entry.szName);
     625                else if (rcExit == RTEXITCODE_SUCCESS)
     626                    rcExit = rcExit2;
    127627            }
    128628            else
    129                 RTMsgError("RTGetOptInit failed: %Rrc\n", rc);
     629                rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathJoin failed with %Rrc for '%s'", rc, Entry.szName);
     630            cCleaned++;
    130631        }
    131632    }
    132     else
    133         RTMsgError("No command was specified\n");
     633    RTDirClose(pDir);
     634    if (!cCleaned)
     635        RTMsgInfo("Nothing to clean.");
    134636    return rcExit;
    135637}
    136638
     639
     640
     641int main(int argc, char **argv)
     642{
     643    /*
     644     * Initialize IPRT and check that we're correctly installed.
     645     */
     646    int rc = RTR3Init();
     647    if (RT_FAILURE(rc))
     648        return RTMsgInitFailure(rc);
     649
     650    char szErr[2048];
     651    rc = SUPR3HardenedVerifySelf(argv[0], true /*fInternal*/, szErr, sizeof(szErr));
     652    if (RT_FAILURE(rc))
     653        return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s", szErr);
     654
     655    /*
     656     * Parse the top level arguments until we find a command.
     657     */
     658    static const RTGETOPTDEF s_aOptions[] =
     659    {
     660#define CMD_INSTALL     1000
     661        { "install",    CMD_INSTALL,    RTGETOPT_REQ_NOTHING },
     662#define CMD_UNINSTALL   1001
     663        { "uninstall",  CMD_UNINSTALL,  RTGETOPT_REQ_NOTHING },
     664#define CMD_CLEANUP     1002
     665        { "cleanup",    CMD_CLEANUP,    RTGETOPT_REQ_NOTHING },
     666    };
     667    RTGETOPTSTATE GetState;
     668    rc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
     669    if (RT_FAILURE(rc))
     670        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOptInit failed: %Rrc\n", rc);
     671    for (;;)
     672    {
     673        RTGETOPTUNION ValueUnion;
     674        int ch = RTGetOpt(&GetState, &ValueUnion);
     675        switch (ch)
     676        {
     677            case 0:
     678                return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No command specified");
     679
     680            case CMD_INSTALL:
     681                return DoInstall(argc, argv);
     682
     683            case CMD_UNINSTALL:
     684                return DoUninstall(argc, argv);
     685
     686            case CMD_CLEANUP:
     687                return DoCleanup(argc, argv);
     688
     689            case 'h':
     690            case 'V':
     691                return DoStandardOption(ch);
     692
     693            default:
     694                return RTGetOptPrintError(ch, &ValueUnion);
     695        }
     696        /* not currently reached */
     697    }
     698    /* not reached */
     699}
     700
  • trunk/src/VBox/Main/VirtualBoxImpl.cpp

    r33784 r33806  
    20622062        /* get the path to the executable */
    20632063        char exePathBuf[RTPATH_MAX];
    2064         char *exePath = RTProcGetExecutableName(exePathBuf, RTPATH_MAX);
     2064        char *exePath = RTProcGetExecutablePath(exePathBuf, RTPATH_MAX);
    20652065        if (!exePath)
    20662066        {
  • trunk/src/VBox/Main/generic/OpenGLTestApp.cpp

    r28800 r33806  
    166166        /* the package type is interesting for Linux distributions */
    167167        char szExecName[RTPATH_MAX];
    168         char *pszExecName = RTProcGetExecutableName(szExecName, sizeof(szExecName));
     168        char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
    169169        RTLogRelLogger(loggerRelease, 0, ~0U,
    170170                       "Executable: %s\n"
  • trunk/src/VBox/Main/include/ExtPackUtil.h

    r33693 r33806  
    2424 * The suffix of a extension pack tarball. */
    2525#define VBOX_EXTPACK_SUFFIX             ".vbox-extpack"
     26
     27/** The minimum length (strlen) of a extension pack name. */
     28#define VBOX_EXTPACK_NAME_MIN_LEN       6
     29/** The max length (strlen) of a extension pack name. */
     30#define VBOX_EXTPACK_NAME_MAX_LEN       64
     31
     32/** The architecture-dependent application data subdirectory where the
     33 * extension packs are installed.  Relative to RTPathAppPrivateArch. */
     34#define VBOX_EXTPACK_INSTALL_DIR        "ExtensionPacks"
     35/** The architecture-independent application data subdirectory where the
     36 * certificates are installed.  Relative to RTPathAppPrivateNoArch. */
     37#define VBOX_EXTPACK_CERT_DIR           "Certificates"
    2638
    2739
     
    5264
    5365iprt::MiniString *VBoxExtPackLoadDesc(const char *a_pszDir, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo);
     66iprt::MiniString *VBoxExtPackExtractNameFromTarballPath(const char *pszTarball);
    5467bool    VBoxExtPackIsValidName(const char *pszName);
    5568bool    VBoxExtPackIsValidVersionString(const char *pszName);
  • trunk/src/VBox/Runtime/VBox/RTAssertShouldPanic-vbox.cpp

    r28800 r33806  
    116116        {
    117117            char *pszExecName = &szCmd[cch];
    118             if (!RTProcGetExecutableName(pszExecName, sizeof(szCmd) - cch))
     118            if (!RTProcGetExecutablePath(pszExecName, sizeof(szCmd) - cch))
    119119                *pszExecName = '\0';
    120120        }
  • trunk/src/VBox/Runtime/VBox/log-vbox.cpp

    r33664 r33806  
    297297# ifndef IN_GUEST
    298298    char szExecName[RTPATH_MAX];
    299     if (!RTProcGetExecutableName(szExecName, sizeof(szExecName)))
     299    if (!RTProcGetExecutablePath(szExecName, sizeof(szExecName)))
    300300        strcpy(szExecName, "VBox");
    301301    RTTIMESPEC TimeSpec;
  • trunk/src/VBox/Runtime/generic/RTProcDaemonize-generic.cpp

    r28800 r33806  
    4949     */
    5050    char szExecPath[RTPATH_MAX];
    51     AssertReturn(RTProcGetExecutableName(szExecPath, sizeof(szExecPath)) == szExecPath, VERR_WRONG_ORDER);
     51    AssertReturn(RTProcGetExecutablePath(szExecPath, sizeof(szExecPath)) == szExecPath, VERR_WRONG_ORDER);
    5252
    5353    /*
  • trunk/src/VBox/Runtime/r3/init.cpp

    r33595 r33806  
    8080
    8181/** The process path.
    82  * This is used by RTPathExecDir and RTProcGetExecutableName and set by rtProcInitName. */
     82 * This is used by RTPathExecDir and RTProcGetExecutablePath and set by rtProcInitName. */
    8383char        g_szrtProcExePath[RTPATH_MAX];
    8484/** The length of g_szrtProcExePath. */
  • trunk/src/VBox/Runtime/r3/process.cpp

    r33454 r33806  
    9292
    9393
    94 RTR3DECL(char *) RTProcGetExecutableName(char *pszExecName, size_t cchExecName)
     94RTR3DECL(char *) RTProcGetExecutablePath(char *pszExecPath, size_t cbExecPath)
    9595{
    9696    if (RT_UNLIKELY(g_szrtProcExePath[0] == '\0'))
     
    101101     */
    102102    size_t cch = g_cchrtProcExePath;
    103     if (cch < cchExecName)
     103    if (cch < cbExecPath)
    104104    {
    105         memcpy(pszExecName, g_szrtProcExePath, cch);
    106         pszExecName[cch] = '\0';
    107         return pszExecName;
     105        memcpy(pszExecPath, g_szrtProcExePath, cch);
     106        pszExecPath[cch] = '\0';
     107        return pszExecPath;
    108108    }
    109109
    110     AssertMsgFailed(("Buffer too small (%zu <= %zu)\n", cchExecName, cch));
     110    AssertMsgFailed(("Buffer too small (%zu <= %zu)\n", cbExecPath, cch));
    111111    return NULL;
    112112}
    113113
     114
     115RTR3DECL(const char *) RTProcShortName(void)
     116{
     117    return &g_szrtProcExePath[g_offrtProcName];
     118}
     119
  • trunk/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp

    r33540 r33806  
    19561956    pVBoxProc->CoreContent    = CC_CONTENT_DEFAULT;
    19571957
    1958     RTProcGetExecutableName(pVBoxProc->szExecPath, sizeof(pVBoxProc->szExecPath));  /* this gets full path not just name */
     1958    RTProcGetExecutablePath(pVBoxProc->szExecPath, sizeof(pVBoxProc->szExecPath));  /* this gets full path not just name */
    19591959    pVBoxProc->pszExecName = RTPathFilename(pVBoxProc->szExecPath);
    19601960
  • trunk/src/VBox/Runtime/testcase/tstRTDigest.cpp

    r32568 r33806  
    4848{
    4949    char szName[RTPATH_MAX];
    50     if (!RTProcGetExecutableName(szName, sizeof(szName)))
     50    if (!RTProcGetExecutablePath(szName, sizeof(szName)))
    5151        strcpy(szName, "tstRTDigest");
    5252
  • trunk/src/VBox/Runtime/testcase/tstRTPath.cpp

    r33450 r33806  
    5353
    5454    /*
    55      * RTPathExecDir, RTPathUserHome and RTProcGetExecutableName.
     55     * RTPathExecDir, RTPathUserHome and RTProcGetExecutablePath.
    5656     */
    5757    RTTestSub(hTest, "RTPathExecDir");
     
    6060        RTTestIPrintf(RTTESTLVL_INFO, "ExecDir={%s}\n", szPath);
    6161
    62     RTTestSub(hTest, "RTProcGetExecutableName");
    63     if (RTProcGetExecutableName(szPath, sizeof(szPath)) == szPath)
     62    RTTestSub(hTest, "RTProcGetExecutablePath");
     63    if (RTProcGetExecutablePath(szPath, sizeof(szPath)) == szPath)
    6464        RTTestIPrintf(RTTESTLVL_INFO, "ExecutableName={%s}\n", szPath);
    6565    else
    66         RTTestIFailed("RTProcGetExecutableName -> NULL");
     66        RTTestIFailed("RTProcGetExecutablePath -> NULL");
    6767
    6868    RTTestSub(hTest, "RTPathUserHome");
  • trunk/src/VBox/Runtime/testcase/tstRTPipe.cpp

    r28800 r33806  
    9494
    9595    char    szPathSelf[RTPATH_MAX];
    96     RTTESTI_CHECK_RETV(RTProcGetExecutableName(szPathSelf, sizeof(szPathSelf)) == szPathSelf);
     96    RTTESTI_CHECK_RETV(RTProcGetExecutablePath(szPathSelf, sizeof(szPathSelf)) == szPathSelf);
    9797
    9898    RTPIPE  hPipeR;
     
    157157
    158158    char    szPathSelf[RTPATH_MAX];
    159     RTTESTI_CHECK_RETV(RTProcGetExecutableName(szPathSelf, sizeof(szPathSelf)) == szPathSelf);
     159    RTTESTI_CHECK_RETV(RTProcGetExecutablePath(szPathSelf, sizeof(szPathSelf)) == szPathSelf);
    160160
    161161    RTPIPE  hPipeR;
  • trunk/src/VBox/Runtime/testcase/tstRTProcCreateEx.cpp

    r30093 r33806  
    436436    RTTestBanner(hTest);
    437437
    438     if (!RTProcGetExecutableName(g_szExecName, sizeof(g_szExecName)))
     438    if (!RTProcGetExecutablePath(g_szExecName, sizeof(g_szExecName)))
    439439        RTStrCopy(g_szExecName, sizeof(g_szExecName), argv[0]);
    440440
  • trunk/src/VBox/Runtime/testcase/tstRTProcIsRunningByName.cpp

    r28800 r33806  
    7272     * Test 3: Check for our own process, filename only.
    7373     */
    74     if (RTProcGetExecutableName(szExecPath, RTPATH_MAX))
     74    if (RTProcGetExecutablePath(szExecPath, RTPATH_MAX))
    7575    {
    7676        /* Strip any path components */
     
    105105    else
    106106    {
    107         RTPrintf("tstRTProcIsRunningByName: FAILURE - RTProcGetExecutableName failed!\n");
     107        RTPrintf("tstRTProcIsRunningByName: FAILURE - RTProcGetExecutablePath failed!\n");
    108108        cErrors++;
    109109    }
  • trunk/src/VBox/Runtime/testcase/tstRTSymlink.cpp

    r33426 r33806  
    129129
    130130    char szExecFile[RTPATH_MAX];
    131     RTTESTI_CHECK_RETV(RTProcGetExecutableName(szExecFile, sizeof(szExecFile)) != NULL);
     131    RTTESTI_CHECK_RETV(RTProcGetExecutablePath(szExecFile, sizeof(szExecFile)) != NULL);
    132132    size_t cchExecFile = strlen(szExecFile);
    133133    RTTESTI_CHECK(RTFileExists(szExecFile));
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette