VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/guestctrl/UIGuestControlInterface.cpp@ 104586

Last change on this file since 104586 was 103710, checked in by vboxsync, 9 months ago

FE/Qt: Get rid of unwanted UICommon includes across whole the GUI.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.0 KB
Line 
1/* $Id: UIGuestControlInterface.cpp 103710 2024-03-06 16:53:27Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIGuestControlInterface class implementation.
4 */
5
6/*
7 * Copyright (C) 2016-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* GUI includes: */
29#include "UIErrorString.h"
30#include "UIGuestControlInterface.h"
31
32/* COM includes: */
33#include "CFsObjInfo.h"
34#include "CGuestDirectory.h"
35#include "CGuestProcess.h"
36#include "CGuestSession.h"
37#include "CGuestFsObjInfo.h"
38
39/* Misc. includes: */
40#include <iprt/err.h>
41#include <iprt/getopt.h>
42
43
44#define GCTLCMD_COMMON_OPT_USER 999 /**< The --username option number. */
45#define GCTLCMD_COMMON_OPT_PASSWORD 998 /**< The --password option number. */
46#define GCTLCMD_COMMON_OPT_PASSWORD_FILE 997 /**< The --password-file option number. */
47#define GCTLCMD_COMMON_OPT_DOMAIN 996 /**< The --domain option number. */
48#define GCTLCMD_COMMON_OPT_SESSION_NAME 995 /**< The --sessionname option number. */
49#define GCTLCMD_COMMON_OPT_SESSION_ID 994 /**< The --sessionid option number. */
50
51#define RETURN_ERROR(strError) \
52 do { \
53 m_strStatus.append(strError); \
54 return false; \
55 } while (0)
56
57#define RETURN_MESSAGE(strMessage) \
58 do { \
59 m_strStatus.append(strMessage); \
60 return true; \
61 } while (0)
62
63#define GCTLCMD_COMMON_OPTION_DEFS() \
64 { "--username", GCTLCMD_COMMON_OPT_USER, RTGETOPT_REQ_STRING }, \
65 { "--passwordfile", GCTLCMD_COMMON_OPT_PASSWORD_FILE, RTGETOPT_REQ_STRING }, \
66 { "--password", GCTLCMD_COMMON_OPT_PASSWORD, RTGETOPT_REQ_STRING }, \
67 { "--domain", GCTLCMD_COMMON_OPT_DOMAIN, RTGETOPT_REQ_STRING }, \
68 { "--quiet", 'q', RTGETOPT_REQ_NOTHING }, \
69 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
70
71#define HANDLE_COMMON_OPTION_DEFS() \
72 case GCTLCMD_COMMON_OPT_USER: \
73 commandData.m_strUserName = ValueUnion.psz; \
74 break; \
75 case GCTLCMD_COMMON_OPT_PASSWORD: \
76 commandData.m_strPassword = ValueUnion.psz; \
77 break;
78
79/* static */ QString UIGuestControlInterface::getFsObjTypeString(KFsObjType type)
80{
81 QString strType;
82 switch(type)
83 {
84 case KFsObjType_Unknown:
85 strType = "Unknown";
86 break;
87 case KFsObjType_Fifo:
88 strType = "Fifo";
89 break;
90 case KFsObjType_DevChar:
91 strType = "DevChar";
92 break;
93 case KFsObjType_Directory:
94 strType = "Directory";
95 break;
96 case KFsObjType_DevBlock:
97 strType = "DevBlock";
98 break;
99 case KFsObjType_File:
100 strType = "File";
101 break;
102 case KFsObjType_Symlink:
103 strType = "Symlink";
104 break;
105 case KFsObjType_Socket:
106 strType = "Socket";
107 break;
108 case KFsObjType_WhiteOut:
109 strType = "WhiteOut";
110 break;
111 default:
112 strType = "Unknown";
113 break;
114 }
115 return strType;
116};
117
118QString generateErrorString(int getOptErrorCode, const RTGETOPTUNION &/*valueUnion*/)
119{
120 QString errorString;
121 // if (valueUnion.pDef)
122 // {
123 // if (valueUnion.pDef->pszLong)
124 // {
125 // errorString = QString(valueUnion.pDef->pszLong);
126 // }
127 // }
128
129 switch (getOptErrorCode)
130 {
131 case VERR_GETOPT_UNKNOWN_OPTION:
132 errorString = errorString.append("RTGetOpt: Command line option not recognized.");
133 break;
134 case VERR_GETOPT_REQUIRED_ARGUMENT_MISSING:
135 errorString = errorString.append("RTGetOpt: Command line option needs argument.");
136 break;
137 case VERR_GETOPT_INVALID_ARGUMENT_FORMAT:
138 errorString = errorString.append("RTGetOpt: Command line option has argument with bad format.");
139 break;
140 case VINF_GETOPT_NOT_OPTION:
141 errorString = errorString.append("RTGetOpt: Not an option.");
142 break;
143 case VERR_GETOPT_INDEX_MISSING:
144 errorString = errorString.append("RTGetOpt: Command line option needs an index.");
145 break;
146 default:
147 break;
148 }
149 return errorString;
150}
151
152/** Common option definitions: */
153class CommandData
154{
155public:
156 CommandData()
157 : m_bSessionIdGiven(false)
158 , m_bSessionNameGiven(false)
159 , m_bCreateParentDirectories(false){}
160 QString m_strUserName;
161 QString m_strPassword;
162 QString m_strExePath;
163 QString m_strSessionName;
164 QString m_strPath;
165 ULONG m_uSessionId;
166 QString m_strDomain;
167 bool m_bSessionIdGiven;
168 bool m_bSessionNameGiven;
169 /* Create the whole path during mkdir */
170 bool m_bCreateParentDirectories;
171 QVector<QString> m_arguments;
172 QVector<QString> m_environmentChanges;
173};
174
175UIGuestControlInterface::UIGuestControlInterface(QObject* parent, const CGuest &comGuest)
176 :QObject(parent)
177 , m_comGuest(comGuest)
178 , m_strHelp("[common-options]\t[--username <name>] [--domain <domain>]\n"
179 "\t\t[--passwordfile <file> | --password <password>]\n"
180 "start\t\t[common-options]\n"
181 "\t\t[--exe <path to executable>] [--timeout <msec>]\n"
182 "\t\t[--sessionid <id> | [sessionname <name>]]\n"
183 "\t\t[-E|--putenv <NAME>[=<VALUE>]] [--unquoted-args]\n"
184 "\t\t[--ignore-orphaned-processes] [--profile]\n"
185 "\t\t-- <program/arg0> [argument1] ... [argumentN]]\n"
186 "createsession\t\t[common-options] [--sessionname <name>]\n"
187 "mkdir\t\t[common-options]\n"
188 "\t\t[-P|--parents] [<guest directory>\n"
189 "\t\t[--sessionid <id> | --sessionname <name>]\n"
190 "stat|ls\t\t[common-options]\n"
191 "\t\t[--sessionid <id> | --sessionname <name>]\n"
192 "list\n"
193 )
194{
195 prepareSubCommandHandlers();
196}
197
198bool UIGuestControlInterface::handleMkdir(int argc , char** argv)
199{
200
201 CommandData commandData;
202
203 static const RTGETOPTDEF s_aOptions[] =
204 {
205 GCTLCMD_COMMON_OPTION_DEFS()
206 { "--sessionname", GCTLCMD_COMMON_OPT_SESSION_NAME, RTGETOPT_REQ_STRING },
207 { "--sessionid", GCTLCMD_COMMON_OPT_SESSION_ID, RTGETOPT_REQ_UINT32 },
208 { "--parents", 'P', RTGETOPT_REQ_NOTHING }
209 };
210
211 int ch;
212 bool pathFound = false;
213 RTGETOPTUNION ValueUnion;
214 RTGETOPTSTATE GetState;
215 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1 /* ignore 0th element (command) */, 0);
216 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
217 {
218 switch (ch)
219 {
220 HANDLE_COMMON_OPTION_DEFS()
221 case GCTLCMD_COMMON_OPT_SESSION_NAME:
222 commandData.m_bSessionNameGiven = true;
223 commandData.m_strSessionName = ValueUnion.psz;
224 break;
225 case GCTLCMD_COMMON_OPT_SESSION_ID:
226 commandData.m_bSessionIdGiven = true;
227 commandData.m_uSessionId = ValueUnion.i32;
228 break;
229 case 'P':
230 commandData.m_bCreateParentDirectories = true;
231 break;
232 case VINF_GETOPT_NOT_OPTION:
233 if (!pathFound)
234 {
235 commandData.m_strPath = ValueUnion.psz;
236 pathFound = true;
237 }
238 /* Allow only a single NOT_OPTION */
239 else
240 RETURN_ERROR(generateErrorString(ch, ValueUnion));
241
242 break;
243 default:
244 RETURN_ERROR(generateErrorString(ch, ValueUnion));
245 }
246 }
247 if (commandData.m_strPath.isEmpty())
248 RETURN_ERROR(QString(m_strHelp).append("Syntax error! No path is given\n"));
249
250 CGuestSession guestSession;
251 if (!findOrCreateSession(commandData, guestSession) || !guestSession.isOk())
252 return false;
253
254
255 //const QString &strErr = comProgressInstall.GetErrorInfo().GetText();
256 QVector<KDirectoryCreateFlag> creationFlags;
257 if (commandData.m_bCreateParentDirectories)
258 creationFlags.push_back(KDirectoryCreateFlag_None);
259 else
260 creationFlags.push_back(KDirectoryCreateFlag_Parents);
261
262 guestSession.DirectoryCreate(commandData.m_strPath, 0 /*ULONG aMode*/, creationFlags);
263
264 //startProcess(commandData, guestSession);
265 return true;
266}
267
268bool UIGuestControlInterface::handleStat(int argc, char** argv)
269{
270 CommandData commandData;
271
272 static const RTGETOPTDEF s_aOptions[] =
273 {
274 GCTLCMD_COMMON_OPTION_DEFS()
275 { "--sessionname", GCTLCMD_COMMON_OPT_SESSION_NAME, RTGETOPT_REQ_STRING },
276 { "--sessionid", GCTLCMD_COMMON_OPT_SESSION_ID, RTGETOPT_REQ_UINT32 }
277 };
278
279 int ch;
280 bool pathFound = false;
281 RTGETOPTUNION ValueUnion;
282 RTGETOPTSTATE GetState;
283 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1 /* ignore 0th element (command) */, 0);
284 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
285 {
286 switch (ch)
287 {
288 HANDLE_COMMON_OPTION_DEFS()
289 case GCTLCMD_COMMON_OPT_SESSION_NAME:
290 commandData.m_bSessionNameGiven = true;
291 commandData.m_strSessionName = ValueUnion.psz;
292 break;
293 case GCTLCMD_COMMON_OPT_SESSION_ID:
294 commandData.m_bSessionIdGiven = true;
295 commandData.m_uSessionId = ValueUnion.i32;
296 break;
297 case 'P':
298 commandData.m_bCreateParentDirectories = true;
299 break;
300 case VINF_GETOPT_NOT_OPTION:
301 if (!pathFound)
302 {
303 commandData.m_strPath = ValueUnion.psz;
304 pathFound = true;
305 }
306 /* Allow only a single NOT_OPTION */
307 else
308 RETURN_ERROR(generateErrorString(ch, ValueUnion));
309
310 break;
311 default:
312 RETURN_ERROR(generateErrorString(ch, ValueUnion));
313 }
314 }
315 if (commandData.m_strPath.isEmpty())
316 RETURN_ERROR(QString(m_strHelp).append("Syntax error! No path is given\n"));
317
318 CGuestSession guestSession;
319 if (!findOrCreateSession(commandData, guestSession) || !guestSession.isOk())
320 return false;
321 if (guestSession.GetStatus() != KGuestSessionStatus_Started)
322 RETURN_ERROR("The guest session is not valid");
323
324 bool isADirectory =
325 guestSession.DirectoryExists(commandData.m_strPath, false /*BOOL aFollowSymlinks*/);
326
327 bool isAFile = false;
328 if (!isADirectory)
329 isAFile = guestSession.FileExists(commandData.m_strPath, false /*BOOL aFollowSymlinks*/);
330
331 if (!isADirectory && !isAFile)
332 RETURN_ERROR("Specified object does not exist");
333
334 CGuestFsObjInfo fsObjectInfo = guestSession.FsObjQueryInfo(commandData.m_strPath, false /*BOOL aFollowSymlinks*/);
335 if (!fsObjectInfo.isOk())
336 RETURN_ERROR("Cannot get object info");
337 QString strObjectInfo = getFsObjInfoString<CGuestFsObjInfo>(fsObjectInfo);
338
339 /* In case it is a directory get a list of its content: */
340 if (isADirectory)
341 {
342 QVector<KDirectoryOpenFlag> aFlags;
343 aFlags.push_back(KDirectoryOpenFlag_None);
344 CGuestDirectory directory = guestSession.DirectoryOpen(commandData.m_strPath, /*aFilter*/ "", aFlags);
345 if (directory.isOk())
346 {
347 CFsObjInfo directoryInfo = directory.Read();
348 while (directoryInfo.isOk())
349 {
350 strObjectInfo.append("\n");
351 strObjectInfo.append(getFsObjInfoString<CFsObjInfo>(directoryInfo));
352 directoryInfo = directory.Read();
353 }
354 }
355 }
356 RETURN_MESSAGE(strObjectInfo);
357}
358
359bool UIGuestControlInterface::handleList(int, char**)
360{
361 if (!m_comGuest.isOk())
362 RETURN_ERROR("The guest session is not valid");
363
364 QString strSessionInfo;
365 QVector<CGuestSession> sessions = m_comGuest.GetSessions();
366 if (sessions.isEmpty())
367 {
368 strSessionInfo.append("No guest sessions");
369 RETURN_MESSAGE(strSessionInfo);
370 }
371 strSessionInfo += QString("Listing %1 guest sessions in total:\n").arg(QString::number(sessions.size()));
372 //strSessionInfo += QString("\t%1\t%2\n").arg("Session Name").arg("Session Id");
373
374 for (int i = 0; i < sessions.size(); ++i)
375 {
376 strSessionInfo += QString("\tName: %1\t\tID: %2\n").arg(sessions[i].GetName()).arg(QString::number(sessions[i].GetId()));
377 QVector<CGuestProcess> processes = sessions[i].GetProcesses();
378 strSessionInfo += QString("\t%1 guest prcesses for this session:\n").arg(QString::number(processes.size()));
379
380 for (int j = 0; j < processes.size(); ++j)
381 {
382 strSessionInfo += QString("\t\tName: %1\t\tID: %2\n").arg(processes[j].GetName()).arg(QString::number(processes[j].GetPID()));
383
384 }
385 }
386 RETURN_MESSAGE(strSessionInfo);
387}
388
389bool UIGuestControlInterface::handleStart(int argc, char** argv)
390{
391 enum kGstCtrlRunOpt
392 {
393 kGstCtrlRunOpt_IgnoreOrphanedProcesses = 1000,
394 kGstCtrlRunOpt_NoProfile, /** @todo Deprecated and will be removed soon; use kGstCtrlRunOpt_Profile instead, if needed. */
395 kGstCtrlRunOpt_Profile,
396 kGstCtrlRunOpt_Dos2Unix,
397 kGstCtrlRunOpt_Unix2Dos,
398 kGstCtrlRunOpt_WaitForStdOut,
399 kGstCtrlRunOpt_NoWaitForStdOut,
400 kGstCtrlRunOpt_WaitForStdErr,
401 kGstCtrlRunOpt_NoWaitForStdErr
402 };
403
404 CommandData commandData;
405
406 static const RTGETOPTDEF s_aOptions[] =
407 {
408 GCTLCMD_COMMON_OPTION_DEFS()
409 { "--sessionname", GCTLCMD_COMMON_OPT_SESSION_NAME, RTGETOPT_REQ_STRING },
410 { "--sessionid", GCTLCMD_COMMON_OPT_SESSION_ID, RTGETOPT_REQ_UINT32 },
411 { "--putenv", 'E', RTGETOPT_REQ_STRING },
412 { "--exe", 'e', RTGETOPT_REQ_STRING },
413 { "--timeout", 't', RTGETOPT_REQ_UINT32 },
414 { "--unquoted-args", 'u', RTGETOPT_REQ_NOTHING },
415 { "--ignore-orphaned-processes", kGstCtrlRunOpt_IgnoreOrphanedProcesses, RTGETOPT_REQ_NOTHING },
416 { "--no-profile", kGstCtrlRunOpt_NoProfile, RTGETOPT_REQ_NOTHING }, /** @todo Deprecated. */
417 { "--profile", kGstCtrlRunOpt_Profile, RTGETOPT_REQ_NOTHING }
418 };
419
420 int ch;
421 RTGETOPTUNION ValueUnion;
422 RTGETOPTSTATE GetState;
423 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1 /* ignore 0th element (command) */, 0);
424 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
425 {
426 switch (ch)
427 {
428 HANDLE_COMMON_OPTION_DEFS()
429 case GCTLCMD_COMMON_OPT_SESSION_NAME:
430 commandData.m_bSessionNameGiven = true;
431 commandData.m_strSessionName = ValueUnion.psz;
432 break;
433 case GCTLCMD_COMMON_OPT_SESSION_ID:
434 commandData.m_bSessionIdGiven = true;
435 commandData.m_uSessionId = ValueUnion.i32;
436 break;
437 case 'e':
438 commandData.m_strExePath = ValueUnion.psz;
439 break;
440 default:
441 RETURN_ERROR(generateErrorString(ch, ValueUnion));
442 }
443 }
444 if (commandData.m_strExePath.isEmpty())
445 RETURN_ERROR(QString(m_strHelp).append("Syntax error! No executable is given\n"));
446
447 CGuestSession guestSession;
448 if (!findOrCreateSession(commandData, guestSession) || !guestSession.isOk())
449 return false;
450 startProcess(commandData, guestSession);
451 return true;
452}
453
454bool UIGuestControlInterface::findOrCreateSession(const CommandData &commandData, CGuestSession &outGuestSession)
455{
456 if (commandData.m_bSessionNameGiven && commandData.m_strSessionName.isEmpty())
457 RETURN_ERROR(QString(m_strHelp).append("'Session Name' is not name valid\n"));
458
459 /* Check if sessionname and sessionid are both supplied */
460 if (commandData.m_bSessionIdGiven && commandData.m_bSessionNameGiven)
461 RETURN_ERROR(QString(m_strHelp).append("Both 'Session Name' and 'Session Id' are supplied\n"));
462
463 /* If sessionid is given then look for the session. if not found return without starting the process: */
464 else if (commandData.m_bSessionIdGiven && !commandData.m_bSessionNameGiven)
465 {
466 if (!findSession(commandData.m_uSessionId, outGuestSession))
467 {
468 RETURN_ERROR(QString(m_strHelp).append("No session with id %1 found.\n").arg(commandData.m_uSessionId));
469 }
470 else
471 return true;
472 }
473 /* If sessionname is given then look for the session. if not try to create a session with the provided name: */
474 else if (!commandData.m_bSessionIdGiven && commandData.m_bSessionNameGiven)
475 {
476 if (!findSession(commandData.m_strSessionName, outGuestSession))
477 {
478 if (!createSession(commandData, outGuestSession))
479 return false;
480 else
481 return true;
482 }
483 else
484 return true;
485 }
486 /* search within the existing CGuestSessions and return a valid one if found: */
487 if (findAValidGuestSession(outGuestSession))
488 return true;
489 /* if neither sessionname and session id is given then create a new session */
490 if (!createSession(commandData, outGuestSession))
491 return false;
492 return true;
493}
494
495bool UIGuestControlInterface::findAValidGuestSession(CGuestSession &outGuestSession)
496{
497 if (!m_comGuest.isOk())
498 return false;
499
500 QVector<CGuestSession> sessions = m_comGuest.GetSessions();
501 for (int i = 0; i < sessions.size(); ++i)
502 {
503 if (sessions[i].isOk() && sessions[i].GetStatus() == KGuestSessionStatus_Started)
504 {
505 outGuestSession = sessions[i];
506 return true;
507 }
508 }
509 return false;
510}
511
512bool UIGuestControlInterface::handleHelp(int, char**)
513{
514 emit sigOutputString(m_strHelp);
515 return true;
516}
517
518bool UIGuestControlInterface::handleCreateSession(int argc, char** argv)
519{
520 CommandData commandData;
521
522 static const RTGETOPTDEF s_aOptions[] =
523 {
524 GCTLCMD_COMMON_OPTION_DEFS()
525 { "--sessionname", GCTLCMD_COMMON_OPT_SESSION_NAME, RTGETOPT_REQ_STRING }
526 };
527
528 int ch;
529 RTGETOPTUNION ValueUnion;
530 RTGETOPTSTATE GetState;
531 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
532 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
533 {
534 switch (ch)
535 {
536 HANDLE_COMMON_OPTION_DEFS()
537 case GCTLCMD_COMMON_OPT_SESSION_NAME:
538 commandData.m_strSessionName = ValueUnion.psz;
539 if (commandData.m_strSessionName.isEmpty())
540 {
541 RETURN_ERROR(QString("'Session Name' is not name valid\n").append(m_strHelp));
542 }
543 break;
544 default:
545 break;
546 }
547 }
548 CGuestSession guestSession;
549 if (!createSession(commandData, guestSession))
550 return false;
551 return true;
552}
553
554bool UIGuestControlInterface::startProcess(const CommandData &commandData, CGuestSession &guestSession)
555{
556 QVector<KProcessCreateFlag> createFlags;
557 createFlags.push_back(KProcessCreateFlag_WaitForProcessStartOnly);
558 CGuestProcess process = guestSession.ProcessCreate(commandData.m_strExePath,
559 commandData.m_arguments,
560 "", /* Working directory. */
561 commandData.m_environmentChanges,
562 createFlags,
563 0);
564 if (!process.isOk())
565 return false;
566 return true;
567}
568
569UIGuestControlInterface::~UIGuestControlInterface()
570{
571}
572
573void UIGuestControlInterface::prepareSubCommandHandlers()
574{
575 m_subCommandHandlers.insert("createsession" , &UIGuestControlInterface::handleCreateSession);
576 m_subCommandHandlers.insert("start", &UIGuestControlInterface::handleStart);
577 m_subCommandHandlers.insert("help" , &UIGuestControlInterface::handleHelp);
578 m_subCommandHandlers.insert("mkdir" , &UIGuestControlInterface::handleMkdir);
579 m_subCommandHandlers.insert("stat" , &UIGuestControlInterface::handleStat);
580 m_subCommandHandlers.insert("ls" , &UIGuestControlInterface::handleStat);
581 m_subCommandHandlers.insert("list" , &UIGuestControlInterface::handleList);
582}
583
584void UIGuestControlInterface::putCommand(const QString &strCommand)
585{
586 if (!isGuestAdditionsAvailable(m_comGuest, "6.1"))
587 {
588 emit sigOutputString("No guest addtions detected. Guest control requires guest additions");
589 return;
590 }
591
592 char **argv;
593 int argc;
594 QByteArray array = strCommand.toLocal8Bit();
595 RTGetOptArgvFromString(&argv, &argc, array.data(), RTGETOPTARGV_CNV_QUOTE_BOURNE_SH, 0);
596 m_strStatus.clear();
597 static const RTGETOPTDEF s_aOptions[] =
598 {
599 GCTLCMD_COMMON_OPTION_DEFS()
600 };
601
602 int ch;
603 RTGETOPTUNION ValueUnion;
604 RTGETOPTSTATE GetState;
605 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
606 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
607 {
608 switch (ch)
609 {
610 case VINF_GETOPT_NOT_OPTION:
611 {
612 /* Try to map ValueUnion.psz to a sub command handler: */
613 QString strNoOption(ValueUnion.psz);
614 if (!strNoOption.isNull())
615 {
616 QMap<QString, HandleFuncPtr>::iterator iterator =
617 m_subCommandHandlers.find(strNoOption);
618 if (iterator != m_subCommandHandlers.end())
619 {
620 (this->*(iterator.value()))(argc, argv);
621 RTGetOptArgvFree(argv);
622 if (!m_strStatus.isEmpty())
623 emit sigOutputString(m_strStatus);
624 return;
625 }
626 else
627 {
628 emit sigOutputString(QString(m_strHelp).append("\nSyntax Error. Unknown Command '%1'").arg(ValueUnion.psz));
629 RTGetOptArgvFree(argv);
630 return;
631 }
632 }
633 break;
634 }
635 default:
636 break;
637 }
638 }
639 if (!m_strStatus.isEmpty())
640 emit sigOutputString(m_strStatus);
641
642 RTGetOptArgvFree(argv);
643}
644
645bool UIGuestControlInterface::findSession(ULONG sessionId, CGuestSession& outSession)
646{
647 if (!m_comGuest.isOk())
648 return false;
649 QVector<CGuestSession> sessionVector = m_comGuest.GetSessions();
650 if (sessionVector.isEmpty())
651 return false;
652 for (int i = 0; i < sessionVector.size(); ++i)
653 {
654 if (sessionVector.at(i).isOk() && sessionId == sessionVector.at(i).GetId())
655 {
656 outSession = sessionVector.at(i);
657 return true;
658 }
659 }
660 return false;
661}
662
663bool UIGuestControlInterface::findSession(const QString& strSessionName, CGuestSession& outSession)
664{
665 if (!m_comGuest.isOk())
666 return false;
667 QVector<CGuestSession> sessionVector = m_comGuest.FindSession(strSessionName);
668 if (sessionVector.isEmpty())
669 return false;
670 /* Return the first session with @a sessionName */
671 outSession = sessionVector.at(0);
672 return false;
673}
674
675bool UIGuestControlInterface::createSession(const CommandData &commandData, CGuestSession& outSession)
676{
677 if (!m_comGuest.isOk())
678 return false;
679 if (commandData.m_strUserName.isEmpty())
680 RETURN_ERROR("No user name has been given");
681 CGuestSession guestSession = m_comGuest.CreateSession(commandData.m_strUserName,
682 commandData.m_strPassword,
683 commandData.m_strDomain,
684 commandData.m_strSessionName);
685
686 if (!guestSession.isOk())
687 return false;
688
689 /* Wait session to start: */
690 const ULONG waitTimeout = 2000;
691 KGuestSessionWaitResult waitResult = guestSession.WaitFor(KGuestSessionWaitForFlag_Start, waitTimeout);
692 if (waitResult != KGuestSessionWaitResult_Start)
693 return false;
694
695 outSession = guestSession;
696 return true;
697}
698
699/* static */
700bool UIGuestControlInterface::isGuestAdditionsAvailable(const CGuest &guest, const char *pszMinimumVersion)
701{
702 CGuest guestNonConst = const_cast<CGuest&>(guest);
703
704 if (guestNonConst.isNull() || !pszMinimumVersion)
705 return false;
706
707 /* Guest control stuff is in userland: */
708 if (!guestNonConst.GetAdditionsStatus(KAdditionsRunLevelType_Userland))
709 return false;
710
711 if (!guestNonConst.isOk())
712 return false;
713
714 /* Check the related GA facility: */
715 LONG64 iLastUpdatedIgnored;
716 if (guestNonConst.GetFacilityStatus(KAdditionsFacilityType_VBoxService, iLastUpdatedIgnored) != KAdditionsFacilityStatus_Active)
717 return false;
718
719 if (!guestNonConst.isOk())
720 return false;
721
722 QString strGAVersion = guestNonConst.GetAdditionsVersion();
723 if (guestNonConst.isOk())
724 return (RTStrVersionCompare(strGAVersion.toUtf8().constData(), pszMinimumVersion) >= 0);
725
726 return false;
727}
728
729template<typename T>
730QString UIGuestControlInterface::getFsObjInfoString(const T &fsObjectInfo) const
731{
732 QString strObjectInfo;
733 if (!fsObjectInfo.isOk())
734 return strObjectInfo;
735
736 strObjectInfo.append(getFsObjTypeString(fsObjectInfo.GetType()).append("\t"));
737 strObjectInfo.append(fsObjectInfo.GetName().append("\t"));
738 strObjectInfo.append(QString::number(fsObjectInfo.GetObjectSize()).append("\t"));
739
740 /* Currently I dont know a way to convert these into a meaningful date/time: */
741 // strObjectInfo.append("BirthTime", QString::number(fsObjectInfo.GetBirthTime()));
742 // strObjectInfo.append("ChangeTime", QString::number(fsObjectInfo.GetChangeTime()));
743
744 return strObjectInfo;
745}
Note: See TracBrowser for help on using the repository browser.

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