VirtualBox

Changeset 60622 in vbox


Ignore:
Timestamp:
Apr 21, 2016 1:00:20 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
106770
Message:

Guest Control: Added proper handling for (VBoxService) toolbox exit codes, resolving various copyto/copyfrom bugs.

Location:
trunk
Files:
2 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/GuestControlSvc.h

    r57753 r60622  
     1/* $Id$ */
    12/** @file
    23 * Guest control service - Common header for host service and guest clients.
     
    45
    56/*
    6  * Copyright (C) 2011-2015 Oracle Corporation
     7 * Copyright (C) 2011-2016 Oracle Corporation
    78 *
    89 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    8283
    8384/**
    84  * Process status when executed in the guest.
    85  */
    86 enum eProcessStatus
    87 {
    88     /** Process is in an undefined state. */
    89     PROC_STS_UNDEFINED = 0,
    90     /** Process has been started. */
    91     PROC_STS_STARTED = 1,
    92     /** Process terminated normally. */
    93     PROC_STS_TEN = 2,
    94     /** Process terminated via signal. */
    95     PROC_STS_TES = 3,
    96     /** Process terminated abnormally. */
    97     PROC_STS_TEA = 4,
    98     /** Process timed out and was killed. */
    99     PROC_STS_TOK = 5,
    100     /** Process timed out and was not killed successfully. */
    101     PROC_STS_TOA = 6,
    102     /** Service/OS is stopping, process was killed. */
    103     PROC_STS_DWN = 7,
    104     /** Something went wrong (error code in flags). */
    105     PROC_STS_ERROR = 8
    106 };
    107 
    108 /** @todo r=bird: Most defines in this file needs to be scoped a little
    109  *        better!  For instance INPUT_FLAG_NONE is very generic. */
    110 
    111 /**
    112  * Input flags, set by the host. This is needed for
    113  * handling flags on the guest side.
    114  * Note: Has to match Main's ProcessInputFlag_* flags!
    115  */
    116 #define INPUT_FLAG_NONE                     0x0
    117 #define INPUT_FLAG_EOF                      RT_BIT(0)
    118 
    119 /**
    120  * Guest session creation flags.
    121  * Only handled internally at the moment.
    122  */
    123 #define SESSIONCREATIONFLAG_NONE            0x0
    124 
    125 /**
    126  * Guest directory removement flags.
    127  * Essentially using what IPRT's RTDIRRMREC_F_
    128  * defines have to offer.
    129  */
    130 #define DIRREMOVE_FLAG_RECURSIVE            RT_BIT(0)
    131 /** Delete the content of the directory and the directory itself. */
    132 #define DIRREMOVE_FLAG_CONTENT_AND_DIR      RT_BIT(1)
    133 /** Only delete the content of the directory, omit the directory it self. */
    134 #define DIRREMOVE_FLAG_CONTENT_ONLY         RT_BIT(2)
    135 /** Mask of valid flags. */
    136 #define DIRREMOVE_FLAG_VALID_MASK           UINT32_C(0x00000003)
    137 
    138 /** @name EXECUTEPROCESSFLAG_XXX Guest process creation flags.
    139  * @note Has to match Main's ProcessCreateFlag_* flags!
    140  */
    141 #define EXECUTEPROCESSFLAG_NONE             UINT32_C(0x0)
    142 #define EXECUTEPROCESSFLAG_WAIT_START       RT_BIT(0)
    143 #define EXECUTEPROCESSFLAG_IGNORE_ORPHANED  RT_BIT(1)
    144 #define EXECUTEPROCESSFLAG_HIDDEN           RT_BIT(2)
    145 #define EXECUTEPROCESSFLAG_NO_PROFILE       RT_BIT(3) /** @todo Rename to EXECUTEPROCESSFLAG_PROFILE in next API change. */
    146 #define EXECUTEPROCESSFLAG_WAIT_STDOUT      RT_BIT(4)
    147 #define EXECUTEPROCESSFLAG_WAIT_STDERR      RT_BIT(5)
    148 #define EXECUTEPROCESSFLAG_EXPAND_ARGUMENTS RT_BIT(6)
    149 #define EXECUTEPROCESSFLAG_UNQUOTED_ARGS    RT_BIT(7)
    150 /** @} */
    151 
    152 /**
    153  * Pipe handle IDs used internally for referencing to
    154  * a certain pipe buffer.
    155  */
    156 #define OUTPUT_HANDLE_ID_STDOUT_DEPRECATED  0 /* Needed for VBox hosts < 4.1.0. */
    157 #define OUTPUT_HANDLE_ID_STDOUT             1
    158 #define OUTPUT_HANDLE_ID_STDERR             2
    159 
    160 /**
    161  * Guest path rename flags.
    162  * Essentially using what IPRT's RTPATHRENAME_FLAGS_
    163  * defines have to offer.
    164  */
    165 /** Do not replace anything. */
    166 #define PATHRENAME_FLAG_NO_REPLACE          UINT32_C(0)
    167 /** This will replace attempt any target which isn't a directory. */
    168 #define PATHRENAME_FLAG_REPLACE             RT_BIT(0)
    169 /** Don't allow symbolic links as part of the path. */
    170 #define PATHRENAME_FLAG_NO_SYMLINKS         RT_BIT(1)
    171 /** Mask of valid flags. */
    172 #define PATHRENAME_FLAG_VALID_MASK          UINT32_C(0x00000002)
    173 
    174 /**
    175  * Defines for guest process array lengths.
    176  */
    177 #define GUESTPROCESS_MAX_CMD_LEN            _1K
    178 #define GUESTPROCESS_MAX_ARGS_LEN           _1K
    179 #define GUESTPROCESS_MAX_ENV_LEN            _64K
    180 #define GUESTPROCESS_MAX_USER_LEN           128
    181 #define GUESTPROCESS_MAX_PASSWORD_LEN       128
    182 #define GUESTPROCESS_MAX_DOMAIN_LEN         256
    183 
    184 /** @name Internal tools built into VBoxService which are used in order to
    185  *        accomplish tasks host<->guest.
    186  * @{
    187  */
    188 #define VBOXSERVICE_TOOL_CAT        "vbox_cat"
    189 #define VBOXSERVICE_TOOL_LS         "vbox_ls"
    190 #define VBOXSERVICE_TOOL_RM         "vbox_rm"
    191 #define VBOXSERVICE_TOOL_MKDIR      "vbox_mkdir"
    192 #define VBOXSERVICE_TOOL_MKTEMP     "vbox_mktemp"
    193 #define VBOXSERVICE_TOOL_STAT       "vbox_stat"
    194 /** @} */
    195 
    196 /**
    197  * Input status, reported by the client.
    198  */
    199 enum eInputStatus
    200 {
    201     /** Input is in an undefined state. */
    202     INPUT_STS_UNDEFINED = 0,
    203     /** Input was written (partially, see cbProcessed). */
    204     INPUT_STS_WRITTEN = 1,
    205     /** Input failed with an error (see flags for rc). */
    206     INPUT_STS_ERROR = 20,
    207     /** Process has abandoned / terminated input handling. */
    208     INPUT_STS_TERMINATED = 21,
    209     /** Too much input data. */
    210     INPUT_STS_OVERFLOW = 30
    211 };
    212 
    213 /**
    21485 * Structure keeping the context of a host callback.
    21586 */
  • trunk/include/VBox/err.h

    r59375 r60622  
    44
    55/*
    6  * Copyright (C) 2006-2015 Oracle Corporation
     6 * Copyright (C) 2006-2016 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    26592659/** A guest control object has changed its overall status. */
    26602660#define VWRN_GSTCTL_OBJECTSTATE_CHANGED             6220
     2661/** Guest process is in a wrong state. */
     2662#define VERR_GSTCTL_PROCESS_WRONG_STATE             (-6221)
     2663/** Started guest process terminated with an exit code <> 0. */
     2664#define VWRN_GSTCTL_PROCESS_EXIT_CODE               6221
    26612665/** @} */
    26622666
  • trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp

    r60583 r60622  
    9191#ifdef VBOX_WITH_VBOXSERVICE_CONTROL
    9292# include "VBoxServiceControl.h"
     93#endif
     94#ifdef VBOX_WITH_VBOXSERVICE_TOOLBOX
     95# include "VBoxServiceToolBox.h"
    9396#endif
    9497
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h

    r59134 r60622  
    55
    66/*
    7  * Copyright (C) 2013-2015 Oracle Corporation
     7 * Copyright (C) 2013-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2424
    2525#include <VBox/VBoxGuestLib.h>
     26#include <VBox/GuestHost/GuestControl.h>
    2627#include <VBox/HostServices/GuestControlSvc.h>
    2728
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp

    r60583 r60622  
    4040#include "VBoxServiceInternal.h"
    4141#include "VBoxServiceControl.h"
     42#include "VBoxServiceToolBox.h"
    4243
    4344using namespace guestControl;
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r60583 r60622  
    200200#endif
    201201
    202 #ifdef VBOX_WITH_VBOXSERVICE_TOOLBOX
    203 extern bool                     VGSvcToolboxMain(int argc, char **argv, RTEXITCODE *prcExit);
    204 #endif
    205 
    206202#ifdef RT_OS_WINDOWS
    207203# ifdef VBOX_WITH_GUEST_PROPS
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp

    r58089 r60622  
    55
    66/*
    7  * Copyright (C) 2012-2015 Oracle Corporation
     7 * Copyright (C) 2012-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4141#include <VBox/VBoxGuestLib.h>
    4242#include <VBox/version.h>
     43
     44#include <VBox/GuestHost/GuestControl.h>
     45
    4346#include "VBoxServiceInternal.h"
     47#include "VBoxServiceToolBox.h"
    4448#include "VBoxServiceUtils.h"
    4549
     50using namespace guestControl;
    4651
    4752/*********************************************************************************************************************************
     
    7883} VBOXSERVICETOOLBOXOUTPUTFLAG;
    7984
     85/*********************************************************************************************************************************
     86*   Prototypes                                                                                                                   *
     87*********************************************************************************************************************************/
     88static RTEXITCODE vgsvcToolboxCat(int argc, char **argv);
     89static RTEXITCODE vgsvcToolboxLs(int argc, char **argv);
     90static RTEXITCODE vgsvcToolboxRm(int argc, char **argv);
     91static RTEXITCODE vgsvcToolboxMkTemp(int argc, char **argv);
     92static RTEXITCODE vgsvcToolboxMkDir(int argc, char **argv);
     93static RTEXITCODE vgsvcToolboxStat(int argc, char **argv);
    8094
    8195/*********************************************************************************************************************************
    8296*   Structures and Typedefs                                                                                                      *
    8397*********************************************************************************************************************************/
    84 /** Pointer to a handler function. */
     98/** Pointer to a tool handler function. */
    8599typedef RTEXITCODE (*PFNHANDLER)(int , char **);
     100
     101/** Definition for a specific toolbox tool. */
     102typedef struct VBOXSERVICETOOLBOXTOOL
     103{
     104    /** Friendly name of the tool. */
     105    const char *pszName;
     106    /** Main handler to be invoked to use the tool. */
     107    RTEXITCODE (*pfnHandler)(int argc, char **argv);
     108    /** Conversion routine to convert the tool's exit code back to an IPRT rc. Optional. */
     109    int        (*pfnExitCodeConvertToRc)(RTEXITCODE rcExit);
     110} VBOXSERVICETOOLBOXTOOL, *PVBOXSERVICETOOLBOXTOOL;
     111
     112static VBOXSERVICETOOLBOXTOOL s_aTools[] =
     113{
     114    { VBOXSERVICE_TOOL_CAT,    vgsvcToolboxCat   , NULL },
     115    { VBOXSERVICE_TOOL_LS,     vgsvcToolboxLs    , NULL },
     116    { VBOXSERVICE_TOOL_RM,     vgsvcToolboxRm    , NULL },
     117    { VBOXSERVICE_TOOL_MKTEMP, vgsvcToolboxMkTemp, NULL },
     118    { VBOXSERVICE_TOOL_MKDIR,  vgsvcToolboxMkDir , NULL },
     119    { VBOXSERVICE_TOOL_STAT,   vgsvcToolboxStat  , NULL }
     120};
    86121
    87122/**
     
    468503            }
    469504
    470             /* If not input files were defined, process stdin. */
     505            /* If no input files were defined, process stdin. */
    471506            if (RTListNodeIsFirst(&inputList, &inputList))
    472507                rc = vgsvcToolboxCatOutput(hInput, hOutput);
     
    478513    vgsvcToolboxPathBufDestroy(&inputList);
    479514
    480     return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
     515    if (RT_FAILURE(rc))
     516    {
     517        switch (rc)
     518        {
     519            case VERR_ACCESS_DENIED:
     520                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_ACCESS_DENIED;
     521
     522            case VERR_FILE_NOT_FOUND:
     523                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_FILE_NOT_FOUND;
     524
     525            case VERR_PATH_NOT_FOUND:
     526                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_PATH_NOT_FOUND;
     527
     528            case VERR_SHARING_VIOLATION:
     529                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_SHARING_VIOLATION;
     530
     531            default:
     532                AssertMsgFailed(("Exit code for %Rrc not implemented\n", rc));
     533                break;
     534        }
     535
     536        return RTEXITCODE_FAILURE;
     537    }
     538
     539    return RTEXITCODE_SUCCESS;
    481540}
    482541
     
    14031462            if (RT_FAILURE(rc2))
    14041463            {
    1405 /** @todo r=bird: You can get a number of other errors here, like access denied. */
    14061464                if (!(fOutputFlags & VBOXSERVICETOOLBOXOUTPUTFLAG_PARSEABLE))
    1407                     RTMsgError("Cannot stat for '%s': No such file or directory (%Rrc)\n", pNodeIt->pszName, rc);
    1408                 rc = VERR_FILE_NOT_FOUND;
    1409                 /* Do not break here -- process every element in the list
    1410                  * and keep failing rc. */
     1465                    RTMsgError("Cannot stat for '%s': %Rrc\n", pNodeIt->pszName, rc2);
    14111466            }
    14121467            else
     
    14161471                                              fOutputFlags,
    14171472                                              &objInfo);
    1418                 if (RT_FAILURE(rc2))
    1419                     rc = rc2;
    14201473            }
     1474
     1475            if (RT_SUCCESS(rc))
     1476                rc = rc2;
     1477            /* Do not break here -- process every element in the list
     1478             * and keep (initial) failing rc. */
    14211479        }
    14221480
     
    14331491
    14341492    vgsvcToolboxPathBufDestroy(&fileList);
    1435     return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
    1436 }
    1437 
    1438 
    1439 
    1440 /**
    1441  * Looks up the handler for the tool give by @a pszTool.
    1442  *
    1443  * @returns Pointer to handler function.  NULL if not found.
     1493
     1494    if (RT_FAILURE(rc))
     1495    {
     1496        switch (rc)
     1497        {
     1498            case VERR_ACCESS_DENIED:
     1499                return (RTEXITCODE)VBOXSERVICETOOLBOX_STAT_EXITCODE_ACCESS_DENIED;
     1500
     1501            case VERR_FILE_NOT_FOUND:
     1502                return (RTEXITCODE)VBOXSERVICETOOLBOX_STAT_EXITCODE_FILE_NOT_FOUND;
     1503
     1504            case VERR_PATH_NOT_FOUND:
     1505                return (RTEXITCODE)VBOXSERVICETOOLBOX_STAT_EXITCODE_PATH_NOT_FOUND;
     1506
     1507            default:
     1508                AssertMsgFailed(("Exit code for %Rrc not implemented\n", rc));
     1509                break;
     1510        }
     1511
     1512        return RTEXITCODE_FAILURE;
     1513    }
     1514
     1515    return RTEXITCODE_SUCCESS;
     1516}
     1517
     1518
     1519/**
     1520 * Looks up the tool definition entry for the tool give by @a pszTool.
     1521 *
     1522 * @returns Pointer to the tool definition.  NULL if not found.
    14441523 * @param   pszTool     The name of the tool.
    14451524 */
    1446 static PFNHANDLER vgsvcToolboxLookUpHandler(const char *pszTool)
    1447 {
    1448     static struct
    1449     {
    1450         const char *pszName;
    1451         RTEXITCODE (*pfnHandler)(int argc, char **argv);
    1452     }
    1453     const s_aTools[] =
    1454     {
    1455         { "cat",    vgsvcToolboxCat    },
    1456         { "ls",     vgsvcToolboxLs     },
    1457         { "rm",     vgsvcToolboxRm     },
    1458         { "mktemp", vgsvcToolboxMkTemp },
    1459         { "mkdir",  vgsvcToolboxMkDir  },
    1460         { "stat",   vgsvcToolboxStat   },
    1461     };
    1462 
    1463     /* Skip optional 'vbox_' prefix. */
    1464     if (   pszTool[0] == 'v'
    1465         && pszTool[1] == 'b'
    1466         && pszTool[2] == 'o'
    1467         && pszTool[3] == 'x'
    1468         && pszTool[4] == '_')
    1469         pszTool += 5;
     1525static PVBOXSERVICETOOLBOXTOOL const vgsvcToolboxLookUp(const char *pszTool)
     1526{
     1527    AssertPtrReturn(pszTool, NULL);
    14701528
    14711529    /* Do a linear search, since we don't have that much stuff in the table. */
    14721530    for (unsigned i = 0; i < RT_ELEMENTS(s_aTools); i++)
    14731531        if (!strcmp(s_aTools[i].pszName, pszTool))
    1474             return s_aTools[i].pfnHandler;
     1532            return &s_aTools[i];
    14751533
    14761534    return NULL;
     1535}
     1536
     1537
     1538/**
     1539 * Converts a tool's exit code back to an IPRT error code.
     1540 *
     1541 * @return  Converted IPRT status code.
     1542 * @param   pszTool                 Name of the toolbox tool to convert exit code for.
     1543 * @param   rcExit                  The tool's exit code to convert.
     1544 */
     1545int VGSvcToolboxExitCodeConvertToRc(const char *pszTool, RTEXITCODE rcExit)
     1546{
     1547    AssertPtrReturn(pszTool, VERR_INVALID_POINTER);
     1548
     1549    PVBOXSERVICETOOLBOXTOOL pTool = vgsvcToolboxLookUp(pszTool);
     1550    if (pTool)
     1551        return pTool->pfnExitCodeConvertToRc(rcExit);
     1552
     1553    AssertMsgFailed(("Tool '%s' not found\n", pszTool));
     1554    return VERR_GENERAL_FAILURE; /* Lookup failed, should not happen. */
    14771555}
    14781556
     
    14941572     */
    14951573    AssertReturn(argc > 0, false);
    1496     const char *pszTool    = RTPathFilename(argv[0]);
    1497     PFNHANDLER  pfnHandler = vgsvcToolboxLookUpHandler(pszTool);
    1498     if (!pfnHandler)
     1574    const char              *pszTool = RTPathFilename(argv[0]);
     1575    PVBOXSERVICETOOLBOXTOOL  pTool   = vgsvcToolboxLookUp(pszTool);
     1576    if (!pTool)
    14991577    {
    15001578        /*
     
    15071585        argv += 2;
    15081586        pszTool = argv[0];
    1509         pfnHandler = vgsvcToolboxLookUpHandler(pszTool);
    1510         if (!pfnHandler)
     1587        pTool = vgsvcToolboxLookUp(pszTool);
     1588        if (!pTool)
    15111589        {
    15121590           *prcExit = RTEXITCODE_SUCCESS;
     
    15281606     */
    15291607    RTMsgSetProgName("VBoxService/%s", pszTool);
    1530     *prcExit = pfnHandler(argc, argv);
     1608    AssertPtr(pTool);
     1609    *prcExit = pTool->pfnHandler(argc, argv);
    15311610
    15321611    return true;
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r59747 r60622  
    55
    66/*
    7  * Copyright (C) 2011-2015 Oracle Corporation
     7 * Copyright (C) 2011-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3838
    3939#ifdef VBOX_WITH_GUEST_CONTROL
     40# include <VBox/GuestHost/GuestControl.h>
    4041# include <VBox/HostServices/GuestControlSvc.h>
    4142using namespace guestControl;
     
    702703    GuestProcessStartupInfo(void)
    703704        : mFlags(ProcessCreateFlag_None),
    704           mTimeoutMS(30 * 1000 /* 30s timeout by default */),
     705          mTimeoutMS(UINT32_MAX /* No timeout by default */),
    705706          mPriority(ProcessPriority_Default) { }
    706707
     
    715716    /** Process creation flags. */
    716717    uint32_t                    mFlags;
     718    /** Timeout (in ms) the process is allowed to run.
     719     *  Specify UINT32_MAX if no timeout (unlimited run time) is given. */
    717720    ULONG                       mTimeoutMS;
    718721    /** Process priority. */
  • trunk/src/VBox/Main/include/GuestDirectoryImpl.h

    r51556 r60622  
    55
    66/*
    7  * Copyright (C) 2012-2014 Oracle Corporation
     7 * Copyright (C) 2012-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    7373        /** The directory's ID. */
    7474        uint32_t                   mID;
     75        /** The process tool instance to use. */
    7576        GuestProcessTool           mProcessTool;
    7677    } mData;
  • trunk/src/VBox/Main/include/GuestProcessImpl.h

    r58521 r60622  
    55
    66/*
    7  * Copyright (C) 2012-2014 Oracle Corporation
     7 * Copyright (C) 2012-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    184184
    185185/**
    186  * Internal class for handling a VBoxService tool ("vbox_ls", vbox_stat", ...).
     186 * Structure for keeping a VBoxService toolbox tool's error info around.
     187 */
     188struct GuestProcessToolErrorInfo
     189{
     190    /** Return code from the guest side for executing the process tool. */
     191    int  guestRc;
     192    /** The process tool's returned exit code. */
     193    LONG lExitCode;
     194};
     195
     196/**
     197 * Internal class for handling the BusyBox-like tools built into VBoxService
     198 * on the guest side. It's also called the VBoxService Toolbox (tm).
     199 *
     200 * Those initially were necessary to guarantee execution of commands (like "ls", "cat")
     201 * under the behalf of a certain guest user.
     202 *
     203 * This class essentially helps to wrap all the gory details like process creation,
     204 * information extraction and maintaining the overall status.
    187205 */
    188206class GuestProcessTool
     
    198216    int Init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, bool fAsync, int *pGuestRc);
    199217
     218    int i_getCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock);
     219
     220    int i_getRc(void) const;
     221
    200222    GuestProcessStream &i_getStdOut(void) { return mStdOut; }
    201223
     
    206228    int i_waitEx(uint32_t fFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc);
    207229
    208     int i_getCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock);
    209 
    210230    bool i_isRunning(void);
    211231
     232    int i_terminatedOk(LONG *plExitCode = NULL);
     233
     234    int i_terminate(uint32_t uTimeoutMS, int *pGuestRc);
     235
     236public:
     237
    212238    static int i_run(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, int *pGuestRc);
     239
     240    static int i_runErrorInfo(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, GuestProcessToolErrorInfo &errorInfo);
    213241
    214242    static int i_runEx(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
    215243                       GuestCtrlStreamObjects *pStrmOutObjects, uint32_t cStrmOutObjects, int *pGuestRc);
    216244
    217     int i_terminatedOk(LONG *pExitCode);
    218 
    219     int i_terminate(uint32_t uTimeoutMS, int *pGuestRc);
     245    static int i_runExErrorInfo(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
     246                                GuestCtrlStreamObjects *pStrmOutObjects, uint32_t cStrmOutObjects, GuestProcessToolErrorInfo &errorInfo);
     247
     248    static int i_exitCodeToRc(const GuestProcessStartupInfo &startupInfo, LONG lExitCode);
     249
     250    static int i_exitCodeToRc(const char *pszTool, LONG lExitCode);
    220251
    221252protected:
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r58521 r60622  
    55
    66/*
    7  * Copyright (C) 2006-2014 Oracle Corporation
     7 * Copyright (C) 2006-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    600600                hr = E_OUTOFMEMORY;
    601601            }
    602             catch(HRESULT eHR)
     602            catch(...)
    603603            {
    604                 LogFlowThisFunc(("Exception was caught in the function \n"));
     604                LogFlowThisFunc(("Exception was caught in the function\n"));
    605605            }
    606606        }
    607607    }
     608
     609    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
    608610    return hr;
    609611#endif /* VBOX_WITH_GUEST_CONTROL */
  • trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp

    r57358 r60622  
    55
    66/*
    7  * Copyright (C) 2012-2015 Oracle Corporation
     7 * Copyright (C) 2012-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    322322        && !mData.mProcessTool.i_isRunning())
    323323    {
    324         rc = mData.mProcessTool.i_terminatedOk(NULL /* Exit code */);
    325         if (rc == VERR_NOT_EQUAL)
    326             rc = VERR_ACCESS_DENIED;
     324        rc = mData.mProcessTool.i_terminatedOk();
    327325    }
    328326
     
    373371                break;
    374372
    375             case VERR_ACCESS_DENIED:
    376                 hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Unable to read / access denied"),
    377                               mData.mOpenInfo.mPath.c_str());
     373            case VWRN_GSTCTL_PROCESS_EXIT_CODE:
     374                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: %Rrc"),
     375                              mData.mOpenInfo.mPath.c_str(), mData.mProcessTool.i_getRc());
    378376                break;
    379377
  • trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp

    r58552 r60622  
    55
    66/*
    7  * Copyright (C) 2012-2015 Oracle Corporation
     7 * Copyright (C) 2012-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    543543            break;
    544544
    545         case VERR_NOT_EQUAL: /** @todo Imprecise to the user; can mean anything and all. */
    546             strError += Utf8StrFmt(tr("Unable to retrieve requested information"));
    547             break;
    548 
    549545        case VERR_NOT_FOUND:
    550546            strError += Utf8StrFmt(tr("The guest execution service is not ready (yet)"));
     
    19501946    int vrc = pSession->i_processCreateExInternal(mStartupInfo, pProcess);
    19511947    if (RT_SUCCESS(vrc))
     1948    {
     1949        int guestRc;
    19521950        vrc = fAsync
    19531951            ? pProcess->i_startProcessAsync()
    1954             : pProcess->i_startProcess(30 * 1000 /* 30s timeout */, pGuestRc);
    1955 
    1956     if (   RT_SUCCESS(vrc)
    1957         && !fAsync
    1958         && (   pGuestRc
    1959             && RT_FAILURE(*pGuestRc)
     1952            : pProcess->i_startProcess(30 * 1000 /* 30s timeout */, &guestRc);
     1953
     1954        if (   RT_SUCCESS(vrc)
     1955            && !fAsync
     1956            && RT_FAILURE(guestRc)
    19601957           )
    1961        )
    1962     {
    1963         vrc = VERR_GSTCTL_GUEST_ERROR;
     1958        {
     1959            if (pGuestRc)
     1960                *pGuestRc = guestRc;
     1961            vrc = VERR_GSTCTL_GUEST_ERROR;
     1962        }
    19641963    }
    19651964
     
    19931992}
    19941993
     1994int GuestProcessTool::i_getRc(void) const
     1995{
     1996    LONG exitCode;
     1997    HRESULT hr = pProcess->COMGETTER(ExitCode(&exitCode));
     1998    Assert(SUCCEEDED(hr));
     1999
     2000    return GuestProcessTool::i_exitCodeToRc(mStartupInfo, exitCode);
     2001}
     2002
    19952003bool GuestProcessTool::i_isRunning(void)
    19962004{
     
    20122020
    20132021/* static */
    2014 int GuestProcessTool::i_run(      GuestSession            *pGuestSession,
    2015                             const GuestProcessStartupInfo &startupInfo,
    2016                             int                           *pGuestRc)
    2017 {
    2018     return i_runEx(pGuestSession, startupInfo,
    2019                    NULL /* pStrmOutObjects */, 0 /* cStrmOutObjects */,
    2020                    pGuestRc);
     2022int GuestProcessTool::i_run(      GuestSession              *pGuestSession,
     2023                            const GuestProcessStartupInfo   &startupInfo,
     2024                                  int                       *pGuestRc /* = NULL */)
     2025{
     2026    int guestRc;
     2027
     2028    GuestProcessToolErrorInfo errorInfo;
     2029    int vrc = i_runErrorInfo(pGuestSession, startupInfo, errorInfo);
     2030    if (RT_SUCCESS(vrc))
     2031    {
     2032        if (errorInfo.guestRc == VWRN_GSTCTL_PROCESS_EXIT_CODE)
     2033        {
     2034            guestRc = GuestProcessTool::i_exitCodeToRc(startupInfo, errorInfo.lExitCode);
     2035        }
     2036        else
     2037            guestRc = errorInfo.guestRc;
     2038
     2039        if (pGuestRc)
     2040            *pGuestRc = guestRc;
     2041    }
     2042
     2043    return vrc;
     2044}
     2045
     2046/* static */
     2047int GuestProcessTool::i_runErrorInfo(      GuestSession              *pGuestSession,
     2048                                     const GuestProcessStartupInfo   &startupInfo,
     2049                                           GuestProcessToolErrorInfo &errorInfo)
     2050{
     2051    return i_runExErrorInfo(pGuestSession, startupInfo,
     2052                            NULL /* pStrmOutObjects */, 0 /* cStrmOutObjects */,
     2053                            errorInfo);
     2054}
     2055
     2056/* static */
     2057int GuestProcessTool::i_runEx(      GuestSession              *pGuestSession,
     2058                              const GuestProcessStartupInfo   &startupInfo,
     2059                                    GuestCtrlStreamObjects    *pStrmOutObjects,
     2060                                    uint32_t                   cStrmOutObjects,
     2061                                    int                       *pGuestRc /* = NULL */)
     2062{
     2063    int guestRc;
     2064
     2065    GuestProcessToolErrorInfo errorInfo;
     2066    int vrc = GuestProcessTool::i_runExErrorInfo(pGuestSession, startupInfo, pStrmOutObjects, cStrmOutObjects, errorInfo);
     2067    if (RT_SUCCESS(vrc))
     2068    {
     2069        if (errorInfo.guestRc == VWRN_GSTCTL_PROCESS_EXIT_CODE)
     2070        {
     2071            guestRc = GuestProcessTool::i_exitCodeToRc(startupInfo, errorInfo.lExitCode);
     2072        }
     2073        else
     2074            guestRc = errorInfo.guestRc;
     2075
     2076        if (pGuestRc)
     2077            *pGuestRc = guestRc;
     2078    }
     2079
     2080    return vrc;
    20212081}
    20222082
     
    20302090 */
    20312091/* static */
    2032 int GuestProcessTool::i_runEx(      GuestSession            *pGuestSession,
    2033                               const GuestProcessStartupInfo &startupInfo,
    2034                                     GuestCtrlStreamObjects  *pStrmOutObjects,
    2035                                     uint32_t                 cStrmOutObjects,
    2036                                     int                     *pGuestRc)
     2092int GuestProcessTool::i_runExErrorInfo(      GuestSession              *pGuestSession,
     2093                                       const GuestProcessStartupInfo  &startupInfo,
     2094                                             GuestCtrlStreamObjects    *pStrmOutObjects,
     2095                                             uint32_t                   cStrmOutObjects,
     2096                                             GuestProcessToolErrorInfo &errorInfo)
    20372097{
    20382098    GuestProcessTool procTool;
    2039     int guestRc;
    2040     int vrc = procTool.Init(pGuestSession, startupInfo, false /* Async */, &guestRc);
     2099    int vrc = procTool.Init(pGuestSession, startupInfo, false /* Async */, &errorInfo.guestRc);
    20412100    if (RT_SUCCESS(vrc))
    20422101    {
     
    20482107                vrc = procTool.i_waitEx(  pStrmOutObjects
    20492108                                        ? GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK
    2050                                         : GUESTPROCESSTOOL_FLAG_NONE, &strmBlk, &guestRc);
     2109                                        : GUESTPROCESSTOOL_FLAG_NONE, &strmBlk, &errorInfo.guestRc);
    20512110                if (pStrmOutObjects)
    20522111                    pStrmOutObjects->push_back(strmBlk);
     
    20622121    {
    20632122        /* Make sure the process runs until completion. */
    2064         vrc = procTool.i_wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
     2123        vrc = procTool.i_wait(GUESTPROCESSTOOL_FLAG_NONE, &errorInfo.guestRc);
    20652124        if (RT_SUCCESS(vrc))
    2066         {
    2067             guestRc = procTool.i_terminatedOk(NULL /* Exit code */);
    2068             if (RT_FAILURE(guestRc))
    2069                 vrc = VERR_GSTCTL_GUEST_ERROR;
    2070         }
    2071     }
    2072 
    2073     if (pGuestRc)
    2074         *pGuestRc = guestRc;
    2075 
    2076     LogFlowFunc(("Returned rc=%Rrc, guestRc=%Rrc\n", vrc, guestRc));
     2125            errorInfo.guestRc = procTool.i_terminatedOk(&errorInfo.lExitCode);
     2126    }
     2127
     2128    LogFlowFunc(("Returned rc=%Rrc, guestRc=%Rrc, exitCode=%ld\n", vrc, errorInfo.guestRc, errorInfo.lExitCode));
    20772129    return vrc;
    20782130}
    20792131
    2080 int GuestProcessTool::i_terminatedOk(LONG *pExitCode)
     2132/**
     2133 * Reports if the tool has been run correctly.
     2134 *
     2135 * @return  Will return VWRN_GSTCTL_PROCESS_EXIT_CODE if the tool process returned an exit code <> 0,
     2136 *          VERR_GSTCTL_PROCESS_WRONG_STATE if the tool process is in a wrong state (e.g. still running),
     2137 *          or VINF_SUCCESS otherwise.
     2138 *
     2139 * @param   plExitCode      Exit code of the tool. Optional.
     2140 */
     2141int GuestProcessTool::i_terminatedOk(LONG *plExitCode /* = NULL */)
    20812142{
    20822143    Assert(!pProcess.isNull());
     
    20862147    if (!i_isRunning())
    20872148    {
    2088         LONG exitCode;
    2089         HRESULT hr = pProcess->COMGETTER(ExitCode(&exitCode));
     2149        LONG lExitCode;
     2150        HRESULT hr = pProcess->COMGETTER(ExitCode(&lExitCode));
    20902151        Assert(SUCCEEDED(hr));
    20912152
    2092         if (pExitCode)
    2093             *pExitCode = exitCode;
    2094 
    2095         vrc = (exitCode != 0)
    2096               /** @todo Special guest control rc needed! */
    2097             ? VERR_NOT_EQUAL : VINF_SUCCESS;
     2153        if (plExitCode)
     2154            *plExitCode = lExitCode;
     2155
     2156        vrc = (lExitCode != 0)
     2157            ? VWRN_GSTCTL_PROCESS_EXIT_CODE : VINF_SUCCESS;
    20982158    }
    20992159    else
    2100         vrc = VERR_INVALID_STATE; /** @todo Special guest control rc needed! */
     2160        vrc = VERR_GSTCTL_PROCESS_WRONG_STATE;
    21012161
    21022162    LogFlowFuncLeaveRC(vrc);
     
    23152375}
    23162376
     2377/**
     2378 * Converts a toolbox tool's exit code to an IPRT error code.
     2379 *
     2380 * @return  int             Returned IPRT error for the particular tool.
     2381 * @param   startupInfo     Startup info of the toolbox tool to lookup error code for.
     2382 * @param   lExitCode       The toolbox tool's exit code to lookup IPRT error for.
     2383 */
     2384/* static */
     2385int GuestProcessTool::i_exitCodeToRc(const GuestProcessStartupInfo &startupInfo, LONG lExitCode)
     2386{
     2387    if (startupInfo.mArguments.size() == 0)
     2388    {
     2389        AssertFailed();
     2390        return VERR_GENERAL_FAILURE; /* Should not happen. */
     2391    }
     2392
     2393    return i_exitCodeToRc(startupInfo.mArguments[0].c_str(), lExitCode);
     2394}
     2395
     2396/**
     2397 * Converts a toolbox tool's exit code to an IPRT error code.
     2398 *
     2399 * @return  int             Returned IPRT error for the particular tool.
     2400 * @param   pszTool         Name of toolbox tool to lookup error code for.
     2401 * @param   rcExit          The toolbox tool's exit code to lookup IPRT error for.
     2402 */
     2403/* static */
     2404int GuestProcessTool::i_exitCodeToRc(const char *pszTool, LONG lExitCode)
     2405{
     2406    AssertPtrReturn(pszTool, VERR_INVALID_POINTER);
     2407
     2408    LogFlowFunc(("%s: %ld\n", pszTool, lExitCode));
     2409
     2410    if (lExitCode == 0) /* No error? Bail out early. */
     2411        return VINF_SUCCESS;
     2412
     2413    if (!RTStrICmp(pszTool, VBOXSERVICE_TOOL_CAT))
     2414    {
     2415        switch (lExitCode)
     2416        {
     2417            case VBOXSERVICETOOLBOX_CAT_EXITCODE_ACCESS_DENIED:     return VERR_ACCESS_DENIED;
     2418            case VBOXSERVICETOOLBOX_CAT_EXITCODE_FILE_NOT_FOUND:    return VERR_FILE_NOT_FOUND;
     2419            case VBOXSERVICETOOLBOX_CAT_EXITCODE_PATH_NOT_FOUND:    return VERR_PATH_NOT_FOUND;
     2420            case VBOXSERVICETOOLBOX_CAT_EXITCODE_SHARING_VIOLATION: return VERR_SHARING_VIOLATION;
     2421            default:
     2422                break;
     2423        }
     2424    }
     2425    else if (!RTStrICmp(pszTool, VBOXSERVICE_TOOL_STAT))
     2426    {
     2427        switch (lExitCode)
     2428        {
     2429            case VBOXSERVICETOOLBOX_STAT_EXITCODE_ACCESS_DENIED:    return VERR_ACCESS_DENIED;
     2430            case VBOXSERVICETOOLBOX_STAT_EXITCODE_FILE_NOT_FOUND:   return VERR_FILE_NOT_FOUND;
     2431            case VBOXSERVICETOOLBOX_STAT_EXITCODE_PATH_NOT_FOUND:   return VERR_PATH_NOT_FOUND;
     2432            default:
     2433                break;
     2434        }
     2435    }
     2436
     2437    AssertMsgFailed(("Error code %ld for tool '%s' not handled\n", lExitCode, pszTool));
     2438    return VERR_GENERAL_FAILURE;
     2439}
     2440
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r60494 r60622  
    589589int GuestSession::i_closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGuestRc)
    590590{
     591    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
     592
    591593    LogFlowThisFunc(("uFlags=%x, uTimeoutMS=%RU32\n", uFlags, uTimeoutMS));
    592594
     
    651653
    652654int GuestSession::i_directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode,
    653                                           uint32_t uFlags, int *pGuestRc)
    654 {
    655     LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
    656                      strPath.c_str(), uMode, uFlags));
     655                                            uint32_t uFlags, int *pGuestRc)
     656{
     657    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
     658
     659    LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n", strPath.c_str(), uMode, uFlags));
    657660
    658661    int vrc = VINF_SUCCESS;
     
    717720                                               GuestFsObjData &objData, int *pGuestRc)
    718721{
    719     LogFlowThisFunc(("strPath=%s fFollowSymlinks=%RTbool\n", strPath.c_str(), fFollowSymlinks));
     722    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
     723
     724    LogFlowThisFunc(("strPath=%s, fFollowSymlinks=%RTbool\n", strPath.c_str(), fFollowSymlinks));
    720725
    721726    int vrc = i_fsQueryInfoInternal(strPath, fFollowSymlinks, objData, pGuestRc);
     
    732737int GuestSession::i_directoryRemoveFromList(GuestDirectory *pDirectory)
    733738{
     739    AssertPtrReturn(pDirectory, VERR_INVALID_POINTER);
     740
    734741    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    735742
     
    773780{
    774781    AssertReturn(!(uFlags & ~DIRREMOVE_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
     782    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
    775783
    776784    LogFlowThisFunc(("strPath=%s, uFlags=0x%x\n", strPath.c_str(), uFlags));
     
    812820                                             bool fDirectory, Utf8Str &strName, int *pGuestRc)
    813821{
     822    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
     823
    814824    LogFlowThisFunc(("strTemplate=%s, strPath=%s, fDirectory=%RTbool\n",
    815825                     strTemplate.c_str(), strPath.c_str(), fDirectory));
     
    878888                                          ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc)
    879889{
     890    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
     891
    880892    LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n",
    881893                     openInfo.mPath.c_str(), openInfo.mFilter.c_str(), openInfo.mFlags));
     
    14291441        *pGuestRc = guestRc;
    14301442
    1431     LogFlowThisFunc(("Returning rc=%Rrc, guestRc=%Rrc\n",
    1432                      vrc, guestRc));
     1443    LogFlowThisFunc(("Returning rc=%Rrc, guestRc=%Rrc\n", vrc, guestRc));
    14331444    return vrc;
    14341445}
     
    14821493        case VERR_MAX_PROCS_REACHED:
    14831494            strError += Utf8StrFmt(tr("Maximum number of concurrent guest processes has been reached"));
    1484             break;
    1485 
    1486         case VERR_NOT_EQUAL: /** @todo Imprecise to the user; can mean anything and all. */
    1487             strError += Utf8StrFmt(tr("Unable to retrieve requested information"));
    14881495            break;
    14891496
     
    19351942    }
    19361943
    1937     /* Adjust timeout. If set to 0, we define
    1938      * an infinite timeout. */
     1944    /* Adjust timeout.
     1945     * If set to 0, we define an infinite timeout (unlimited process run time). */
    19391946    if (procInfo.mTimeoutMS == 0)
    19401947        procInfo.mTimeoutMS = UINT32_MAX;
     
    26502657        {
    26512658            case VERR_GSTCTL_GUEST_ERROR:
    2652                 /** @todo Handle VERR_NOT_EQUAL (meaning process exit code <> 0). */
    2653                 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Could not create directory"));
     2659                hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: %s",
     2660                                                    GuestDirectory::i_guestErrorToString(guestRc).c_str()));
    26542661                break;
    26552662
  • trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp

    r60494 r60622  
    297297    int rc;
    298298
     299    RTMSINTERVAL msTimeout = 30 * 1000; /** @todo 30s timeout for all actions. Make this configurable? */
     300
    299301    RTFILE fileLocal;
    300302    PRTFILE pFile = &fileLocal;
     
    338340    }
    339341
     342    /*
     343     * Query information about our destination first.
     344     */
     345    int guestRc;
     346    if (RT_SUCCESS(rc))
     347    {
     348        GuestFsObjData objData;
     349        rc = pSession->i_directoryQueryInfoInternal(mDest, true /* fFollowSymlinks */, objData, &guestRc);
     350        if (RT_SUCCESS(rc))
     351        {
     352            mDest = Utf8StrFmt("%s/%s", mDest.c_str(), RTPathFilename(mSource.c_str()));
     353        }
     354        else if (rc == VERR_NOT_A_DIRECTORY)
     355        {
     356            rc = VINF_SUCCESS;
     357        }
     358    }
     359
     360    /** @todo Implement sparse file support? */
     361
     362    /*
     363     * Start the actual copying process by cat'ing the source file to the
     364     * destination file on the guest.
     365     */
    340366    GuestProcessStartupInfo procInfo;
    341367    procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_CAT);
     
    347373
    348374    /* Startup process. */
    349     ComObjPtr<GuestProcess> pProcess; int guestRc;
     375    ComObjPtr<GuestProcess> pProcess;
    350376    if (RT_SUCCESS(rc))
    351377        rc = pSession->i_processCreateExInternal(procInfo, pProcess);
     
    353379    {
    354380        Assert(!pProcess.isNull());
    355         rc = pProcess->i_startProcess(30 * 1000 /* 30s timeout */,
    356                                       &guestRc);
     381        rc = pProcess->i_startProcess(msTimeout, &guestRc);
    357382    }
    358383
     
    370395                                    Utf8StrFmt(GuestSession::tr(
    371396                                    "Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),
    372                                                mSource.c_str(), rc));
     397                                    mSource.c_str(), rc));
    373398                break;
    374399        }
     
    386411        for (;;)
    387412        {
    388             rc = pProcess->i_waitFor(ProcessWaitForFlag_StdIn,
    389                                      30 * 1000 /* Timeout */, waitRes, &guestRc);
     413            rc = pProcess->i_waitFor(ProcessWaitForFlag_StdIn, msTimeout, waitRes, &guestRc);
    390414            if (   RT_FAILURE(rc)
    391415                || (   waitRes != ProcessWaitResult_StdIn
     
    418442                    {
    419443                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    420                                             Utf8StrFmt(GuestSession::tr("Could not read from file \"%s\" (%Rrc)"),
     444                                            Utf8StrFmt(GuestSession::tr("Could not read from host file \"%s\" (%Rrc)"),
    421445                                                       mSource.c_str(), rc));
    422446                        break;
     
    426450                {
    427451                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    428                                         Utf8StrFmt(GuestSession::tr("Seeking file \"%s\" to offset %RU64 failed: %Rrc"),
     452                                        Utf8StrFmt(GuestSession::tr("Seeking host file \"%s\" to offset %RU64 failed: %Rrc"),
    429453                                                   mSource.c_str(), cbWrittenTotal, rc));
    430454                    break;
     
    452476            rc = pProcess->i_writeData(0 /* StdIn */, fFlags,
    453477                                       byBuf, cbRead,
    454                                        30 * 1000 /* Timeout */, &cbWritten, &guestRc);
     478                                       msTimeout, &cbWritten, &guestRc);
    455479            if (RT_FAILURE(rc))
    456480            {
     
    464488                    default:
    465489                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    466                                             Utf8StrFmt(GuestSession::tr("Writing to file \"%s\" (offset %RU64) failed: %Rrc"),
     490                                            Utf8StrFmt(GuestSession::tr("Writing to guest file \"%s\" (offset %RU64) failed: %Rrc"),
    467491                                            mDest.c_str(), cbWrittenTotal, rc));
    468492                        break;
     
    503527                         rc, cbToRead, cbWrittenTotal, mSourceSize));
    504528
     529        /*
     530         * Wait on termination of guest process until it completed all operations.
     531         */
    505532        if (   !fCanceled
    506533            || RT_SUCCESS(rc))
    507534        {
     535            rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate, msTimeout, waitRes, &guestRc);
     536            if (   RT_FAILURE(rc)
     537                || waitRes != ProcessWaitResult_Terminate)
     538            {
     539                if (RT_FAILURE(rc))
     540                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     541                                        Utf8StrFmt(
     542                                        GuestSession::tr("Waiting on termination for copying file \"%s\" to guest failed: %Rrc"),
     543                                        mSource.c_str(), rc));
     544                else
     545                {
     546                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     547                                        Utf8StrFmt(GuestSession::tr(
     548                                                   "Waiting on termination for copying file \"%s\" to guest failed with wait result %ld"),
     549                                                   mSource.c_str(), waitRes));
     550                    rc = VERR_GENERAL_FAILURE; /* Fudge. */
     551                }
     552            }
     553        }
     554
     555        if (RT_SUCCESS(rc))
     556        {
     557            /*
     558             * Newer VBoxService toolbox versions report what went wrong via exit code.
     559             * So handle this first.
     560             */
     561            ProcessStatus_T procStatus;
     562            LONG exitCode;
     563            if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
     564                    && procStatus != ProcessStatus_TerminatedNormally)
     565                || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
     566                    && exitCode != 0)
     567               )
     568            {
     569                LogFlowThisFunc(("procStatus=%ld, exitCode=%ld\n", procStatus, exitCode));
     570                rc = GuestProcessTool::i_exitCodeToRc(procInfo, exitCode);
     571                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     572                                    Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to guest failed: %Rrc"),
     573                                               mSource.c_str(), rc));
     574            }
    508575            /*
    509576             * Even if we succeeded until here make sure to check whether we really transfered
    510577             * everything.
    511578             */
    512             if (   mSourceSize > 0
    513                 && cbWrittenTotal == 0)
     579            else if (   mSourceSize > 0
     580                     && cbWrittenTotal == 0)
    514581            {
    515582                /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
    516583                 * to the destination -> access denied. */
    517584                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    518                                     Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
     585                                    Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to guest \"%s\""),
    519586                                               mSource.c_str(), mDest.c_str()));
    520                 rc = VERR_GENERAL_FAILURE; /* Fudge. */
     587                rc = VERR_ACCESS_DENIED;
    521588            }
    522589            else if (cbWrittenTotal < mSourceSize)
     
    524591                /* If we did not copy all let the user know. */
    525592                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    526                                     Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"),
     593                                    Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to guest failed (%RU64/%RU64 bytes transfered)"),
    527594                                               mSource.c_str(), cbWrittenTotal, mSourceSize));
    528                 rc = VERR_GENERAL_FAILURE; /* Fudge. */
    529             }
    530             else
    531             {
    532                 rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate,
    533                                          30 * 1000 /* Timeout */, waitRes, &guestRc);
    534                 if (   RT_FAILURE(rc)
    535                     || waitRes != ProcessWaitResult_Terminate)
    536                 {
    537                     if (RT_FAILURE(rc))
    538                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    539                                             Utf8StrFmt(
    540                                             GuestSession::tr("Waiting on termination for copying file \"%s\" failed: %Rrc"),
    541                                                        mSource.c_str(), rc));
    542                     else
    543                     {
    544                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    545                                             Utf8StrFmt(GuestSession::tr(
    546                                             "Waiting on termination for copying file \"%s\" failed with wait result %ld"),
    547                                                        mSource.c_str(), waitRes));
    548                         rc = VERR_GENERAL_FAILURE; /* Fudge. */
    549                     }
    550                 }
    551 
    552                 if (RT_SUCCESS(rc))
    553                 {
    554                     ProcessStatus_T procStatus;
    555                     LONG exitCode;
    556                     if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
    557                             && procStatus != ProcessStatus_TerminatedNormally)
    558                         || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
    559                             && exitCode != 0)
    560                        )
    561                     {
    562                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    563                                             Utf8StrFmt(GuestSession::tr(
    564                                             "Copying file \"%s\" failed with status %ld, exit code %ld"),
    565                                                        mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
    566                         rc = VERR_GENERAL_FAILURE; /* Fudge. */
    567                     }
    568                 }
    569 
    570 
    571                 if (RT_SUCCESS(rc))
    572                     rc = setProgressSuccess();
    573             }
     595                rc = VERR_INTERRUPTED;
     596            }
     597
     598            if (RT_SUCCESS(rc))
     599                rc = setProgressSuccess();
    574600        }
    575601    } /* processCreateExInteral */
     
    632658    AutoCaller autoCaller(pSession);
    633659    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     660
     661    RTMSINTERVAL msTimeout = 30 * 1000; /** @todo 30s timeout for all actions. Make this configurable? */
    634662
    635663    /*
     
    651679        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    652680                            Utf8StrFmt(GuestSession::tr("Object \"%s\" on the guest is not a file"), mSource.c_str()));
    653         rc = VERR_GENERAL_FAILURE; /* Fudge. */
     681        rc = VERR_NOT_A_FILE;
    654682    }
    655683
     
    662690        {
    663691            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    664                                 Utf8StrFmt(GuestSession::tr("Error opening destination file \"%s\": %Rrc"),
     692                                Utf8StrFmt(GuestSession::tr("Opening/creating destination file on host \"%s\" failed: %Rrc"),
    665693                                           mDest.c_str(), rc));
    666694        }
     
    681709            rc = pSession->i_processCreateExInternal(procInfo, pProcess);
    682710            if (RT_SUCCESS(rc))
    683                 rc = pProcess->i_startProcess(30 * 1000 /* 30s timeout */,
    684                                               &guestRc);
     711                rc = pProcess->i_startProcess(msTimeout, &guestRc);
    685712            if (RT_FAILURE(rc))
    686713            {
     
    688715                {
    689716                    case VERR_GSTCTL_GUEST_ERROR:
    690                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    691                                             GuestProcess::i_guestErrorToString(guestRc));
     717                        setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(guestRc));
    692718                        break;
    693719
     
    696722                                            Utf8StrFmt(GuestSession::tr(
    697723                                           "Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),
    698                                                        mSource.c_str(), rc));
     724                                           mSource.c_str(), rc));
    699725                        break;
    700726                }
     
    711737                for (;;)
    712738                {
    713                     rc = pProcess->i_waitFor(ProcessWaitForFlag_StdOut,
    714                                              30 * 1000 /* Timeout */, waitRes, &guestRc);
     739                    rc = pProcess->i_waitFor(ProcessWaitForFlag_StdOut, msTimeout, waitRes, &guestRc);
    715740                    if (RT_FAILURE(rc))
    716741                    {
     
    742767                        uint32_t cbRead = 0; /* readData can return with VWRN_GSTCTL_OBJECTSTATE_CHANGED. */
    743768                        rc = pProcess->i_readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
    744                                                   30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
     769                                                  msTimeout, byBuf, sizeof(byBuf),
    745770                                                  &cbRead, &guestRc);
    746771                        if (RT_FAILURE(rc))
     
    755780                                default:
    756781                                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    757                                                         Utf8StrFmt(GuestSession::tr("Reading from file \"%s\" (offset %RU64) failed: %Rrc"),
     782                                                        Utf8StrFmt(GuestSession::tr("Reading from guest file \"%s\" (offset %RU64) failed: %Rrc"),
    758783                                                                   mSource.c_str(), cbWrittenTotal, rc));
    759784                                    break;
     
    769794                            {
    770795                                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    771                                                     Utf8StrFmt(GuestSession::tr("Error writing to file \"%s\" (%RU64 bytes left): %Rrc"),
     796                                                    Utf8StrFmt(GuestSession::tr("Writing to host file \"%s\" (%RU64 bytes left) failed: %Rrc"),
    772797                                                                mDest.c_str(), cbToRead, rc));
    773798                                break;
     
    802827                                 rc, guestRc, waitRes, cbWrittenTotal, objData.mObjectSize, cbToRead));
    803828
     829                /*
     830                 * Wait on termination of guest process until it completed all operations.
     831                 */
    804832                if (   !fCanceled
    805833                    || RT_SUCCESS(rc))
    806834                {
     835                    rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate, msTimeout, waitRes, &guestRc);
     836                    if (   RT_FAILURE(rc)
     837                        || waitRes != ProcessWaitResult_Terminate)
     838                    {
     839                        if (RT_FAILURE(rc))
     840                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     841                                                Utf8StrFmt(
     842                                                GuestSession::tr("Waiting on termination for copying file \"%s\" from guest failed: %Rrc"),
     843                                                mSource.c_str(), rc));
     844                        else
     845                        {
     846                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     847                                                Utf8StrFmt(GuestSession::tr(
     848                                                           "Waiting on termination for copying file \"%s\" from guest failed with wait result %ld"),
     849                                                           mSource.c_str(), waitRes));
     850                            rc = VERR_GENERAL_FAILURE; /* Fudge. */
     851                        }
     852                    }
     853                }
     854
     855                if (RT_SUCCESS(rc))
     856                {
     857                    ProcessStatus_T procStatus;
     858                    LONG exitCode;
     859                    if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
     860                            && procStatus != ProcessStatus_TerminatedNormally)
     861                        || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
     862                            && exitCode != 0)
     863                       )
     864                    {
     865                        LogFlowThisFunc(("procStatus=%ld, exitCode=%ld\n", procStatus, exitCode));
     866                        rc = GuestProcessTool::i_exitCodeToRc(procInfo, exitCode);
     867                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     868                                            Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to host failed: %Rrc"),
     869                                                       mSource.c_str(), rc));
     870                    }
    807871                    /*
    808872                     * Even if we succeeded until here make sure to check whether we really transfered
    809873                     * everything.
    810874                     */
    811                     if (   objData.mObjectSize > 0
    812                         && cbWrittenTotal == 0)
     875                    else if (   objData.mObjectSize > 0
     876                             && cbWrittenTotal == 0)
    813877                    {
    814878                        /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
    815879                         * to the destination -> access denied. */
    816880                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    817                                             Utf8StrFmt(GuestSession::tr("Unable to write \"%s\" to \"%s\": Access denied"),
    818                                             mSource.c_str(), mDest.c_str()));
    819                         rc = VERR_GENERAL_FAILURE; /* Fudge. */
     881                                            Utf8StrFmt(GuestSession::tr("Writing guest file \"%s\" to host to \"%s\" failed: Access denied"),
     882                                                       mSource.c_str(), mDest.c_str()));
     883                        rc = VERR_ACCESS_DENIED;
    820884                    }
    821885                    else if (cbWrittenTotal < (uint64_t)objData.mObjectSize)
     
    823887                        /* If we did not copy all let the user know. */
    824888                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    825                                             Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RI64 bytes transfered)"),
    826                                                        mSource.c_str(), cbWrittenTotal, objData.mObjectSize));
    827                         rc = VERR_GENERAL_FAILURE; /* Fudge. */
     889                                            Utf8StrFmt(GuestSession::tr("Copying guest file \"%s\" to host to \"%s\" failed (%RU64/%RI64 bytes transfered)"),
     890                                                       mSource.c_str(), mDest.c_str(), cbWrittenTotal, objData.mObjectSize));
     891                        rc = VERR_INTERRUPTED;
    828892                    }
    829                     else
    830                     {
    831                         ProcessStatus_T procStatus;
    832                         LONG exitCode;
    833                         if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
    834                                 && procStatus != ProcessStatus_TerminatedNormally)
    835                             || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
    836                                 && exitCode != 0)
    837                            )
    838                         {
    839                             setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    840                                                 Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %d"),
    841                                                            mSource.c_str(), procStatus, exitCode)); /**@todo Add
    842                                                                                                        stringify methods! */
    843                             rc = VERR_GENERAL_FAILURE; /* Fudge. */
    844                         }
    845                         else /* Yay, success! */
    846                             rc = setProgressSuccess();
    847                     }
     893
     894                    if (RT_SUCCESS(rc))
     895                        rc = setProgressSuccess();
    848896                }
    849897            }
     
    10981146    LogRel(("Running %s ...\n", procInfo.mName.c_str()));
    10991147
    1100     LONG exitCode;
    11011148    GuestProcessTool procTool; int guestRc;
    11021149    int vrc = procTool.Init(pSession, procInfo, false /* Async */, &guestRc);
     
    11061153            vrc = procTool.i_wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
    11071154        if (RT_SUCCESS(vrc))
    1108             vrc = procTool.i_terminatedOk(&exitCode);
     1155            vrc = procTool.i_terminatedOk();
    11091156    }
    11101157
     
    11131160        switch (vrc)
    11141161        {
    1115             case VERR_NOT_EQUAL: /** @todo Special guest control rc needed! */
     1162            case VWRN_GSTCTL_PROCESS_EXIT_CODE:
    11161163                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1117                                     Utf8StrFmt(GuestSession::tr("Running update file \"%s\" on guest terminated with exit code %ld"),
    1118                                                procInfo.mExecutable.c_str(), exitCode));
     1164                                    Utf8StrFmt(GuestSession::tr("Running update file \"%s\" on guest failed: %Rrc"),
     1165                                               procInfo.mExecutable.c_str(), procTool.i_getRc()));
    11191166                break;
    11201167
Note: See TracChangeset for help on using the changeset viewer.

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