VirtualBox

Changeset 33898 in vbox


Ignore:
Timestamp:
Nov 9, 2010 1:49:22 PM (14 years ago)
Author:
vboxsync
Message:

Guest Control/Main+VBoxManage: Implemented first bits for on-guest directory creation, added path correction based on detected guest OS.

Location:
trunk/src/VBox
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

    r33841 r33898  
    9595                 "                            --username <name> --password <password>\n"
    9696                 "                            [--dryrun] [--recursive] [--verbose] [--flags <flags>]\n"
     97                 "\n"
     98                 "                            createdirectory <vmname>|<uuid>\n"
     99                 "                            <directory to create on guest>\n"
     100                 "                            --username <name> --password <password>\n"
     101                 "                            [--parents] [--mode <mode>]\n"
    97102                 "\n"
    98103                 "                            updateadditions <vmname>|<uuid>\n"
     
    593598        return VERR_NO_MEMORY;
    594599    }
    595    
     600
    596601    pNode->Node.pPrev = NULL;
    597602    pNode->Node.pNext = NULL;
     
    12371242}
    12381243
     1244static int handleCtrlCreateDirectory(HandlerArg *a)
     1245{
     1246    /*
     1247     * Check the syntax.  We can deduce the correct syntax from the number of
     1248     * arguments.
     1249     */
     1250    if (a->argc < 2) /* At least the directory we want to create should be present :-). */
     1251        return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");
     1252
     1253    Utf8Str Utf8Directory(a->argv[1]);
     1254    Utf8Str Utf8UserName;
     1255    Utf8Str Utf8Password;
     1256    uint32_t uFlags = CreateDirectoryFlag_None;
     1257    uint32_t uMode = 0;
     1258    bool fVerbose = false;
     1259
     1260    /* Iterate through all possible commands (if available). */
     1261    bool usageOK = true;
     1262    for (int i = 3; usageOK && i < a->argc; i++)
     1263    {
     1264        if (   !strcmp(a->argv[i], "--username")
     1265            || !strcmp(a->argv[i], "--user"))
     1266        {
     1267            if (i + 1 >= a->argc)
     1268                usageOK = false;
     1269            else
     1270            {
     1271                Utf8UserName = a->argv[i + 1];
     1272                ++i;
     1273            }
     1274        }
     1275        else if (   !strcmp(a->argv[i], "--password")
     1276                 || !strcmp(a->argv[i], "--pwd"))
     1277        {
     1278            if (i + 1 >= a->argc)
     1279                usageOK = false;
     1280            else
     1281            {
     1282                Utf8Password = a->argv[i + 1];
     1283                ++i;
     1284            }
     1285        }
     1286        else if (   !strcmp(a->argv[i], "--parents")
     1287                 || !strcmp(a->argv[i], "-p"))
     1288        {
     1289            uFlags |= CreateDirectoryFlag_Parents;
     1290        }
     1291        else if (   !strcmp(a->argv[i], "--mode")
     1292                 || !strcmp(a->argv[i], "-m"))
     1293        {
     1294            if (i + 1 >= a->argc)
     1295                usageOK = false;
     1296            else
     1297            {
     1298                uMode = atoi(a->argv[i + 1]);
     1299                ++i;
     1300            }
     1301        }
     1302        else if (!strcmp(a->argv[i], "--flags"))
     1303        {
     1304            if (i + 1 >= a->argc)
     1305                usageOK = false;
     1306            else
     1307            {
     1308                /* Nothing to do here yet. */
     1309                ++i;
     1310            }
     1311        }
     1312        /** @todo Add force flag for overwriting existing stuff. */
     1313        else if (!strcmp(a->argv[i], "--verbose"))
     1314            fVerbose = true;
     1315        else
     1316            return errorSyntax(USAGE_GUESTCONTROL,
     1317                               "Invalid parameter '%s'", Utf8Str(a->argv[i]).c_str());
     1318    }
     1319
     1320    if (!usageOK)
     1321        return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");
     1322
     1323    if (Utf8Directory.isEmpty())
     1324        return errorSyntax(USAGE_GUESTCONTROL,
     1325                           "No directory specified!");
     1326
     1327    if (Utf8UserName.isEmpty())
     1328        return errorSyntax(USAGE_GUESTCONTROL,
     1329                           "No user name specified!");
     1330
     1331    /* Lookup VM. */
     1332    ComPtr<IMachine> machine;
     1333    /* Assume it's an UUID. */
     1334    HRESULT rc;
     1335    CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
     1336                                           machine.asOutParam()));
     1337    if (FAILED(rc))
     1338        return 1;
     1339
     1340    /* Machine is running? */
     1341    MachineState_T machineState;
     1342    CHECK_ERROR_RET(machine, COMGETTER(State)(&machineState), 1);
     1343    if (machineState != MachineState_Running)
     1344    {
     1345        RTMsgError("Machine \"%s\" is not running!\n", a->argv[0]);
     1346        return 1;
     1347    }
     1348
     1349    /* Open a session for the VM. */
     1350    CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
     1351
     1352    do
     1353    {
     1354        /* Get the associated console. */
     1355        ComPtr<IConsole> console;
     1356        CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
     1357        /* ... and session machine */
     1358        ComPtr<IMachine> sessionMachine;
     1359        CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
     1360
     1361        ComPtr<IGuest> guest;
     1362        CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
     1363
     1364        ComPtr<IProgress> progress;
     1365        rc = guest->CreateDirectory(Bstr(Utf8Directory).raw(),
     1366                                    Bstr(Utf8UserName).raw(), Bstr(Utf8Password).raw(),
     1367                                    uMode, uFlags, progress.asOutParam());
     1368        if (FAILED(rc))
     1369        {
     1370            /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way
     1371             * because it contains more accurate info about what went wrong. */
     1372            ErrorInfo info(guest, COM_IIDOF(IGuest));
     1373            if (info.isFullAvailable())
     1374            {
     1375                if (rc == VBOX_E_IPRT_ERROR)
     1376                    RTMsgError("%ls.", info.getText().raw());
     1377                else
     1378                    RTMsgError("%ls (%Rhrc).", info.getText().raw(), info.getResultCode());
     1379            }
     1380        }
     1381        else
     1382        {
     1383            /* Setup signal handling if cancelable. */
     1384            ASSERT(progress);
     1385            bool fCanceledAlready = false;
     1386            BOOL fCancelable;
     1387            HRESULT hrc = progress->COMGETTER(Cancelable)(&fCancelable);
     1388            if (FAILED(hrc))
     1389                fCancelable = FALSE;
     1390            if (fCancelable)
     1391            {
     1392                signal(SIGINT,   ctrlCopySignalHandler);
     1393        #ifdef SIGBREAK
     1394                signal(SIGBREAK, ctrlCopySignalHandler);
     1395        #endif
     1396            }
     1397
     1398            /* Wait for process to exit ... */
     1399            BOOL fCompleted = FALSE;
     1400            BOOL fCanceled = FALSE;
     1401            while (   SUCCEEDED(progress->COMGETTER(Completed(&fCompleted)))
     1402                   && !fCompleted)
     1403            {
     1404                /* Process async cancelation */
     1405                if (g_fCopyCanceled && !fCanceledAlready)
     1406                {
     1407                    hrc = progress->Cancel();
     1408                    if (SUCCEEDED(hrc))
     1409                        fCanceledAlready = TRUE;
     1410                    else
     1411                        g_fCopyCanceled = false;
     1412                }
     1413
     1414                /* Progress canceled by Main API? */
     1415                if (   SUCCEEDED(progress->COMGETTER(Canceled(&fCanceled)))
     1416                    && fCanceled)
     1417                {
     1418                    break;
     1419                }
     1420            }
     1421
     1422            /* Undo signal handling */
     1423            if (fCancelable)
     1424            {
     1425                signal(SIGINT,   SIG_DFL);
     1426        #ifdef SIGBREAK
     1427                signal(SIGBREAK, SIG_DFL);
     1428        #endif
     1429            }
     1430
     1431            if (fCanceled)
     1432            {
     1433                //RTPrintf("Copy operation canceled!\n");
     1434            }
     1435            else if (   fCompleted
     1436                     && SUCCEEDED(rc))
     1437            {
     1438                LONG iRc = false;
     1439                CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
     1440                if (FAILED(iRc))
     1441                {
     1442                    com::ProgressErrorInfo info(progress);
     1443                    if (   info.isFullAvailable()
     1444                        || info.isBasicAvailable())
     1445                    {
     1446                        /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way
     1447                         * because it contains more accurate info about what went wrong. */
     1448                        if (info.getResultCode() == VBOX_E_IPRT_ERROR)
     1449                            RTMsgError("%ls.", info.getText().raw());
     1450                        else
     1451                        {
     1452                            RTMsgError("Copy operation error details:");
     1453                            GluePrintErrorInfo(info);
     1454                        }
     1455                    }
     1456                }
     1457            }
     1458        }
     1459
     1460        a->session->UnlockMachine();
     1461    } while (0);
     1462    return SUCCEEDED(rc) ? 0 : 1;
     1463}
     1464
    12391465static int handleCtrlUpdateAdditions(HandlerArg *a)
    12401466{
     
    13881614        return handleCtrlExecProgram(&arg);
    13891615    }
    1390     else if (!strcmp(a->argv[0], "copyto"))
     1616    else if (   !strcmp(a->argv[0], "copyto")
     1617             || !strcmp(a->argv[0], "cp"))
    13911618    {
    13921619        return handleCtrlCopyTo(&arg);
     1620    }
     1621    else if (   !strcmp(a->argv[0], "createdirectory")
     1622             || !strcmp(a->argv[0], "createdir")
     1623             || !strcmp(a->argv[0], "mkdir"))
     1624    {
     1625        return handleCtrlCreateDirectory(&arg);
    13931626    }
    13941627    else if (   !strcmp(a->argv[0], "updateadditions")
  • trunk/src/VBox/Main/GuestImpl.cpp

    r33776 r33898  
    23162316                    if (RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", Utf8Dest.c_str()))
    23172317                    {
     2318                        /*
     2319                         * Normalize path slashes, based on the detected guest.
     2320                         */
     2321                        Utf8Str osType = mData.mOSTypeId;
     2322                        if (   osType.contains("Microsoft", Utf8Str::CaseInsensitive)
     2323                            || osType.contains("Windows", Utf8Str::CaseInsensitive))
     2324                        {
     2325                            /* We have a Windows guest. */
     2326                            RTPathChangeToDosSlashes(szOutput, true /* Force conversion. */);
     2327                        }
     2328                        else /* ... or something which isn't from Redmond ... */
     2329                        {
     2330                            RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */);
     2331                        }
     2332
    23182333                        args.push_back(Bstr(VBOXSERVICE_TOOL_CAT).raw()); /* The actual (internal) tool to use (as argv[0]). */
    23192334                        args.push_back(Bstr(szOutput).raw());             /* We want to write a file ... */
     
    23262341                    if (SUCCEEDED(rc))
    23272342                    {
    2328                         LogRel(("Copying file \"%s\" to guest \"%s\" ...\n",
    2329                                 Utf8Source.c_str(), Utf8Dest.c_str()));
     2343                        LogRel(("Copying file \"%s\" to guest \"%s\" (%u bytes) ...\n",
     2344                                Utf8Source.c_str(), Utf8Dest.c_str(), cbSize));
    23302345                        /*
    23312346                         * Okay, since we gathered all stuff we need until now to start the
     
    23892404                }
    23902405                RTFileClose(fileSource);
     2406            }
     2407        }
     2408    }
     2409    catch (std::bad_alloc &)
     2410    {
     2411        rc = E_OUTOFMEMORY;
     2412    }
     2413    return rc;
     2414#endif /* VBOX_WITH_GUEST_CONTROL */
     2415}
     2416
     2417STDMETHODIMP Guest::CreateDirectory(IN_BSTR aDirectory,
     2418                                    IN_BSTR aUserName, IN_BSTR aPassword,
     2419                                    ULONG aMode, ULONG aFlags,
     2420                                    IProgress **aProgress)
     2421{
     2422#ifndef VBOX_WITH_GUEST_CONTROL
     2423    ReturnComNotImplemented();
     2424#else  /* VBOX_WITH_GUEST_CONTROL */
     2425    using namespace guestControl;
     2426
     2427    CheckComArgStrNotEmptyOrNull(aDirectory);
     2428
     2429    /* Do not allow anonymous executions (with system rights). */
     2430    if (RT_UNLIKELY((aUserName) == NULL || *(aUserName) == '\0'))
     2431        return setError(E_INVALIDARG, tr("No user name specified"));
     2432
     2433    LogRel(("Creating guest directory \"%s\" as  user \"%s\" ...\n",
     2434            Utf8Str(aDirectory).c_str(), Utf8Str(aUserName).c_str()));
     2435
     2436    return createDirectoryInternal(aDirectory,
     2437                                   aUserName, aPassword,
     2438                                   aMode, aFlags, aProgress, NULL /* rc */);
     2439#endif
     2440}
     2441
     2442STDMETHODIMP Guest::createDirectoryInternal(IN_BSTR aDirectory,
     2443                                            IN_BSTR aUserName, IN_BSTR aPassword,
     2444                                            ULONG aMode, ULONG aFlags,
     2445                                            IProgress **aProgress, int *pRC)
     2446{
     2447#ifndef VBOX_WITH_GUEST_CONTROL
     2448    ReturnComNotImplemented();
     2449#else /* VBOX_WITH_GUEST_CONTROL */
     2450    using namespace guestControl;
     2451
     2452    CheckComArgStrNotEmptyOrNull(aDirectory);
     2453    CheckComArgOutPointerValid(aProgress);
     2454
     2455    AutoCaller autoCaller(this);
     2456    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     2457
     2458    /* Validate flags. */
     2459    if (aFlags != CreateDirectoryFlag_None)
     2460    {
     2461        if (!(aFlags & CreateDirectoryFlag_Parents))
     2462        {
     2463            return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
     2464        }
     2465    }
     2466
     2467    HRESULT rc = S_OK;
     2468
     2469    try
     2470    {
     2471        Utf8Str Utf8Directory(aDirectory);
     2472        Utf8Str Utf8UserName(aUserName);
     2473        Utf8Str Utf8Password(aPassword);
     2474
     2475        com::SafeArray<IN_BSTR> args;
     2476        com::SafeArray<IN_BSTR> env;
     2477
     2478        /*
     2479         * Prepare tool command line.
     2480         */
     2481        args.push_back(Bstr(VBOXSERVICE_TOOL_CAT).raw()); /* The actual (internal) tool to use (as argv[0]). */
     2482        if (aFlags & CreateDirectoryFlag_Parents)
     2483            args.push_back(Bstr("--parents").raw());      /* We also want to create the parent directories. */
     2484        if (aMode > 0)
     2485        {
     2486            args.push_back(Bstr("--mode").raw());         /* Set the creation mode. */
     2487
     2488            char szMode[16];
     2489            if (RTStrPrintf(szMode, sizeof(szMode), "%o", aMode))
     2490                args.push_back(Bstr(szMode).raw());
     2491            else
     2492                rc = setError(VBOX_E_IPRT_ERROR, tr("Error preparing command line"));
     2493        }
     2494        args.push_back(Bstr(Utf8Directory).raw());  /* The directory we want to create. */
     2495
     2496        /*
     2497         * Execute guest process.
     2498         */
     2499        ComPtr<IProgress> execProgress;
     2500        ULONG uPID;
     2501        if (SUCCEEDED(rc))
     2502        {
     2503            rc = ExecuteProcess(Bstr(VBOXSERVICE_TOOL_CAT).raw(),
     2504                                ExecuteProcessFlag_None,
     2505                                ComSafeArrayAsInParam(args),
     2506                                ComSafeArrayAsInParam(env),
     2507                                Bstr(Utf8UserName).raw(),
     2508                                Bstr(Utf8Password).raw(),
     2509                                5 * 1000 /* Wait 5s for getting the process started. */,
     2510                                &uPID, execProgress.asOutParam());
     2511        }
     2512
     2513        if (SUCCEEDED(rc))
     2514        {
     2515            /* Wait for process to exit ... */
     2516            BOOL fCompleted = FALSE;
     2517            BOOL fCanceled = FALSE;
     2518
     2519            while (   SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted)))
     2520                   && !fCompleted)
     2521            {
     2522                /* Progress canceled by Main API? */
     2523                if (   SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled)))
     2524                    && fCanceled)
     2525                {
     2526                    break;
     2527                }
     2528            }
     2529
     2530            if (SUCCEEDED(rc))
     2531            {
     2532                /* Return the progress to the caller. */
     2533                execProgress.queryInterfaceTo(aProgress);
    23912534            }
    23922535        }
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r33848 r33898  
    76977697  </enum>
    76987698
     7699  <enum
     7700    name="CreateDirectoryFlag"
     7701    uuid="26ff5bdd-c81f-4304-857b-b8be5e3f9cd6"
     7702  >
     7703    <desc>
     7704      Directory creation flags.
     7705    </desc>
     7706
     7707    <const name="None"                    value="0">
     7708      <desc>No flag set.</desc>
     7709    </const>
     7710
     7711    <const name="Parents"                 value="1">
     7712      <desc>No error if existing, make parent directories as needed.</desc>
     7713    </const>
     7714  </enum>
     7715
    76997716  <interface
    77007717     name="IGuest" extends="$unknown"
    7701      uuid="ded6983f-5c81-4bf9-90af-73f65fd9b728"
     7718     uuid="1039b0cc-9bc1-4c6d-8d12-864aa48aa5b9"
    77027719     wsmap="managed"
    77037720     >
     
    80238040        <desc>
    80248041          Copy flags.
     8042        </desc>
     8043      </param>
     8044      <param name="progress" type="IProgress" dir="return">
     8045        <desc>Progress object to track the operation completion.</desc>
     8046      </param>
     8047    </method>
     8048
     8049    <method name="createDirectory">
     8050      <desc>
     8051        Creates a directory on the guest.
     8052
     8053        <result name="VBOX_E_IPRT_ERROR">
     8054          Error while creating directory.
     8055        </result>
     8056
     8057      </desc>
     8058      <param name="directory" type="wstring" dir="in">
     8059        <desc>
     8060          Directory to create.
     8061        </desc>
     8062      </param>
     8063      <param name="userName" type="wstring" dir="in">
     8064        <desc>
     8065          User name under which the directory creation will be executed; the
     8066          user has to exist and have the appropriate rights to create the
     8067          desired directory.
     8068        </desc>
     8069      </param>
     8070      <param name="password" type="wstring" dir="in">
     8071        <desc>
     8072          Password of the user account specified.
     8073        </desc>
     8074      </param>
     8075      <param name="mode" type="unsigned long" dir="in">
     8076        <desc>
     8077          File mode.
     8078        </desc>
     8079      </param>
     8080      <param name="flags" type="unsigned long" dir="in">
     8081        <desc>
     8082          Additional flags. Not used at the moment and must be set to 0.
    80258083        </desc>
    80268084      </param>
  • trunk/src/VBox/Main/include/GuestImpl.h

    r33776 r33898  
    102102    STDMETHOD(GetProcessStatus)(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ULONG *aStatus);
    103103    STDMETHOD(CopyToGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUserName, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress);
     104    STDMETHOD(CreateDirectory)(IN_BSTR aDirectory, IN_BSTR aUserName, IN_BSTR aPassword, ULONG aMode, ULONG aFlags, IProgress **aProgress);
    104105    STDMETHOD(InternalGetStatistics)(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle,
    105106                                     ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemShared, ULONG *aMemCache,
     
    112113                                   IN_BSTR aUserName, IN_BSTR aPassword,
    113114                                   ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress, int *pRC);
     115    HRESULT createDirectoryInternal(IN_BSTR aDirectory, IN_BSTR aUserName, IN_BSTR aPassword,
     116                                    ULONG aMode, ULONG aFlags, IProgress **aProgress, int *pRC);
    114117    void setAdditionsInfo(Bstr aInterfaceVersion, VBOXOSTYPE aOsType);
    115118    void setAdditionsInfo2(Bstr aAdditionsVersion, Bstr aVersionName, Bstr aRevision);
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